dmitrysoshnikov / babel-plugin-transform-modern-regexp Goto Github PK
View Code? Open in Web Editor NEWBabel plugin for modern RegExp features in JavaScript
License: MIT License
Babel plugin for modern RegExp features in JavaScript
License: MIT License
Code:
'use strict'
let testString = 'foo:napp2019'
const regex = /(?<p>\w+):(?<name>\w+)(?<year>\d+)/ui
let res = regex.exec(testString)
console.log(res.groups.year)
console.log(res.groups.p)
console.log(res.groups.name)
console.log(regex.test(testString))
Result:
> [email protected] test /Users/nappdev/projects/bugz/babel-plugin-transform-modern-regexp
> babel --plugins transform-modern-regexp -o compiled.js script.js && node compiled.js
/Users/nappdev/projects/bugz/babel-plugin-transform-modern-regexp/compiled.js:8
console.log(res.groups.year);
^
TypeError: Cannot read property 'year' of undefined
at Object.<anonymous> (/Users/nappdev/projects/bugz/babel-plugin-transform-modern-regexp/compiled.js:8:24)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:191:16)
at bootstrap_node.js:612:3
npm ERR! Test failed. See above for more details.
An example project for this issue is available here: https://github.com/dotnetCarpenter/bug-babel-plugin-transform-modern-regexp
By default we use natural "double-escaping" of meta-char per JS.
E.g.:
new RegExp(`\\d+`);
Instead of:
new RegExp(`\d+`);
This is a standard JS way, however the second approach looks much cleaner, and correlates with the syntax in regexp literals: /\d+/
.
We can easily implement the second approach: for this we should use raw
value of a template string, instead of cooked
value, which we use now.
To see the difference between raw
, and cooked
values, check this example in AST explorer.
I.e. for the template string:
`\n\d`
We get the following values:
{
"raw": "\\n\\d",
"cooked": "\nd"
}
So the raw
value directly corresponds to the auto doubly-escaped values which we need.
However, there is an issue with \1
, ... \7
values: they are disallowed in template strings (as Octal numbers). And these values can normally be used in regexes as backreferences to captured groups.
Therefore, we can enable the single-escape mode (using raw
value), but still require to escape reference with \\1
, etc. This brings slight inconsistency, however, not often one needs to backreference in regexes, and the convenience of using \d+
instead of \\d+
overweights it. Technically, we'll need to replace \\\\1
to \\1
in the raw
value for such numbers.
Since this is "unnatural" way for JS strings (but still much more convenient than default way), we can enabled this behind a transform option singleEspaceMeta
.
NOTE: this is mostly for spec-compatibility; practically regexes can be used without runtime
As the comments says, a transform can accept includeRuntime
option (which is currently disabled).
If the option is passed, regexes are wrapped into RegExpTree
wrapper, and provide extra functionality at runtime (e.g. accessing captured named groups on matched result).
The runtime implementation already exists, we need to pull it into a separate package, which can be auto-required by the transform.
const re = new RegExp(`
# A regular expression for date.
(?<year>\\d{4})- # year part of a date
(?<month>\\d{2})- # month part of a date
(?<day>\\d{2}) # day part of a date
`, 'x');
const result = re.exec('2017-04-17');
console.log(result.groups.year); // 2017
Is translated into:
// Auto-require `regexp-tree-runtime`, it should be in the dependencies.
const RegExpTree = require('regexp-tree-runtime');
...
const re = new RegExpTree(/(\d{4})-(\d{2})-(\d{2})/, {
flags: 'x',
source: <original-source>,
groups: {
year: 1,
month: 2,
day: 3,
},
});
const result = re.exec('2017-04-17');
console.log(result.groups.year); // 2017
I'm trying to transpile the following (I just added this plugins to babel plugins array):
export const templateToRegexp = template => {
let pattern = template;
pattern = pattern.replace(/\/:(?<param>[\w\d]+?)(?=\/|$)/gi, '\\/(?<$<param>>[\\w\\d]+?)(?=\\/|$)');
pattern = pattern.replace(/\/:(?<param>[\w\d]+?)\?/gi, '(\\/(?<=\\/)(?<$<param>>[\\w\\d]+?)(?=\\/|$))?');
pattern = '^' + pattern + '$';
const regexp = new RegExp(pattern, 'i');
return regexp;
};
But I get:
SyntaxError:
/[.*+?^${}()|[\]\\]/g
^
Unexpected token: "|" at 1:12.
Is there some syntax error in the regexps I'm trying to transpile?
Note: everything works on Chrome.
As seen here.
The compat-transpiler from regexp-tree accepts a whitelist of transforms to apply, so this can be used for the same purposes on the Babel plugin (per request).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.