Improve code quality and write tests

This commit is contained in:
Shivam Mathur
2019-09-20 08:11:20 +05:30
parent db44db4b97
commit 43178a7254
3597 changed files with 255478 additions and 785554 deletions

View File

@ -0,0 +1,50 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
'use strict';
var compatTransforms = require('./transforms');
var _transform = require('../transform');
module.exports = {
/**
* Translates a regexp in new syntax to equivalent regexp in old syntax.
*
* @param string|RegExp|AST - regexp
* @param Array transformsWhitelist - names of the transforms to apply
*/
transform: function transform(regexp) {
var transformsWhitelist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var transformToApply = transformsWhitelist.length > 0 ? transformsWhitelist : Object.keys(compatTransforms);
var result = void 0;
// Collect extra data per transform.
var extra = {};
transformToApply.forEach(function (transformName) {
if (!compatTransforms.hasOwnProperty(transformName)) {
throw new Error('Unknown compat-transform: ' + transformName + '. ' + 'Available transforms are: ' + Object.keys(compatTransforms).join(', '));
}
var handler = compatTransforms[transformName];
result = _transform.transform(regexp, handler);
regexp = result.getAST();
// Collect `extra` transform result.
if (typeof handler.getExtra === 'function') {
extra[transformName] = handler.getExtra();
}
});
// Set the final extras for all transforms.
result.setExtra(extra);
return result;
}
};

View File

@ -0,0 +1,123 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
'use strict';
/**
* The `RegExpTree` class provides runtime support for `compat-transpiler`
* module from `regexp-tree`.
*
* E.g. it tracks names of the capturing groups, in order to access the
* names on the matched result.
*
* It's a thin-wrapper on top of original regexp.
*/
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var RegExpTree = function () {
/**
* Initializes a `RegExpTree` instance.
*
* @param RegExp - a regular expression
*
* @param Object state:
*
* An extra state which may store any related to transformation
* data, for example, names of the groups.
*
* - flags - original flags
* - groups - names of the groups, and their indices
* - source - original source
*/
function RegExpTree(re, _ref) {
var flags = _ref.flags,
groups = _ref.groups,
source = _ref.source;
_classCallCheck(this, RegExpTree);
this._re = re;
this._groups = groups;
// Original props.
this.flags = flags;
this.source = source || re.source;
this.dotAll = flags.includes('s');
// Inherited directly from `re`.
this.global = re.global;
this.ignoreCase = re.ignoreCase;
this.multiline = re.multiline;
this.sticky = re.sticky;
this.unicode = re.unicode;
}
/**
* Facade wrapper for RegExp `test` method.
*/
_createClass(RegExpTree, [{
key: 'test',
value: function test(string) {
return this._re.test(string);
}
/**
* Facade wrapper for RegExp `compile` method.
*/
}, {
key: 'compile',
value: function compile(string) {
return this._re.compile(string);
}
/**
* Facade wrapper for RegExp `toString` method.
*/
}, {
key: 'toString',
value: function toString() {
if (!this._toStringResult) {
this._toStringResult = '/' + this.source + '/' + this.flags;
}
return this._toStringResult;
}
/**
* Facade wrapper for RegExp `exec` method.
*/
}, {
key: 'exec',
value: function exec(string) {
var result = this._re.exec(string);
if (!this._groups || !result) {
return result;
}
result.groups = {};
for (var group in this._groups) {
var groupNumber = this._groups[group];
result.groups[group] = result[groupNumber];
}
return result;
}
}]);
return RegExpTree;
}();
module.exports = {
RegExpTree: RegExpTree
};

View File

@ -0,0 +1,69 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
'use strict';
/**
* A regexp-tree plugin to translate `/./s` to `/[\0-\uFFFF]/`.
*/
module.exports = {
// Whether `u` flag present. In which case we transform to
// \u{10FFFF} instead of \uFFFF.
_hasUFlag: false,
// Only run this plugin if we have `s` flag.
shouldRun: function shouldRun(ast) {
var shouldRun = ast.flags.includes('s');
if (!shouldRun) {
return false;
}
// Strip the `s` flag.
ast.flags = ast.flags.replace('s', '');
// Whether we have also `u`.
this._hasUFlag = ast.flags.includes('u');
return true;
},
Char: function Char(path) {
var node = path.node;
if (node.kind !== 'meta' || node.value !== '.') {
return;
}
var toValue = '\\uFFFF';
var toSymbol = '\uFFFF';
if (this._hasUFlag) {
toValue = '\\u{10FFFF}';
toSymbol = '\uDBFF\uDFFF';
}
path.replace({
type: 'CharacterClass',
expressions: [{
type: 'ClassRange',
from: {
type: 'Char',
value: '\\0',
kind: 'decimal',
symbol: '\0'
},
to: {
type: 'Char',
value: toValue,
kind: 'unicode',
symbol: toSymbol
}
}]
});
}
};

View File

@ -0,0 +1,59 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
'use strict';
/**
* A regexp-tree plugin to translate `/(?<name>a)\k<name>/` to `/(a)\1/`.
*/
module.exports = {
// To track the names of the groups, and return them
// in the transform result state.
//
// A map from name to number: {foo: 2, bar: 4}
_groupNames: {},
/**
* Initialises the trasnform.
*/
init: function init() {
this._groupNames = {};
},
/**
* Returns extra state, which eventually is returned to
*/
getExtra: function getExtra() {
return this._groupNames;
},
Group: function Group(path) {
var node = path.node;
if (!node.name) {
return;
}
// Record group name.
this._groupNames[node.name] = node.number;
delete node.name;
delete node.nameRaw;
},
Backreference: function Backreference(path) {
var node = path.node;
if (node.kind !== 'name') {
return;
}
node.kind = 'number';
node.reference = node.number;
delete node.referenceRaw;
}
};

View File

@ -0,0 +1,23 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
'use strict';
/**
* A regexp-tree plugin to remove `x` flag `/foo/x` to `/foo/`.
*
* Note: other features of `x` flags (whitespace, comments) are
* already removed at parsing stage.
*/
module.exports = {
RegExp: function RegExp(_ref) {
var node = _ref.node;
if (node.flags.includes('x')) {
node.flags = node.flags.replace('x', '');
}
}
};

View File

@ -0,0 +1,17 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
'use strict';
module.exports = {
// "dotAll" `s` flag
dotAll: require('./compat-dotall-s-transform'),
// Named capturing groups.
namedCapturingGroups: require('./compat-named-capturing-groups-transform'),
// `x` flag
xFlag: require('./compat-x-flag-transform')
};