1 | 'use strict';
|
2 | const cleanRegexp = require('clean-regexp');
|
3 | const {optimize} = require('regexp-tree');
|
4 | const getDocumentationUrl = require('./utils/get-documentation-url');
|
5 | const quoteString = require('./utils/quote-string');
|
6 |
|
7 | const message = '{{original}} can be optimized to {{optimized}}';
|
8 |
|
9 | const create = context => {
|
10 | const {sortCharacterClasses} = context.options[0] || {};
|
11 |
|
12 | const blacklist = [];
|
13 |
|
14 | if (sortCharacterClasses === false) {
|
15 | blacklist.push('charClassClassrangesMerge');
|
16 | }
|
17 |
|
18 | return {
|
19 | 'Literal[regex]': node => {
|
20 | const {raw: original, regex} = node;
|
21 |
|
22 |
|
23 |
|
24 | if (regex.flags.includes('u')) {
|
25 | return;
|
26 | }
|
27 |
|
28 | let optimized = original;
|
29 |
|
30 | try {
|
31 | optimized = optimize(original, undefined, {blacklist}).toString();
|
32 | } catch {}
|
33 |
|
34 | if (original === optimized) {
|
35 | return;
|
36 | }
|
37 |
|
38 | context.report({
|
39 | node,
|
40 | message,
|
41 | data: {
|
42 | original,
|
43 | optimized
|
44 | },
|
45 | fix: fixer => fixer.replaceText(node, optimized)
|
46 | });
|
47 | },
|
48 | 'NewExpression[callee.type="Identifier"][callee.name="RegExp"][arguments.length>=1][arguments.0.type="Literal"]': node => {
|
49 | const [patternNode, flagsNode] = node.arguments;
|
50 |
|
51 | if (typeof patternNode.value !== 'string') {
|
52 | return;
|
53 | }
|
54 |
|
55 | const oldPattern = patternNode.value;
|
56 | const flags = flagsNode &&
|
57 | flagsNode.type === 'Literal' &&
|
58 | typeof flagsNode.value === 'string' ?
|
59 | flagsNode.value :
|
60 | '';
|
61 |
|
62 | const newPattern = cleanRegexp(oldPattern, flags);
|
63 |
|
64 | if (oldPattern !== newPattern) {
|
65 | context.report({
|
66 | node,
|
67 | message,
|
68 | data: {
|
69 | original: oldPattern,
|
70 | optimized: newPattern
|
71 | },
|
72 | fix: fixer => fixer.replaceText(
|
73 | patternNode,
|
74 | quoteString(newPattern)
|
75 | )
|
76 | });
|
77 | }
|
78 | }
|
79 | };
|
80 | };
|
81 |
|
82 | const schema = [
|
83 | {
|
84 | type: 'object',
|
85 | properties: {
|
86 | sortCharacterClasses: {
|
87 | type: 'boolean',
|
88 | default: true
|
89 | }
|
90 | }
|
91 | }
|
92 | ];
|
93 |
|
94 | module.exports = {
|
95 | create,
|
96 | meta: {
|
97 | type: 'suggestion',
|
98 | docs: {
|
99 | url: getDocumentationUrl(__filename)
|
100 | },
|
101 | fixable: 'code',
|
102 | schema
|
103 | }
|
104 | };
|