[Pkg-javascript-commits] [node-regexpu-core] 01/02: New upstream version 4.1.2+ds

Julien Puydt julien.puydt at laposte.net
Sat Sep 9 16:44:54 UTC 2017


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-regexpu-core.

commit a53bb2da9f8e2bd3584b4407977ddcd2bada3371
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Sat Sep 9 18:24:09 2017 +0200

    New upstream version 4.1.2+ds
---
 .editorconfig                          |   12 +
 .gitattributes                         |    2 +
 .gitignore                             |   17 +
 .travis.yml                            |   17 +
 LICENSE-MIT.txt                        |   20 +
 README.md                              |  109 +++
 package-lock.json                      | 1257 ++++++++++++++++++++++++++++++++
 package.json                           |   68 ++
 property-escapes.md                    |  330 +++++++++
 rewrite-pattern.js                     |  270 +++++++
 scripts/character-class-escape-sets.js |  135 ++++
 scripts/iu-mappings.js                 |  179 +++++
 tests/tests.js                         |  760 +++++++++++++++++++
 13 files changed, 3176 insertions(+)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..6f9f40f
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = tab
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[{README.md,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..0a91f75
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Automatically normalize line endings for all text-based files
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..444ec4d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+# Coverage report
+coverage
+
+# Installed npm modules
+node_modules
+
+# Folder view configuration files
+.DS_Store
+Desktop.ini
+
+# Thumbnail cache files
+._*
+Thumbs.db
+
+# Files that might appear on external disks
+.Spotlight-V100
+.Trashes
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..eaf74ce
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+sudo: false
+language: node_js
+node_js:
+  - '4'
+  - '5'
+  - '6'
+  - '7'
+  - '8'
+script:
+  - 'if [ "${TRAVIS_NODE_VERSION}" = "8" ]; then
+       npm run build;
+     fi'
+  - 'npm test'
+after_script:
+  - 'istanbul cover --report html node_modules/.bin/_mocha tests -- -u exports -R spec && codecov'
+git:
+  depth: 1
diff --git a/LICENSE-MIT.txt b/LICENSE-MIT.txt
new file mode 100644
index 0000000..a41e0a7
--- /dev/null
+++ b/LICENSE-MIT.txt
@@ -0,0 +1,20 @@
+Copyright Mathias Bynens <https://mathiasbynens.be/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..45da73b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,109 @@
+# regexpu-core [![Build status](https://travis-ci.org/mathiasbynens/regexpu-core.svg?branch=master)](https://travis-ci.org/mathiasbynens/regexpu-core) [![Code coverage status](https://img.shields.io/codecov/c/github/mathiasbynens/regexpu-core.svg)](https://codecov.io/gh/mathiasbynens/regexpu-core) [![Dependency status](https://gemnasium.com/mathiasbynens/regexpu-core.svg)](https://gemnasium.com/mathiasbynens/regexpu-core)
+
+_regexpu_ is a source code transpiler that enables the use of ES6 Unicode regular expressions in JavaScript-of-today (ES5).
+
+_regexpu-core_ contains _regexpu_’s core functionality, i.e. `rewritePattern(pattern, flag)`, which enables rewriting regular expressions that make use of [the ES6 `u` flag](https://mathiasbynens.be/notes/es6-unicode-regex) into equivalent ES5-compatible regular expression patterns.
+
+## Installation
+
+To use _regexpu-core_ programmatically, install it as a dependency via [npm](https://www.npmjs.com/):
+
+```bash
+npm install regexpu-core --save
+```
+
+Then, `require` it:
+
+```js
+const rewritePattern = require('regexpu-core');
+```
+
+## API
+
+This module exports a single function named `rewritePattern`.
+
+### `rewritePattern(pattern, flags, options)`
+
+This function takes a string that represents a regular expression pattern as well as a string representing its flags, and returns an ES5-compatible version of the pattern.
+
+```js
+rewritePattern('foo.bar', 'u');
+// → 'foo(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\uDC00-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF])bar'
+
+rewritePattern('[\\u{1D306}-\\u{1D308}a-z]', 'u');
+// → '(?:[a-z]|\\uD834[\\uDF06-\\uDF08])'
+
+rewritePattern('[\\u{1D306}-\\u{1D308}a-z]', 'ui');
+// → '(?:[a-z\\u017F\\u212A]|\\uD834[\\uDF06-\\uDF08])'
+```
+
+_regexpu-core_ can rewrite non-ES6 regular expressions too, which is useful to demonstrate how their behavior changes once the `u` and `i` flags are added:
+
+```js
+// In ES5, the dot operator only matches BMP symbols:
+rewritePattern('foo.bar');
+// → 'foo(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uFFFF])bar'
+
+// But with the ES6 `u` flag, it matches astral symbols too:
+rewritePattern('foo.bar', 'u');
+// → 'foo(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\uDC00-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF])bar'
+```
+
+The optional `options` argument recognizes the following properties:
+
+#### `dotAllFlag` (default: `false`)
+
+Setting this option to `true` enables experimental support for [the `s` (`dotAll`) flag](https://github.com/mathiasbynens/es-regexp-dotall-flag).
+
+```js
+rewritePattern('.');
+// → '[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uFFFF]'
+
+rewritePattern('.', '', {
+  'dotAllFlag': true
+});
+// → '[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uFFFF]'
+
+rewritePattern('.', 's', {
+  'dotAllFlag': true
+});
+// → '[\\0-\\uFFFF]'
+
+rewritePattern('.', 'su', {
+  'dotAllFlag': true
+});
+// → '(?:[\\0-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF])'
+```
+
+#### `unicodePropertyEscape` (default: `false`)
+
+Setting this option to `true` enables [experimental support for Unicode property escapes](property-escapes.md):
+
+```js
+rewritePattern('\\p{Block=Aegean_Numbers}', 'u', {
+  'unicodePropertyEscape': true
+});
+// → '(?:\\uD800[\\uDD00-\\uDD3F])'
+```
+
+#### `useUnicodeFlag` (default: `false`)
+
+Setting this option to `true` enables the use of Unicode code point escapes of the form `\u{…}`. Note that in regular expressions, such escape sequences only work correctly when the ES6 `u` flag is set. Enabling this setting often results in more compact output, although there are cases (such as `\p{Lu}`) where it actually _increases_ the output size.
+
+```js
+rewritePattern('\\p{Block=Aegean_Numbers}', 'u', {
+  'unicodePropertyEscape': true,
+  'useUnicodeFlag': true
+});
+// → '[\\u{10100}-\\u{1013F}]'
+```
+
+## Author
+
+| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
+|---|
+| [Mathias Bynens](https://mathiasbynens.be/) |
+
+## License
+
+_regexpu-core_ is available under the [MIT](https://mths.be/mit) license.
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..660df26
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1257 @@
+{
+	"name": "regexpu-core",
+	"version": "4.1.2",
+	"lockfileVersion": 1,
+	"requires": true,
+	"dependencies": {
+		"abbrev": {
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+			"integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
+			"dev": true
+		},
+		"ajv": {
+			"version": "4.11.8",
+			"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+			"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+			"dev": true,
+			"requires": {
+				"co": "4.6.0",
+				"json-stable-stringify": "1.0.1"
+			}
+		},
+		"align-text": {
+			"version": "0.1.4",
+			"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+			"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+			"dev": true,
+			"requires": {
+				"kind-of": "3.2.2",
+				"longest": "1.0.1",
+				"repeat-string": "1.6.1"
+			}
+		},
+		"amdefine": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+			"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+			"dev": true
+		},
+		"argparse": {
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+			"integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+			"dev": true,
+			"requires": {
+				"sprintf-js": "1.0.3"
+			}
+		},
+		"argv": {
+			"version": "0.0.2",
+			"resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz",
+			"integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=",
+			"dev": true
+		},
+		"asn1": {
+			"version": "0.2.3",
+			"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+			"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
+			"dev": true
+		},
+		"assert-plus": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+			"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
+			"dev": true
+		},
+		"async": {
+			"version": "1.5.2",
+			"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+			"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+			"dev": true
+		},
+		"asynckit": {
+			"version": "0.4.0",
+			"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+			"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+			"dev": true
+		},
+		"aws-sign2": {
+			"version": "0.6.0",
+			"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+			"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
+			"dev": true
+		},
+		"aws4": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+			"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
+			"dev": true
+		},
+		"balanced-match": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+			"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+			"dev": true
+		},
+		"bcrypt-pbkdf": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+			"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"tweetnacl": "0.14.5"
+			}
+		},
+		"boom": {
+			"version": "2.10.1",
+			"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+			"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+			"dev": true,
+			"requires": {
+				"hoek": "2.16.3"
+			}
+		},
+		"brace-expansion": {
+			"version": "1.1.8",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+			"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+			"dev": true,
+			"requires": {
+				"balanced-match": "1.0.0",
+				"concat-map": "0.0.1"
+			}
+		},
+		"browser-stdout": {
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+			"integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+			"dev": true
+		},
+		"camelcase": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+			"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+			"dev": true,
+			"optional": true
+		},
+		"caseless": {
+			"version": "0.12.0",
+			"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+			"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+			"dev": true
+		},
+		"center-align": {
+			"version": "0.1.3",
+			"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+			"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"align-text": "0.1.4",
+				"lazy-cache": "1.0.4"
+			}
+		},
+		"cliui": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+			"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"center-align": "0.1.3",
+				"right-align": "0.1.3",
+				"wordwrap": "0.0.2"
+			},
+			"dependencies": {
+				"wordwrap": {
+					"version": "0.0.2",
+					"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+					"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+					"dev": true,
+					"optional": true
+				}
+			}
+		},
+		"co": {
+			"version": "4.6.0",
+			"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+			"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+			"dev": true
+		},
+		"codecov": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/codecov/-/codecov-2.3.0.tgz",
+			"integrity": "sha1-rSWixuBELRN0DZ1N27mj4nFDMPQ=",
+			"dev": true,
+			"requires": {
+				"argv": "0.0.2",
+				"request": "2.81.0",
+				"urlgrey": "0.4.4"
+			}
+		},
+		"combined-stream": {
+			"version": "1.0.5",
+			"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+			"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
+			"dev": true,
+			"requires": {
+				"delayed-stream": "1.0.0"
+			}
+		},
+		"commander": {
+			"version": "2.9.0",
+			"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+			"integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+			"dev": true,
+			"requires": {
+				"graceful-readlink": "1.0.1"
+			}
+		},
+		"concat-map": {
+			"version": "0.0.1",
+			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+			"dev": true
+		},
+		"core-util-is": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+			"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+			"dev": true
+		},
+		"cryptiles": {
+			"version": "2.0.5",
+			"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+			"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+			"dev": true,
+			"requires": {
+				"boom": "2.10.1"
+			}
+		},
+		"dashdash": {
+			"version": "1.14.1",
+			"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+			"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+			"dev": true,
+			"requires": {
+				"assert-plus": "1.0.0"
+			},
+			"dependencies": {
+				"assert-plus": {
+					"version": "1.0.0",
+					"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+					"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+					"dev": true
+				}
+			}
+		},
+		"debug": {
+			"version": "2.6.8",
+			"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+			"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+			"dev": true,
+			"requires": {
+				"ms": "2.0.0"
+			}
+		},
+		"decamelize": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+			"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+			"dev": true,
+			"optional": true
+		},
+		"deep-is": {
+			"version": "0.1.3",
+			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+			"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+			"dev": true
+		},
+		"delayed-stream": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+			"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+			"dev": true
+		},
+		"diff": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
+			"integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
+			"dev": true
+		},
+		"ecc-jsbn": {
+			"version": "0.1.1",
+			"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+			"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"jsbn": "0.1.1"
+			}
+		},
+		"escape-string-regexp": {
+			"version": "1.0.5",
+			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+			"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+			"dev": true
+		},
+		"escodegen": {
+			"version": "1.8.1",
+			"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+			"integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
+			"dev": true,
+			"requires": {
+				"esprima": "2.7.3",
+				"estraverse": "1.9.3",
+				"esutils": "2.0.2",
+				"optionator": "0.8.2",
+				"source-map": "0.2.0"
+			}
+		},
+		"esprima": {
+			"version": "2.7.3",
+			"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+			"integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+			"dev": true
+		},
+		"estraverse": {
+			"version": "1.9.3",
+			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+			"integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
+			"dev": true
+		},
+		"esutils": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+			"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+			"dev": true
+		},
+		"extend": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+			"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
+			"dev": true
+		},
+		"extsprintf": {
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+			"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+			"dev": true
+		},
+		"fast-levenshtein": {
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+			"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+			"dev": true
+		},
+		"forever-agent": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+			"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+			"dev": true
+		},
+		"form-data": {
+			"version": "2.1.4",
+			"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+			"integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+			"dev": true,
+			"requires": {
+				"asynckit": "0.4.0",
+				"combined-stream": "1.0.5",
+				"mime-types": "2.1.16"
+			}
+		},
+		"fs.realpath": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+			"dev": true
+		},
+		"getpass": {
+			"version": "0.1.7",
+			"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+			"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+			"dev": true,
+			"requires": {
+				"assert-plus": "1.0.0"
+			},
+			"dependencies": {
+				"assert-plus": {
+					"version": "1.0.0",
+					"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+					"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+					"dev": true
+				}
+			}
+		},
+		"glob": {
+			"version": "5.0.15",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+			"integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+			"dev": true,
+			"requires": {
+				"inflight": "1.0.6",
+				"inherits": "2.0.3",
+				"minimatch": "3.0.4",
+				"once": "1.4.0",
+				"path-is-absolute": "1.0.1"
+			}
+		},
+		"graceful-readlink": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+			"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+			"dev": true
+		},
+		"growl": {
+			"version": "1.9.2",
+			"resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
+			"integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
+			"dev": true
+		},
+		"handlebars": {
+			"version": "4.0.10",
+			"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz",
+			"integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=",
+			"dev": true,
+			"requires": {
+				"async": "1.5.2",
+				"optimist": "0.6.1",
+				"source-map": "0.4.4",
+				"uglify-js": "2.8.29"
+			},
+			"dependencies": {
+				"source-map": {
+					"version": "0.4.4",
+					"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+					"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+					"dev": true,
+					"requires": {
+						"amdefine": "1.0.1"
+					}
+				}
+			}
+		},
+		"har-schema": {
+			"version": "1.0.5",
+			"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+			"integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
+			"dev": true
+		},
+		"har-validator": {
+			"version": "4.2.1",
+			"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+			"integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
+			"dev": true,
+			"requires": {
+				"ajv": "4.11.8",
+				"har-schema": "1.0.5"
+			}
+		},
+		"has-flag": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+			"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+			"dev": true
+		},
+		"hawk": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+			"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+			"dev": true,
+			"requires": {
+				"boom": "2.10.1",
+				"cryptiles": "2.0.5",
+				"hoek": "2.16.3",
+				"sntp": "1.0.9"
+			}
+		},
+		"hoek": {
+			"version": "2.16.3",
+			"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+			"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
+			"dev": true
+		},
+		"http-signature": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+			"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+			"dev": true,
+			"requires": {
+				"assert-plus": "0.2.0",
+				"jsprim": "1.4.1",
+				"sshpk": "1.13.1"
+			}
+		},
+		"inflight": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+			"dev": true,
+			"requires": {
+				"once": "1.4.0",
+				"wrappy": "1.0.2"
+			}
+		},
+		"inherits": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+			"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+			"dev": true
+		},
+		"is-buffer": {
+			"version": "1.1.5",
+			"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
+			"integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
+			"dev": true
+		},
+		"is-typedarray": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+			"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+			"dev": true
+		},
+		"isexe": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+			"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+			"dev": true
+		},
+		"isstream": {
+			"version": "0.1.2",
+			"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+			"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+			"dev": true
+		},
+		"istanbul": {
+			"version": "0.4.5",
+			"resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
+			"integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
+			"dev": true,
+			"requires": {
+				"abbrev": "1.0.9",
+				"async": "1.5.2",
+				"escodegen": "1.8.1",
+				"esprima": "2.7.3",
+				"glob": "5.0.15",
+				"handlebars": "4.0.10",
+				"js-yaml": "3.8.4",
+				"mkdirp": "0.5.1",
+				"nopt": "3.0.6",
+				"once": "1.4.0",
+				"resolve": "1.1.7",
+				"supports-color": "3.2.3",
+				"which": "1.2.14",
+				"wordwrap": "1.0.0"
+			},
+			"dependencies": {
+				"supports-color": {
+					"version": "3.2.3",
+					"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+					"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+					"dev": true,
+					"requires": {
+						"has-flag": "1.0.0"
+					}
+				}
+			}
+		},
+		"js-yaml": {
+			"version": "3.8.4",
+			"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz",
+			"integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=",
+			"dev": true,
+			"requires": {
+				"argparse": "1.0.9",
+				"esprima": "3.1.3"
+			},
+			"dependencies": {
+				"esprima": {
+					"version": "3.1.3",
+					"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+					"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
+					"dev": true
+				}
+			}
+		},
+		"jsbn": {
+			"version": "0.1.1",
+			"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+			"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+			"dev": true,
+			"optional": true
+		},
+		"jsesc": {
+			"version": "2.5.1",
+			"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
+			"integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=",
+			"dev": true
+		},
+		"json-schema": {
+			"version": "0.2.3",
+			"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+			"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+			"dev": true
+		},
+		"json-stable-stringify": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+			"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+			"dev": true,
+			"requires": {
+				"jsonify": "0.0.0"
+			}
+		},
+		"json-stringify-safe": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+			"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+			"dev": true
+		},
+		"json3": {
+			"version": "3.3.2",
+			"resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+			"integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+			"dev": true
+		},
+		"jsonify": {
+			"version": "0.0.0",
+			"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+			"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+			"dev": true
+		},
+		"jsprim": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+			"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+			"dev": true,
+			"requires": {
+				"assert-plus": "1.0.0",
+				"extsprintf": "1.3.0",
+				"json-schema": "0.2.3",
+				"verror": "1.10.0"
+			},
+			"dependencies": {
+				"assert-plus": {
+					"version": "1.0.0",
+					"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+					"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+					"dev": true
+				}
+			}
+		},
+		"kind-of": {
+			"version": "3.2.2",
+			"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+			"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+			"dev": true,
+			"requires": {
+				"is-buffer": "1.1.5"
+			}
+		},
+		"lazy-cache": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+			"integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+			"dev": true,
+			"optional": true
+		},
+		"levn": {
+			"version": "0.3.0",
+			"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+			"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+			"dev": true,
+			"requires": {
+				"prelude-ls": "1.1.2",
+				"type-check": "0.3.2"
+			}
+		},
+		"lodash": {
+			"version": "4.17.4",
+			"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+			"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+			"dev": true
+		},
+		"lodash._baseassign": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+			"integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
+			"dev": true,
+			"requires": {
+				"lodash._basecopy": "3.0.1",
+				"lodash.keys": "3.1.2"
+			}
+		},
+		"lodash._basecopy": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+			"integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+			"dev": true
+		},
+		"lodash._basecreate": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
+			"integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
+			"dev": true
+		},
+		"lodash._getnative": {
+			"version": "3.9.1",
+			"resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+			"integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+			"dev": true
+		},
+		"lodash._isiterateecall": {
+			"version": "3.0.9",
+			"resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+			"integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+			"dev": true
+		},
+		"lodash.create": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
+			"integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
+			"dev": true,
+			"requires": {
+				"lodash._baseassign": "3.2.0",
+				"lodash._basecreate": "3.0.3",
+				"lodash._isiterateecall": "3.0.9"
+			}
+		},
+		"lodash.isarguments": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+			"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+			"dev": true
+		},
+		"lodash.isarray": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+			"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+			"dev": true
+		},
+		"lodash.keys": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+			"integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+			"dev": true,
+			"requires": {
+				"lodash._getnative": "3.9.1",
+				"lodash.isarguments": "3.1.0",
+				"lodash.isarray": "3.0.4"
+			}
+		},
+		"longest": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+			"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+			"dev": true
+		},
+		"mime-db": {
+			"version": "1.29.0",
+			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz",
+			"integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=",
+			"dev": true
+		},
+		"mime-types": {
+			"version": "2.1.16",
+			"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz",
+			"integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=",
+			"dev": true,
+			"requires": {
+				"mime-db": "1.29.0"
+			}
+		},
+		"minimatch": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+			"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+			"dev": true,
+			"requires": {
+				"brace-expansion": "1.1.8"
+			}
+		},
+		"minimist": {
+			"version": "0.0.10",
+			"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+			"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+			"dev": true
+		},
+		"mkdirp": {
+			"version": "0.5.1",
+			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+			"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+			"dev": true,
+			"requires": {
+				"minimist": "0.0.8"
+			},
+			"dependencies": {
+				"minimist": {
+					"version": "0.0.8",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+					"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+					"dev": true
+				}
+			}
+		},
+		"mocha": {
+			"version": "3.5.0",
+			"resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz",
+			"integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==",
+			"dev": true,
+			"requires": {
+				"browser-stdout": "1.3.0",
+				"commander": "2.9.0",
+				"debug": "2.6.8",
+				"diff": "3.2.0",
+				"escape-string-regexp": "1.0.5",
+				"glob": "7.1.1",
+				"growl": "1.9.2",
+				"json3": "3.3.2",
+				"lodash.create": "3.1.1",
+				"mkdirp": "0.5.1",
+				"supports-color": "3.1.2"
+			},
+			"dependencies": {
+				"glob": {
+					"version": "7.1.1",
+					"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+					"integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+					"dev": true,
+					"requires": {
+						"fs.realpath": "1.0.0",
+						"inflight": "1.0.6",
+						"inherits": "2.0.3",
+						"minimatch": "3.0.4",
+						"once": "1.4.0",
+						"path-is-absolute": "1.0.1"
+					}
+				}
+			}
+		},
+		"ms": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+			"dev": true
+		},
+		"nopt": {
+			"version": "3.0.6",
+			"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+			"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+			"dev": true,
+			"requires": {
+				"abbrev": "1.0.9"
+			}
+		},
+		"oauth-sign": {
+			"version": "0.8.2",
+			"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+			"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
+			"dev": true
+		},
+		"once": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+			"dev": true,
+			"requires": {
+				"wrappy": "1.0.2"
+			}
+		},
+		"optimist": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+			"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+			"dev": true,
+			"requires": {
+				"minimist": "0.0.10",
+				"wordwrap": "0.0.3"
+			},
+			"dependencies": {
+				"wordwrap": {
+					"version": "0.0.3",
+					"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+					"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+					"dev": true
+				}
+			}
+		},
+		"optionator": {
+			"version": "0.8.2",
+			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+			"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+			"dev": true,
+			"requires": {
+				"deep-is": "0.1.3",
+				"fast-levenshtein": "2.0.6",
+				"levn": "0.3.0",
+				"prelude-ls": "1.1.2",
+				"type-check": "0.3.2",
+				"wordwrap": "1.0.0"
+			}
+		},
+		"path-is-absolute": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+			"dev": true
+		},
+		"performance-now": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+			"integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
+			"dev": true
+		},
+		"prelude-ls": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+			"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+			"dev": true
+		},
+		"punycode": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+			"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+			"dev": true
+		},
+		"qs": {
+			"version": "6.4.0",
+			"resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+			"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
+			"dev": true
+		},
+		"regenerate": {
+			"version": "1.3.2",
+			"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
+			"integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA="
+		},
+		"regenerate-unicode-properties": {
+			"version": "5.1.1",
+			"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-5.1.1.tgz",
+			"integrity": "sha512-oaZXgyhHR9VYnYFzPRdO+k7tHaUXO5jPqfFYnaC5kIW9NQ0kVwb5rt8x5CEC0LCZ7WRIUy7zIrCF7R2xIbjiRA==",
+			"requires": {
+				"regenerate": "1.3.2"
+			}
+		},
+		"regexpu-fixtures": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/regexpu-fixtures/-/regexpu-fixtures-2.1.1.tgz",
+			"integrity": "sha1-qDaM8+3EfmIVORQi7qhkHDFsGo8=",
+			"dev": true
+		},
+		"regjsgen": {
+			"version": "0.3.0",
+			"resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.3.0.tgz",
+			"integrity": "sha1-DuSj6SdkMM2iXx54nqbBW4ewy0M="
+		},
+		"regjsparser": {
+			"version": "0.2.1",
+			"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.2.1.tgz",
+			"integrity": "sha1-w3h1U/rwTndcMCEC7zRtmVAA7Bw=",
+			"requires": {
+				"jsesc": "0.5.0"
+			},
+			"dependencies": {
+				"jsesc": {
+					"version": "0.5.0",
+					"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+					"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+				}
+			}
+		},
+		"repeat-string": {
+			"version": "1.6.1",
+			"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+			"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+			"dev": true
+		},
+		"request": {
+			"version": "2.81.0",
+			"resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+			"integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
+			"dev": true,
+			"requires": {
+				"aws-sign2": "0.6.0",
+				"aws4": "1.6.0",
+				"caseless": "0.12.0",
+				"combined-stream": "1.0.5",
+				"extend": "3.0.1",
+				"forever-agent": "0.6.1",
+				"form-data": "2.1.4",
+				"har-validator": "4.2.1",
+				"hawk": "3.1.3",
+				"http-signature": "1.1.1",
+				"is-typedarray": "1.0.0",
+				"isstream": "0.1.2",
+				"json-stringify-safe": "5.0.1",
+				"mime-types": "2.1.16",
+				"oauth-sign": "0.8.2",
+				"performance-now": "0.2.0",
+				"qs": "6.4.0",
+				"safe-buffer": "5.1.1",
+				"stringstream": "0.0.5",
+				"tough-cookie": "2.3.2",
+				"tunnel-agent": "0.6.0",
+				"uuid": "3.1.0"
+			}
+		},
+		"resolve": {
+			"version": "1.1.7",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+			"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+			"dev": true
+		},
+		"right-align": {
+			"version": "0.1.3",
+			"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+			"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"align-text": "0.1.4"
+			}
+		},
+		"safe-buffer": {
+			"version": "5.1.1",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+			"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+			"dev": true
+		},
+		"sntp": {
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+			"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+			"dev": true,
+			"requires": {
+				"hoek": "2.16.3"
+			}
+		},
+		"source-map": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+			"integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"amdefine": "1.0.1"
+			}
+		},
+		"sprintf-js": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+			"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+			"dev": true
+		},
+		"sshpk": {
+			"version": "1.13.1",
+			"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
+			"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+			"dev": true,
+			"requires": {
+				"asn1": "0.2.3",
+				"assert-plus": "1.0.0",
+				"bcrypt-pbkdf": "1.0.1",
+				"dashdash": "1.14.1",
+				"ecc-jsbn": "0.1.1",
+				"getpass": "0.1.7",
+				"jsbn": "0.1.1",
+				"tweetnacl": "0.14.5"
+			},
+			"dependencies": {
+				"assert-plus": {
+					"version": "1.0.0",
+					"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+					"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+					"dev": true
+				}
+			}
+		},
+		"stringstream": {
+			"version": "0.0.5",
+			"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+			"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
+			"dev": true
+		},
+		"supports-color": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+			"integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
+			"dev": true,
+			"requires": {
+				"has-flag": "1.0.0"
+			}
+		},
+		"tough-cookie": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
+			"integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
+			"dev": true,
+			"requires": {
+				"punycode": "1.4.1"
+			}
+		},
+		"tunnel-agent": {
+			"version": "0.6.0",
+			"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+			"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+			"dev": true,
+			"requires": {
+				"safe-buffer": "5.1.1"
+			}
+		},
+		"tweetnacl": {
+			"version": "0.14.5",
+			"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+			"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+			"dev": true,
+			"optional": true
+		},
+		"type-check": {
+			"version": "0.3.2",
+			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+			"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+			"dev": true,
+			"requires": {
+				"prelude-ls": "1.1.2"
+			}
+		},
+		"uglify-js": {
+			"version": "2.8.29",
+			"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+			"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"source-map": "0.5.6",
+				"uglify-to-browserify": "1.0.2",
+				"yargs": "3.10.0"
+			},
+			"dependencies": {
+				"source-map": {
+					"version": "0.5.6",
+					"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+					"integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+					"dev": true,
+					"optional": true
+				}
+			}
+		},
+		"uglify-to-browserify": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+			"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+			"dev": true,
+			"optional": true
+		},
+		"unicode-10.0.0": {
+			"version": "0.7.4",
+			"resolved": "https://registry.npmjs.org/unicode-10.0.0/-/unicode-10.0.0-0.7.4.tgz",
+			"integrity": "sha512-TXvlDZJxOQ7DVMl0fvlUe+VrDxEvv9yxnAyXHReiBOsKlqGTOgV79eKWOHURH7ySmuxncq0boRzZx63z/elPeA==",
+			"dev": true
+		},
+		"unicode-canonical-property-names-ecmascript": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.2.tgz",
+			"integrity": "sha512-tIHxB3DR9aS8uArhzIja8y0LQDvWx7DZIRkHJtLPnM29x/m0sNiMF9FYsxIASpkj85qfBvMWBsFURZoHIX6ceA=="
+		},
+		"unicode-match-property-ecmascript": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.3.tgz",
+			"integrity": "sha512-nFcaBFcr08UQNF15ZgI5ISh3yUnQm7SJRRxwYrL5VYX46pS+6Q7TCTv4zbK+j6/l7rQt0mMiTL2zpmeygny6rA==",
+			"requires": {
+				"unicode-canonical-property-names-ecmascript": "1.0.2",
+				"unicode-property-aliases-ecmascript": "1.0.3"
+			}
+		},
+		"unicode-match-property-value-ecmascript": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.1.tgz",
+			"integrity": "sha512-lM8B0FDZQh9yYGgiabRQcyWicB27VLOolSBRIxsO7FeQPtg+79Oe7sC8Mzr8BObDs+G9CeYmC/shHo6OggNEog=="
+		},
+		"unicode-property-aliases-ecmascript": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.3.tgz",
+			"integrity": "sha512-TdDmDOTxEf2ad1g3ZBpM6cqKIb2nJpVlz1Q++casDryKz18tpeMBhSng9hjC1CTQCkOV9Rw2knlSB6iRo7ad1w=="
+		},
+		"unicode-tr51": {
+			"version": "9.0.0",
+			"resolved": "https://registry.npmjs.org/unicode-tr51/-/unicode-tr51-9.0.0.tgz",
+			"integrity": "sha512-dqQFvT+4Oc8kHseEBB2a/xMKJcPz7jUvkUfw4AG7YUoyhjBl6/lCpHoSEHBXA199Bv804Ob8lB2O7WTqsyai2A==",
+			"dev": true
+		},
+		"urlgrey": {
+			"version": "0.4.4",
+			"resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz",
+			"integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=",
+			"dev": true
+		},
+		"uuid": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+			"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==",
+			"dev": true
+		},
+		"verror": {
+			"version": "1.10.0",
+			"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+			"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+			"dev": true,
+			"requires": {
+				"assert-plus": "1.0.0",
+				"core-util-is": "1.0.2",
+				"extsprintf": "1.3.0"
+			},
+			"dependencies": {
+				"assert-plus": {
+					"version": "1.0.0",
+					"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+					"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+					"dev": true
+				}
+			}
+		},
+		"which": {
+			"version": "1.2.14",
+			"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
+			"integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
+			"dev": true,
+			"requires": {
+				"isexe": "2.0.0"
+			}
+		},
+		"window-size": {
+			"version": "0.1.0",
+			"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+			"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+			"dev": true,
+			"optional": true
+		},
+		"wordwrap": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+			"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+			"dev": true
+		},
+		"wrappy": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+			"dev": true
+		},
+		"yargs": {
+			"version": "3.10.0",
+			"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+			"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+			"dev": true,
+			"optional": true,
+			"requires": {
+				"camelcase": "1.2.1",
+				"cliui": "2.1.0",
+				"decamelize": "1.2.0",
+				"window-size": "0.1.0"
+			}
+		}
+	}
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..86c3628
--- /dev/null
+++ b/package.json
@@ -0,0 +1,68 @@
+{
+	"name": "regexpu-core",
+	"version": "4.1.2",
+	"description": "regexpu’s core functionality (i.e. `rewritePattern(pattern, flag)`), capable of translating ES6 Unicode regular expressions to ES5.",
+	"homepage": "https://mths.be/regexpu",
+	"main": "rewrite-pattern.js",
+	"engines": {
+		"node": ">=4"
+	},
+	"keywords": [
+		"codegen",
+		"desugaring",
+		"ecmascript",
+		"es5",
+		"es6",
+		"harmony",
+		"javascript",
+		"refactoring",
+		"regex",
+		"regexp",
+		"regular expressions",
+		"rewriting",
+		"syntax",
+		"transformation",
+		"transpile",
+		"transpiler",
+		"unicode"
+	],
+	"license": "MIT",
+	"author": {
+		"name": "Mathias Bynens",
+		"url": "https://mathiasbynens.be/"
+	},
+	"repository": {
+		"type": "git",
+		"url": "https://github.com/mathiasbynens/regexpu-core.git"
+	},
+	"bugs": "https://github.com/mathiasbynens/regexpu-core/issues",
+	"files": [
+		"LICENSE-MIT.txt",
+		"rewrite-pattern.js",
+		"data/character-class-escape-sets.js",
+		"data/iu-mappings.js"
+	],
+	"scripts": {
+		"build": "node scripts/iu-mappings.js && node scripts/character-class-escape-sets.js",
+		"test": "mocha tests",
+		"cover": "istanbul cover --report html node_modules/.bin/_mocha tests -- -u exports -R spec"
+	},
+	"dependencies": {
+		"regenerate": "^1.3.2",
+		"regenerate-unicode-properties": "^5.1.1",
+		"regjsgen": "^0.3.0",
+		"regjsparser": "^0.2.1",
+		"unicode-match-property-ecmascript": "^1.0.3",
+		"unicode-match-property-value-ecmascript": "^1.0.1"
+	},
+	"devDependencies": {
+		"codecov": "^2.3.0",
+		"istanbul": "^0.4.5",
+		"jsesc": "^2.5.1",
+		"lodash": "^4.17.4",
+		"mocha": "^3.5.0",
+		"regexpu-fixtures": "^2.1.1",
+		"unicode-10.0.0": "^0.7.4",
+		"unicode-tr51": "^9.0.0"
+	}
+}
diff --git a/property-escapes.md b/property-escapes.md
new file mode 100644
index 0000000..881f139
--- /dev/null
+++ b/property-escapes.md
@@ -0,0 +1,330 @@
+# Unicode property escapes in _regexpu_
+
+To opt-in to experimental support for [Unicode property escapes](https://github.com/mathiasbynens/es-regexp-unicode-property-escapes), enable [the `unicodePropertyEscape` option](README.md#unicodepropertyescape-default-false).
+
+```js
+rewritePattern('\\p{Script_Extensions=Anatolian_Hieroglyphs}', 'u', {
+  'unicodePropertyEscape': true
+});
+// → '(?:\\uD811[\\uDC00-\\uDE46])'
+```
+
+If you’re targeting ES6 environments exclusively, consider enabling [the `useUnicodeFlag` option](README.md#useunicodeflag-default-false) for simpler (but not necessarily more compact) output.
+
+```js
+rewritePattern('\\p{Script_Extensions=Anatolian_Hieroglyphs}', 'u', {
+  'unicodePropertyEscape': true,
+  'useUnicodeFlag': true
+});
+// → '[\\u{14400}-\\u{14646}]'
+```
+
+[An online demo is available.](https://mothereff.in/regexpu#input=var+regex+%3D+/%5Cp%7BScript_Extensions%3DGreek%7D/u%3B&unicodePropertyEscape=1)
+
+Note that this feature is non-standard. This implementation may or may not reflect what eventually gets specified.
+
+What follows is an exhaustive overview of the Unicode properties and values that _regexpu_ supports in `\p{…}` and `\P{…}` expressions in regular expressions with the `u` flag.
+
+## Non-binary properties
+
+### `General_Category`
+
+Possible values:
+
+```sh
+$ node -e 'require("regenerate-unicode-properties").get("General_Category").forEach(c => { console.log(`\\p{${c}}`); })'
+\p{Cased_Letter}
+\p{Close_Punctuation}
+\p{Connector_Punctuation}
+\p{Control}
+\p{Currency_Symbol}
+\p{Dash_Punctuation}
+\p{Decimal_Number}
+\p{Enclosing_Mark}
+\p{Final_Punctuation}
+\p{Format}
+\p{Initial_Punctuation}
+\p{Letter}
+\p{Letter_Number}
+\p{Line_Separator}
+\p{Lowercase_Letter}
+\p{Mark}
+\p{Math_Symbol}
+\p{Modifier_Letter}
+\p{Modifier_Symbol}
+\p{Nonspacing_Mark}
+\p{Number}
+\p{Open_Punctuation}
+\p{Other}
+\p{Other_Letter}
+\p{Other_Number}
+\p{Other_Punctuation}
+\p{Other_Symbol}
+\p{Paragraph_Separator}
+\p{Private_Use}
+\p{Punctuation}
+\p{Separator}
+\p{Space_Separator}
+\p{Spacing_Mark}
+\p{Surrogate}
+\p{Symbol}
+\p{Titlecase_Letter}
+\p{Unassigned}
+\p{Uppercase_Letter}
+```
+
+Note that the `General_Category=` prefix may be used, e.g. `\p{General_Category=Cased_Letter}`.
+
+Category aliases may be used, e.g. `\p{Lc}` or `\p{General_Category=Lc}`, although IMHO it’s more readable to stick to the canonical category names listed above.
+
+### `Script` & `Script_Extensions`
+
+The sets of possible values for `Script` and `Script_Extensions` are identical:
+
+```sh
+$ node -e 'require("regenerate-unicode-properties").get("Script_Extensions").forEach(s => { console.log(`\\p{Script_Extensions=${s}}`); })'
+\p{Script_Extensions=Adlam}
+\p{Script_Extensions=Ahom}
+\p{Script_Extensions=Anatolian_Hieroglyphs}
+\p{Script_Extensions=Arabic}
+\p{Script_Extensions=Armenian}
+\p{Script_Extensions=Avestan}
+\p{Script_Extensions=Balinese}
+\p{Script_Extensions=Bamum}
+\p{Script_Extensions=Bassa_Vah}
+\p{Script_Extensions=Batak}
+\p{Script_Extensions=Bengali}
+\p{Script_Extensions=Bhaiksuki}
+\p{Script_Extensions=Bopomofo}
+\p{Script_Extensions=Brahmi}
+\p{Script_Extensions=Braille}
+\p{Script_Extensions=Buginese}
+\p{Script_Extensions=Buhid}
+\p{Script_Extensions=Canadian_Aboriginal}
+\p{Script_Extensions=Carian}
+\p{Script_Extensions=Caucasian_Albanian}
+\p{Script_Extensions=Chakma}
+\p{Script_Extensions=Cham}
+\p{Script_Extensions=Cherokee}
+\p{Script_Extensions=Common}
+\p{Script_Extensions=Coptic}
+\p{Script_Extensions=Cuneiform}
+\p{Script_Extensions=Cypriot}
+\p{Script_Extensions=Cyrillic}
+\p{Script_Extensions=Deseret}
+\p{Script_Extensions=Devanagari}
+\p{Script_Extensions=Duployan}
+\p{Script_Extensions=Egyptian_Hieroglyphs}
+\p{Script_Extensions=Elbasan}
+\p{Script_Extensions=Ethiopic}
+\p{Script_Extensions=Georgian}
+\p{Script_Extensions=Glagolitic}
+\p{Script_Extensions=Gothic}
+\p{Script_Extensions=Grantha}
+\p{Script_Extensions=Greek}
+\p{Script_Extensions=Gujarati}
+\p{Script_Extensions=Gurmukhi}
+\p{Script_Extensions=Han}
+\p{Script_Extensions=Hangul}
+\p{Script_Extensions=Hanunoo}
+\p{Script_Extensions=Hatran}
+\p{Script_Extensions=Hebrew}
+\p{Script_Extensions=Hiragana}
+\p{Script_Extensions=Imperial_Aramaic}
+\p{Script_Extensions=Inherited}
+\p{Script_Extensions=Inscriptional_Pahlavi}
+\p{Script_Extensions=Inscriptional_Parthian}
+\p{Script_Extensions=Javanese}
+\p{Script_Extensions=Kaithi}
+\p{Script_Extensions=Kannada}
+\p{Script_Extensions=Katakana}
+\p{Script_Extensions=Kayah_Li}
+\p{Script_Extensions=Kharoshthi}
+\p{Script_Extensions=Khmer}
+\p{Script_Extensions=Khojki}
+\p{Script_Extensions=Khudawadi}
+\p{Script_Extensions=Lao}
+\p{Script_Extensions=Latin}
+\p{Script_Extensions=Lepcha}
+\p{Script_Extensions=Limbu}
+\p{Script_Extensions=Linear_A}
+\p{Script_Extensions=Linear_B}
+\p{Script_Extensions=Lisu}
+\p{Script_Extensions=Lycian}
+\p{Script_Extensions=Lydian}
+\p{Script_Extensions=Mahajani}
+\p{Script_Extensions=Malayalam}
+\p{Script_Extensions=Mandaic}
+\p{Script_Extensions=Manichaean}
+\p{Script_Extensions=Marchen}
+\p{Script_Extensions=Masaram_Gondi}
+\p{Script_Extensions=Meetei_Mayek}
+\p{Script_Extensions=Mende_Kikakui}
+\p{Script_Extensions=Meroitic_Cursive}
+\p{Script_Extensions=Meroitic_Hieroglyphs}
+\p{Script_Extensions=Miao}
+\p{Script_Extensions=Modi}
+\p{Script_Extensions=Mongolian}
+\p{Script_Extensions=Mro}
+\p{Script_Extensions=Multani}
+\p{Script_Extensions=Myanmar}
+\p{Script_Extensions=Nabataean}
+\p{Script_Extensions=New_Tai_Lue}
+\p{Script_Extensions=Newa}
+\p{Script_Extensions=Nko}
+\p{Script_Extensions=Nushu}
+\p{Script_Extensions=Ogham}
+\p{Script_Extensions=Ol_Chiki}
+\p{Script_Extensions=Old_Hungarian}
+\p{Script_Extensions=Old_Italic}
+\p{Script_Extensions=Old_North_Arabian}
+\p{Script_Extensions=Old_Permic}
+\p{Script_Extensions=Old_Persian}
+\p{Script_Extensions=Old_South_Arabian}
+\p{Script_Extensions=Old_Turkic}
+\p{Script_Extensions=Oriya}
+\p{Script_Extensions=Osage}
+\p{Script_Extensions=Osmanya}
+\p{Script_Extensions=Pahawh_Hmong}
+\p{Script_Extensions=Palmyrene}
+\p{Script_Extensions=Pau_Cin_Hau}
+\p{Script_Extensions=Phags_Pa}
+\p{Script_Extensions=Phoenician}
+\p{Script_Extensions=Psalter_Pahlavi}
+\p{Script_Extensions=Rejang}
+\p{Script_Extensions=Runic}
+\p{Script_Extensions=Samaritan}
+\p{Script_Extensions=Saurashtra}
+\p{Script_Extensions=Sharada}
+\p{Script_Extensions=Shavian}
+\p{Script_Extensions=Siddham}
+\p{Script_Extensions=SignWriting}
+\p{Script_Extensions=Sinhala}
+\p{Script_Extensions=Sora_Sompeng}
+\p{Script_Extensions=Soyombo}
+\p{Script_Extensions=Sundanese}
+\p{Script_Extensions=Syloti_Nagri}
+\p{Script_Extensions=Syriac}
+\p{Script_Extensions=Tagalog}
+\p{Script_Extensions=Tagbanwa}
+\p{Script_Extensions=Tai_Le}
+\p{Script_Extensions=Tai_Tham}
+\p{Script_Extensions=Tai_Viet}
+\p{Script_Extensions=Takri}
+\p{Script_Extensions=Tamil}
+\p{Script_Extensions=Tangut}
+\p{Script_Extensions=Telugu}
+\p{Script_Extensions=Thaana}
+\p{Script_Extensions=Thai}
+\p{Script_Extensions=Tibetan}
+\p{Script_Extensions=Tifinagh}
+\p{Script_Extensions=Tirhuta}
+\p{Script_Extensions=Ugaritic}
+\p{Script_Extensions=Vai}
+\p{Script_Extensions=Warang_Citi}
+\p{Script_Extensions=Yi}
+\p{Script_Extensions=Zanabazar_Square}
+```
+
+Note that script name aliases may be used as well, e.g. `\p{Script_Extensions=Aghb}`, although IMHO it’s more readable to stick to the canonical script names listed above.
+
+## Binary properties
+
+The following binary properties are supported:
+
+```sh
+$ node -e 'require("regenerate-unicode-properties").get("Binary_Property").forEach(p => { console.log(`\\p{${p}}`); })'
+\p{ASCII}
+\p{ASCII_Hex_Digit}
+\p{Alphabetic}
+\p{Any}
+\p{Assigned}
+\p{Bidi_Control}
+\p{Bidi_Mirrored}
+\p{Case_Ignorable}
+\p{Cased}
+\p{Changes_When_Casefolded}
+\p{Changes_When_Casemapped}
+\p{Changes_When_Lowercased}
+\p{Changes_When_NFKC_Casefolded}
+\p{Changes_When_Titlecased}
+\p{Changes_When_Uppercased}
+\p{Dash}
+\p{Default_Ignorable_Code_Point}
+\p{Deprecated}
+\p{Diacritic}
+\p{Emoji}
+\p{Emoji_Component}
+\p{Emoji_Modifier}
+\p{Emoji_Modifier_Base}
+\p{Emoji_Presentation}
+\p{Extended_Pictographic}
+\p{Extender}
+\p{Grapheme_Base}
+\p{Grapheme_Extend}
+\p{Hex_Digit}
+\p{IDS_Binary_Operator}
+\p{IDS_Trinary_Operator}
+\p{ID_Continue}
+\p{ID_Start}
+\p{Ideographic}
+\p{Join_Control}
+\p{Logical_Order_Exception}
+\p{Lowercase}
+\p{Math}
+\p{Noncharacter_Code_Point}
+\p{Pattern_Syntax}
+\p{Pattern_White_Space}
+\p{Quotation_Mark}
+\p{Radical}
+\p{Regional_Indicator}
+\p{Sentence_Terminal}
+\p{Soft_Dotted}
+\p{Terminal_Punctuation}
+\p{Unified_Ideograph}
+\p{Uppercase}
+\p{Variation_Selector}
+\p{White_Space}
+\p{XID_Continue}
+\p{XID_Start}
+```
+
+Note that property name aliases may be used as well, e.g. `\p{AHex}`, although IMHO it’s more readable to stick to the canonical property names listed above.
+
+### Unsupported properties
+
+The abovementioned list of properties and values goes a long way towards fulfilling [UTR18 requirement RL2.7](http://unicode.org/reports/tr18/#RL2.7). However, the following properties are not currently supported:
+
+* `Age`
+* `Bidi_Class`
+* `Bidi_Mirroring_Glyph`
+* `Bidi_Paired_Bracket_Type`
+* `Bidi_Paired_Bracket`
+* `Block`
+* `Canonical_Combining_Class`
+* `Case_Folding`
+* `Decomposition_Mapping`
+* `Decomposition_Type`
+* `East_Asian_Width`
+* `Grapheme_Cluster_Break`
+* `Hangul_Syllable_Type`
+* `Joining_Group`
+* `Joining_Type`
+* `Line_Break`
+* `Lowercase_Mapping`
+* `Name` & `Name_Alias`
+* `NFC_Quick_Check`
+* `NFD_Quick_Check`
+* `NFKC_Casefold`
+* `NFKC_Quick_Check`
+* `NFKD_Quick_Check`
+* `Numeric_Type`
+* `Numeric_Value`
+* `Sentence_Break`
+* `Simple_Case_Folding`
+* `Simple_Lowercase_Mapping`
+* `Simple_Titlecase_Mapping`
+* `Simple_Uppercase_Mapping`
+* `Titlecase_Mapping`
+* `Uppercase_Mapping`
+* `Word_Break`
diff --git a/rewrite-pattern.js b/rewrite-pattern.js
new file mode 100644
index 0000000..380d4d3
--- /dev/null
+++ b/rewrite-pattern.js
@@ -0,0 +1,270 @@
+'use strict';
+
+const generate = require('regjsgen').generate;
+const parse = require('regjsparser').parse;
+const regenerate = require('regenerate');
+const unicodeMatchProperty = require('unicode-match-property-ecmascript');
+const unicodeMatchPropertyValue = require('unicode-match-property-value-ecmascript');
+const iuMappings = require('./data/iu-mappings.js');
+const ESCAPE_SETS = require('./data/character-class-escape-sets.js');
+
+// Prepare a Regenerate set containing all code points, used for negative
+// character classes (if any).
+const UNICODE_SET = regenerate().addRange(0x0, 0x10FFFF);
+// Without the `u` flag, the range stops at 0xFFFF.
+// https://mths.be/es6#sec-pattern-semantics
+const BMP_SET = regenerate().addRange(0x0, 0xFFFF);
+
+// Prepare a Regenerate set containing all code points that are supposed to be
+// matched by `/./u`. https://mths.be/es6#sec-atom
+const DOT_SET_UNICODE = UNICODE_SET.clone() // all Unicode code points
+	.remove(
+		// minus `LineTerminator`s (https://mths.be/es6#sec-line-terminators):
+		0x000A, // Line Feed <LF>
+		0x000D, // Carriage Return <CR>
+		0x2028, // Line Separator <LS>
+		0x2029  // Paragraph Separator <PS>
+	);
+// Prepare a Regenerate set containing all code points that are supposed to be
+// matched by `/./` (only BMP code points).
+const DOT_SET = DOT_SET_UNICODE.clone()
+	.intersection(BMP_SET);
+
+const getCharacterClassEscapeSet = (character, unicode, ignoreCase) => {
+	if (unicode) {
+		if (ignoreCase) {
+			return ESCAPE_SETS.UNICODE_IGNORE_CASE.get(character);
+		}
+		return ESCAPE_SETS.UNICODE.get(character);
+	}
+	return ESCAPE_SETS.REGULAR.get(character);
+};
+
+const getDotSet = (unicode, dotAll) => {
+	if (dotAll) {
+		return unicode ? UNICODE_SET : BMP_SET;
+	}
+	return unicode ? DOT_SET_UNICODE : DOT_SET;
+};
+
+const getUnicodePropertyValueSet = (property, value) => {
+	const path = value ?
+		`${ property }/${ value }` :
+		`Binary_Property/${ property }`;
+	try {
+		return require(`regenerate-unicode-properties/${ path }.js`);
+	} catch (exception) {
+		throw new Error(
+			`Failed to recognize value \`${ value }\` for property ` +
+			`\`${ property }\`.`
+		);
+	}
+};
+
+const handleLoneUnicodePropertyNameOrValue = (value) => {
+	// It could be a `General_Category` value or a binary property.
+	// Note: `unicodeMatchPropertyValue` throws on invalid values.
+	try {
+		const property = 'General_Category';
+		const category = unicodeMatchPropertyValue(property, value);
+		return getUnicodePropertyValueSet(property, category);
+	} catch (exception) {}
+	// It’s not a `General_Category` value, so check if it’s a binary
+	// property. Note: `unicodeMatchProperty` throws on invalid properties.
+	const property = unicodeMatchProperty(value);
+	return getUnicodePropertyValueSet(property);
+};
+
+const getUnicodePropertyEscapeSet = (value, isNegative) => {
+	const parts = value.split('=');
+	const firstPart = parts[0];
+	let set;
+	if (parts.length == 1) {
+		set = handleLoneUnicodePropertyNameOrValue(firstPart);
+	} else {
+		// The pattern consists of two parts, i.e. `Property=Value`.
+		const property = unicodeMatchProperty(firstPart);
+		const value = unicodeMatchPropertyValue(property, parts[1]);
+		set = getUnicodePropertyValueSet(property, value);
+	}
+	if (isNegative) {
+		return UNICODE_SET.clone().remove(set);
+	}
+	return set.clone();
+};
+
+// Given a range of code points, add any case-folded code points in that range
+// to a set.
+regenerate.prototype.iuAddRange = function(min, max) {
+	const $this = this;
+	do {
+		const folded = caseFold(min);
+		if (folded) {
+			$this.add(folded);
+		}
+	} while (++min <= max);
+	return $this;
+};
+
+const update = (item, pattern) => {
+	let tree = parse(pattern, config.useUnicodeFlag ? 'u' : '');
+	switch (tree.type) {
+		case 'characterClass':
+		case 'group':
+		case 'value':
+			// No wrapping needed.
+			break;
+		default:
+			// Wrap the pattern in a non-capturing group.
+			tree = wrap(tree, pattern);
+	}
+	Object.assign(item, tree);
+};
+
+const wrap = (tree, pattern) => {
+	// Wrap the pattern in a non-capturing group.
+	return {
+		'type': 'group',
+		'behavior': 'ignore',
+		'body': [tree],
+		'raw': `(?:${ pattern })`
+	};
+};
+
+const caseFold = (codePoint) => {
+	return iuMappings.get(codePoint) || false;
+};
+
+const processCharacterClass = (characterClassItem, regenerateOptions) => {
+	let set = regenerate();
+	for (const item of characterClassItem.body) {
+		switch (item.type) {
+			case 'value':
+				set.add(item.codePoint);
+				if (config.ignoreCase && config.unicode && !config.useUnicodeFlag) {
+					const folded = caseFold(item.codePoint);
+					if (folded) {
+						set.add(folded);
+					}
+				}
+				break;
+			case 'characterClassRange':
+				const min = item.min.codePoint;
+				const max = item.max.codePoint;
+				set.addRange(min, max);
+				if (config.ignoreCase && config.unicode && !config.useUnicodeFlag) {
+					set.iuAddRange(min, max);
+				}
+				break;
+			case 'characterClassEscape':
+				set.add(getCharacterClassEscapeSet(
+					item.value,
+					config.unicode,
+					config.ignoreCase
+				));
+				break;
+			case 'unicodePropertyEscape':
+				set.add(getUnicodePropertyEscapeSet(item.value, item.negative));
+				break;
+			// The `default` clause is only here as a safeguard; it should never be
+			// reached. Code coverage tools should ignore it.
+			/* istanbul ignore next */
+			default:
+				throw new Error(`Unknown term type: ${ item.type }`);
+		}
+	}
+	if (characterClassItem.negative) {
+		set = (config.unicode ? UNICODE_SET : BMP_SET).clone().remove(set);
+	}
+	update(characterClassItem, set.toString(regenerateOptions));
+	return characterClassItem;
+};
+
+const processTerm = (item, regenerateOptions) => {
+	switch (item.type) {
+		case 'dot':
+			update(
+				item,
+				getDotSet(config.unicode, config.dotAll).toString(regenerateOptions)
+			);
+			break;
+		case 'characterClass':
+			item = processCharacterClass(item, regenerateOptions);
+			break;
+		case 'unicodePropertyEscape':
+			update(
+				item,
+				getUnicodePropertyEscapeSet(item.value, item.negative)
+					.toString(regenerateOptions)
+			);
+			break;
+		case 'characterClassEscape':
+			update(
+				item,
+				getCharacterClassEscapeSet(
+					item.value,
+					config.unicode,
+					config.ignoreCase
+				).toString(regenerateOptions)
+			);
+			break;
+		case 'alternative':
+		case 'disjunction':
+		case 'group':
+		case 'quantifier':
+			item.body = item.body.map(term => {
+				return processTerm(term, regenerateOptions);
+			});
+			break;
+		case 'value':
+			const codePoint = item.codePoint;
+			const set = regenerate(codePoint);
+			if (config.ignoreCase && config.unicode && !config.useUnicodeFlag) {
+				const folded = caseFold(codePoint);
+				if (folded) {
+					set.add(folded);
+				}
+			}
+			update(item, set.toString(regenerateOptions));
+			break;
+		case 'anchor':
+		case 'empty':
+		case 'group':
+		case 'reference':
+			// Nothing to do here.
+			break;
+		// The `default` clause is only here as a safeguard; it should never be
+		// reached. Code coverage tools should ignore it.
+		/* istanbul ignore next */
+		default:
+			throw new Error(`Unknown term type: ${ item.type }`);
+	}
+	return item;
+};
+
+const config = {
+	'ignoreCase': false,
+	'unicode': false,
+	'dotAll': false,
+	'useUnicodeFlag': false
+};
+const rewritePattern = (pattern, flags, options) => {
+	const regjsparserFeatures = {
+		'unicodePropertyEscape': options && options.unicodePropertyEscape
+	};
+	config.ignoreCase = flags && flags.includes('i');
+	config.unicode = flags && flags.includes('u');
+	const supportDotAllFlag = options && options.dotAllFlag;
+	config.dotAll = supportDotAllFlag && flags && flags.includes('s');
+	config.useUnicodeFlag = options && options.useUnicodeFlag;
+	const regenerateOptions = {
+		'hasUnicodeFlag': config.useUnicodeFlag,
+		'bmpOnly': !config.unicode
+	};
+	const tree = parse(pattern, flags, regjsparserFeatures);
+	// Note: `processTerm` mutates `tree`.
+	processTerm(tree, regenerateOptions);
+	return generate(tree);
+};
+
+module.exports = rewritePattern;
diff --git a/scripts/character-class-escape-sets.js b/scripts/character-class-escape-sets.js
new file mode 100644
index 0000000..1f4c21a
--- /dev/null
+++ b/scripts/character-class-escape-sets.js
@@ -0,0 +1,135 @@
+'use strict';
+
+const fs = require('fs');
+const jsesc = require('jsesc');
+const regenerate = require('regenerate');
+
+const Zs = require('unicode-10.0.0/General_Category/Space_Separator/code-points.js');
+
+const iuMappings = require('../data/iu-mappings.js');
+
+const caseFold = (codePoint) => {
+	return iuMappings.get(codePoint) || false;
+};
+
+// Prepare a Regenerate set containing all code points, used for negative
+// character classes (if any).
+const UNICODE_SET = regenerate().addRange(0x0, 0x10FFFF);
+// Without the `u` flag, the range stops at 0xFFFF.
+// https://mths.be/es#sec-pattern-semantics
+const BMP_SET = regenerate().addRange(0x0, 0xFFFF);
+
+const ESCAPE_CHARS = {};
+const ESCAPE_CHARS_UNICODE = {};
+const ESCAPE_CHARS_UNICODE_IGNORE_CASE = {};
+const addCharacterClassEscape = (lower, set) => {
+	ESCAPE_CHARS[lower] = ESCAPE_CHARS_UNICODE[lower] = set;
+	const upper = lower.toUpperCase();
+	ESCAPE_CHARS[upper] = BMP_SET.clone().remove(set);
+	ESCAPE_CHARS_UNICODE[upper] = UNICODE_SET.clone().remove(set);
+	// Check if one or more symbols in this set fold to another one. If so,
+	// a copy of the set including the mapped symbols is created for use with
+	// regular expressions that have both the `u` and `i` flags set.
+	const codePoints = set.toArray();
+	const iuSet = regenerate();
+	let containsFoldingSymbols = false;
+	for (const codePoint of codePoints) {
+		let folded = caseFold(codePoint);
+		if (folded) {
+			containsFoldingSymbols = true;
+			iuSet.add(folded);
+			folded = caseFold(folded);
+			if (folded) {
+				iuSet.add(folded);
+			}
+		}
+	}
+	const iuLowerSet = containsFoldingSymbols ?
+		iuSet.clone().add(set) :
+		set;
+	const iuUpperSet = UNICODE_SET.clone().remove(iuLowerSet);
+	ESCAPE_CHARS_UNICODE_IGNORE_CASE[lower] = iuLowerSet;
+	ESCAPE_CHARS_UNICODE_IGNORE_CASE[upper] = iuUpperSet;
+}
+
+// Prepare a Regenerate set for every existing character class escape.
+// https://mths.be/es#sec-characterclassescape
+addCharacterClassEscape(
+	'd', // `\d` and `\D`
+	regenerate().addRange('0', '9')
+);
+addCharacterClassEscape(
+	's', // `\s` and `\S`
+	regenerate(
+		// https://mths.be/es#sec-white-space
+		0x0009,
+		0x000B,
+		0x000C,
+		0x0020,
+		0x00A0,
+		0xFEFF,
+		Zs,
+		// https://mths.be/es#sec-line-terminators
+		0x000A,
+		0x000D,
+		0x2028,
+		0x2029
+	)
+);
+addCharacterClassEscape(
+	'w', // `\w` and `\W`
+	regenerate('_').addRange('a', 'z').addRange('A', 'Z').addRange('0', '9')
+);
+
+/*----------------------------------------------------------------------------*/
+
+const codePointToString = (codePoint) => {
+	return '0x' + codePoint.toString(16).toUpperCase();
+};
+
+// Regenerate plugin that turns a set into some JavaScript source code that
+// generates that set.
+regenerate.prototype.toCode = function() {
+	const data = this.data;
+	// Iterate over the data per `(start, end)` pair.
+	let index = 0;
+	let start;
+	let end;
+	const length = data.length;
+	const loneCodePoints = [];
+	const ranges = [];
+	while (index < length) {
+		start = data[index];
+		end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
+		if (start == end) {
+			loneCodePoints.push(codePointToString(start));
+		} else {
+			ranges.push(
+				'addRange(' + codePointToString(start) +
+				', ' + codePointToString(end) + ')'
+			);
+		}
+		index += 2;
+	}
+	return 'regenerate(' + loneCodePoints.join(', ') + ')' +
+		(ranges.length ? '\n\t\t.' + ranges.join('\n\t\t.') : '');
+};
+
+const stringify = (name, object) => {
+	const source = 'exports.' + name + ' = new Map([\n\t' + Object.keys(object).map((character) => {
+		const set = object[character];
+		return '[' + jsesc(character, { 'wrap': true }) + ', ' + set.toCode() + ']';
+	}).join(',\n\t') + '\n]);';
+	return source;
+};
+
+const source = [
+	'// Generated using `npm run build`. Do not edit.\n' +
+	`'use strict';\n\nconst regenerate = require('regenerate');`,
+	stringify('REGULAR', ESCAPE_CHARS),
+	stringify('UNICODE', ESCAPE_CHARS_UNICODE),
+	stringify('UNICODE_IGNORE_CASE', ESCAPE_CHARS_UNICODE_IGNORE_CASE)
+].join('\n\n');
+
+// Save the precompiled sets to a static file.
+fs.writeFileSync('data/character-class-escape-sets.js', source + '\n');
diff --git a/scripts/iu-mappings.js b/scripts/iu-mappings.js
new file mode 100644
index 0000000..a85852f
--- /dev/null
+++ b/scripts/iu-mappings.js
@@ -0,0 +1,179 @@
+'use strict';
+
+const fs = require('fs');
+const _ = require('lodash');
+const jsesc = require('jsesc');
+
+const hex = (number) => {
+	return `0x${ number.toString(16).toUpperCase() }`;
+};
+
+const writeMap = (fileName, map) => {
+	// Sort map by key.
+	const sortedMap = new Map([...map].sort((a, b) => a[0] - b[0]));
+	fs.writeFileSync(
+		fileName,
+		`module.exports = ${ jsesc(sortedMap, {
+			'compact': false,
+			'numbers': 'hexadecimal'
+		}) };\n`
+	);
+}
+
+// Given two code points, check if both are in the ASCII range and if one is
+// the uppercased version of the other. In that case, ES5 engines know about
+// this mapping, so it’s only needed to include one of the two in a
+// case-insensitive regular expression.
+const isES5CasedVariant = (a, b) => {
+	return (a < 0x80 && b < 0x80) &&
+		(oneWayMappings.get(a) == b || oneWayMappings.get(b) == a);
+};
+
+const extend = (map, key, value, callback) => {
+	if (map.has(key)) {
+		const currentValue = map.get(key);
+		if (Array.isArray(currentValue)) {
+			if (currentValue.indexOf(value) > -1) {
+				return;
+			}
+			if (callback) {
+				const skip = currentValue.some((codePoint) => {
+					return callback(codePoint, value);
+				});
+				if (skip) {
+					return;
+				}
+			}
+			currentValue.push(value);
+		} else {
+			if (currentValue == value) {
+				return;
+			}
+			if (callback) {
+				if (callback(currentValue, value)) {
+					return;
+				}
+			}
+			map.set(key, [currentValue, value]);
+		}
+	} else {
+		map.set(key, value);
+	}
+};
+
+// From <http://unicode.org/Public/UCD/latest/ucd/CaseFolding.txt>:
+//
+// The status field is:
+// C: common case folding, common mappings shared by both simple and full
+//    mappings.
+// F: full case folding, mappings that cause strings to grow in length. Multiple
+//    characters are separated by spaces.
+// S: simple case folding, mappings to single characters where different from F.
+// T: special case for uppercase I and dotted uppercase I
+//    - For non-Turkic languages, this mapping is normally not used.
+//    - For Turkic languages (tr, az), this mapping can be used instead of the
+//      normal mapping for these characters. Note that the Turkic mappings do
+//      not maintain canonical equivalence without additional processing.
+//      See the discussions of case mapping in the Unicode Standard for more
+//      information.
+//
+// Usage:
+//  A. To do a simple case folding, use the mappings with status C + S.
+//  B. To do a full case folding, use the mappings with status C + F.
+
+const commonMappings = require('unicode-10.0.0/Case_Folding/C/code-points.js');
+const simpleMappings = require('unicode-10.0.0/Case_Folding/S/code-points.js');
+
+// We want the `C` mappings in both directions (i.e. `A` should fold to `a`
+// and `a` to `A`), and the `S` mappings in both directions (i.e. `ẞ` should
+// fold to `ß` and `ß` to `ẞ`). Let’s start with the simple case folding (in
+// one direction) first, then filter the set, and then deal with the inverse.
+const oneWayMappings = new Map();
+for (const [from, to] of commonMappings) {
+	oneWayMappings.set(from, to);
+}
+for (const [from, to] of simpleMappings) {
+	oneWayMappings.set(from, to);
+}
+// Note: various code points can fold into the same code point, so it’s not
+// possible to simply invert `oneWayMappings` — some entries would be lost in
+// the process.
+
+// In case-insignificant matches when `Unicode` is `true` (i.e. when the `u`
+// flag is enabled), all characters are implicitly case-folded using the
+// simple mapping provided by the Unicode standard immediately before they
+// are compared. The simple mapping always maps to a single code point, so it
+// does not map, for example, `ß` (U+00DF) to `SS`. It may however map a code
+// point outside the Basic Latin range to a character within, for example, `ſ`
+// (U+017F) to `s`. Such characters are not mapped if `Unicode` is `false`.
+// This prevents Unicode code points such as U+017F and U+212A from matching
+// regular expressions such as `/[a‑z]/i`, but they will match `/[a‑z]/ui`.
+// https://mths.be/es6#sec-runtime-semantics-canonicalize-abstract-operation
+// Get the mappings that are unique to regular expressions that have both the
+// `i` and `u` flags set. In addition to the above, this includes all mappings
+// for astral code points.
+const filteredMappings = new Map();
+for (const [from, to] of oneWayMappings) {
+	// Case folding is applied to both the pattern and the string being matched.
+	// Because of that e.g. `/[A-Z]/iu` matches U+017F and U+212A, just like
+	// `/[a-z]/iu` would, even though no symbol in the range from `A` to `Z`
+	// folds to U+017F or U+212A directly. Since we’re only transpiling regular
+	// expressions and not strings, we have to account for this in regular
+	// expressions only. This can be done as per this example:
+	// 1. `oneWayMappings` already maps `S` to `s`. (83 → 115)
+	// 2. `oneWayMappings` already maps `ſ` to `s`. (383 → 115)
+	// 3. So, in the generated mappings, make sure `S` maps to `ſ`. (83 → 383)
+	// Check if there are any other code points that map to the same `to` value.
+	for (const [otherFrom, otherTo] of oneWayMappings) {
+		if (otherFrom != from && otherTo == to) {
+			// Note: we could use `extend` here, but it’s not necessary as there can
+			// only be a single value for the key `from` at this point.
+			filteredMappings.set(from, otherFrom);
+		}
+	}
+	if (
+		// Include astral code points.
+		(from > 0xFFFF || to > 0xFFFF) ||
+		// Exclude ES5 mappings as per the above comment.
+		// https://mths.be/es6#sec-runtime-semantics-canonicalize-abstract-operation
+		(
+			// TODO: Make this not depend on the engine in which this build script
+			// runs. (If V8 has a bug, then the generated data has the same bug.)
+			!RegExp(String.fromCodePoint(from), 'i').test(String.fromCodePoint(to))
+		)
+	) {
+		extend(filteredMappings, from, to);
+	} else {
+		const stringFrom = String.fromCodePoint(from);
+		const stringTo = String.fromCodePoint(to);
+		const code = `/${
+			jsesc(stringFrom)
+		}/i.test(${
+			jsesc(stringTo, { 'wrap': true })
+		})`;
+		console.log(
+			`Skipping ${ hex(from) } → ${ hex(to) } since ${ code } is already \`true\`.`
+		);
+		// The following snippet was used to create https://mths.be/demo/regex-i.
+		// https://github.com/mathiasbynens/regexpu-core/issues/7#issuecomment-225894534
+		// console.log(
+		// 	`console.assert(${ code }, ${ JSON.stringify(code) });`
+		// );
+	}
+}
+
+// Create a new object containing all `filteredMappings` and their inverse.
+const iuMappings = new Map();
+for (const [from, to] of filteredMappings) {
+	if (Array.isArray(to)) {
+		for (const codePoint of to) {
+			extend(iuMappings, from, codePoint, isES5CasedVariant);
+			extend(iuMappings, codePoint, from, isES5CasedVariant);
+		}
+	} else {
+		extend(iuMappings, from, to, isES5CasedVariant);
+		extend(iuMappings, to, from, isES5CasedVariant);
+	}
+}
+
+writeMap('data/iu-mappings.js', iuMappings);
diff --git a/tests/tests.js b/tests/tests.js
new file mode 100644
index 0000000..66150ae
--- /dev/null
+++ b/tests/tests.js
@@ -0,0 +1,760 @@
+'use strict';
+
+const assert = require('assert');
+const regenerate = require('regenerate');
+const rewritePattern = require('../rewrite-pattern.js');
+const fixtures = require('regexpu-fixtures');
+
+const BMP_SET = regenerate().addRange(0x0, 0xFFFF);
+const BMP_PATTERN = BMP_SET.toString({ 'bmpOnly': true });
+const UNICODE_SET = regenerate().addRange(0x0, 0x10FFFF);
+const UNICODE_PATTERN = UNICODE_SET.toString();
+
+describe('rewritePattern', () => {
+	for (const fixture of fixtures) {
+		const pattern = fixture.pattern;
+		for (const flag of fixture.flags) {
+			it('rewrites `/' + pattern + '/' + flag + '` correctly', () => {
+				assert.equal(rewritePattern(pattern, flag), fixture.transpiled);
+			});
+		}
+	}
+});
+
+const unicodePropertyEscapeFixtures = [
+	// http://unicode.org/reports/tr18/#RL1.2 item 1
+	{
+		'path': 'General_Category/Uppercase_Letter',
+		'expressions': [
+			'gc=Lu',
+			'gc=Uppercase_Letter',
+			'General_Category=Lu',
+			'General_Category=Uppercase_Letter',
+			'Lu',
+			'Uppercase_Letter'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 2a
+	{
+		'path': 'Script/Greek',
+		'expressions': [
+			'sc=Grek',
+			'sc=Greek',
+			'Script=Grek',
+			'Script=Greek'
+		]
+	},
+	{
+		'path': 'Script/Hiragana',
+		'expressions': [
+			'sc=Hira',
+			'sc=Hiragana',
+			'Script=Hira',
+			'Script=Hiragana'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 2b
+	{
+		'path': 'Script_Extensions/Greek',
+		'expressions': [
+			'scx=Grek',
+			'scx=Greek',
+			'Script_Extensions=Grek',
+			'Script_Extensions=Greek'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 3
+	{
+		'path': 'Binary_Property/Alphabetic',
+		'expressions': [
+			'Alpha',
+			'Alphabetic'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 4
+	{
+		'path': 'Binary_Property/Uppercase',
+		'expressions': [
+			'Upper',
+			'Uppercase'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 5
+	{
+		'path': 'Binary_Property/Lowercase',
+		'expressions': [
+			'Lower',
+			'Lowercase'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 6
+	{
+		'path': 'Binary_Property/White_Space',
+		'expressions': [
+			'WSpace',
+			'White_Space'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 7
+	{
+		'path': 'Binary_Property/Noncharacter_Code_Point',
+		'expressions': [
+			'NChar',
+			'Noncharacter_Code_Point'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 8
+	{
+		'path': 'Binary_Property/Default_Ignorable_Code_Point',
+		'expressions': [
+			'DI',
+			'Default_Ignorable_Code_Point'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 9a
+	{
+		'path': 'Binary_Property/Any',
+		'expressions': [
+			'Any'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 9b
+	{
+		'path': 'Binary_Property/ASCII',
+		'expressions': [
+			'ASCII'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL1.2 item 9c
+	{
+		'path': 'Binary_Property/Assigned',
+		'expressions': [
+			'Assigned'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/ASCII_Hex_Digit',
+		'expressions': [
+			'ASCII_Hex_Digit',
+			'AHex'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	// {
+	// 	'path': 'Bidi_Class/Arabic_Letter',
+	// 	'expressions': [
+	// 		'bc=AL',
+	// 		'bc=Arabic_Letter',
+	// 		'Bidi_Class=AL',
+	// 		'Bidi_Class=Arabic_Letter'
+	// 	]
+	// },
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Bidi_Control',
+		'expressions': [
+			'Bidi_C',
+			'Bidi_Control'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	// {
+	// 	'path': 'Block/Alphabetic_Presentation_Forms',
+	// 	'expressions': [
+	// 		'blk=Alphabetic_PF',
+	// 		'blk=Alphabetic_Presentation_Forms',
+	// 		'Block=Alphabetic_PF',
+	// 		'Block=Alphabetic_Presentation_Forms'
+	// 	]
+	// },
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Bidi_Mirrored',
+		'expressions': [
+			'Bidi_M',
+			'Bidi_Mirrored'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Case_Ignorable',
+		'expressions': [
+			'CI',
+			'Case_Ignorable',
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Cased',
+		'expressions': [
+			'Cased'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Changes_When_NFKC_Casefolded',
+		'expressions': [
+			'CWKCF',
+			'Changes_When_NFKC_Casefolded'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Changes_When_Casefolded',
+		'expressions': [
+			'CWCF',
+			'Changes_When_Casefolded'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Changes_When_Casemapped',
+		'expressions': [
+			'CWCM',
+			'Changes_When_Casemapped'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Changes_When_Lowercased',
+		'expressions': [
+			'CWL',
+			'Changes_When_Lowercased'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Changes_When_Titlecased',
+		'expressions': [
+			'CWT',
+			'Changes_When_Titlecased'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Changes_When_Uppercased',
+		'expressions': [
+			'CWU',
+			'Changes_When_Uppercased'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Dash',
+		'expressions': [
+			'Dash'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Deprecated',
+		'expressions': [
+			'Dep',
+			'Deprecated'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Diacritic',
+		'expressions': [
+			'Dia',
+			'Diacritic'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Extender',
+		'expressions': [
+			'Ext',
+			'Extender'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Grapheme_Base',
+		'expressions': [
+			'Gr_Base',
+			'Grapheme_Base'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Grapheme_Extend',
+		'expressions': [
+			'Gr_Ext',
+			'Grapheme_Extend'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Hex_Digit',
+		'expressions': [
+			'Hex',
+			'Hex_Digit'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/ID_Continue',
+		'expressions': [
+			'IDC',
+			'ID_Continue'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/ID_Start',
+		'expressions': [
+			'IDS',
+			'ID_Start'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Ideographic',
+		'expressions': [
+			'Ideo',
+			'Ideographic'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/IDS_Binary_Operator',
+		'expressions': [
+			'IDSB',
+			'IDS_Binary_Operator'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/IDS_Trinary_Operator',
+		'expressions': [
+			'IDST',
+			'IDS_Trinary_Operator'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Join_Control',
+		'expressions': [
+			'Join_C',
+			'Join_Control'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Logical_Order_Exception',
+		'expressions': [
+			'LOE',
+			'Logical_Order_Exception'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Math',
+		'expressions': [
+			'Math'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Pattern_Syntax',
+		'expressions': [
+			'Pat_Syn',
+			'Pattern_Syntax'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Pattern_White_Space',
+		'expressions': [
+			'Pat_WS',
+			'Pattern_White_Space'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Quotation_Mark',
+		'expressions': [
+			'QMark',
+			'Quotation_Mark'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Radical',
+		'expressions': [
+			'Radical'
+		]
+	},
+	{
+		'path': 'Binary_Property/Regional_Indicator',
+		'expressions': [
+			'RI',
+			'Regional_Indicator'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Soft_Dotted',
+		'expressions': [
+			'SD',
+			'Soft_Dotted'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Sentence_Terminal',
+		'expressions': [
+			'STerm',
+			'Sentence_Terminal'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Terminal_Punctuation',
+		'expressions': [
+			'Term',
+			'Terminal_Punctuation'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Unified_Ideograph',
+		'expressions': [
+			'UIdeo',
+			'Unified_Ideograph'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/Variation_Selector',
+		'expressions': [
+			'VS',
+			'Variation_Selector'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/XID_Continue',
+		'expressions': [
+			'XIDC',
+			'XID_Continue'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	{
+		'path': 'Binary_Property/XID_Start',
+		'expressions': [
+			'XIDS',
+			'XID_Start'
+		]
+	},
+	// http://unicode.org/reports/tr18/#RL2.7
+	// {
+	// 	'path': 'Bidi_Paired_Bracket_Type/Open',
+	// 	'expressions': [
+	// 		'bpt=o',
+	// 		'bpt=Open',
+	// 		'Bidi_Paired_Bracket_Type=o',
+	// 		'Bidi_Paired_Bracket_Type=Open'
+	// 	]
+	// },
+	// {
+	// 	'path': 'Block/Superscripts_And_Subscripts',
+	// 	'expressions': [
+	// 		'blk=Super_And_Sub',
+	// 		'blk=Superscripts_And_Subscripts',
+	// 		'Block=Super_And_Sub',
+	// 		'Block=Superscripts_And_Subscripts'
+	// 	]
+	// },
+	// http://unicode.org/reports/tr51/
+	{
+		'path': 'Emoji',
+		'expressions': [
+			'Emoji'
+		]
+	},
+	// http://unicode.org/reports/tr51/
+	{
+		'path': 'Emoji_Component',
+		'expressions': [
+			'Emoji_Component'
+		]
+	},
+	// http://unicode.org/reports/tr51/
+	{
+		'path': 'Emoji_Modifier',
+		'expressions': [
+			'Emoji_Modifier'
+		]
+	},
+	// http://unicode.org/reports/tr51/
+	{
+		'path': 'Emoji_Modifier_Base',
+		'expressions': [
+			'Emoji_Modifier_Base'
+		]
+	},
+	// http://unicode.org/reports/tr51/
+	{
+		'path': 'Emoji_Presentation',
+		'expressions': [
+			'Emoji_Presentation'
+		]
+	},
+	// http://unicode.org/reports/tr51/proposed.html
+	{
+		'path': 'Extended_Pictographic',
+		'expressions': [
+			'Extended_Pictographic'
+		]
+	},
+];
+
+const getPropertyValuePattern = (path) => {
+	const codePoints =
+		(path == 'Extended_Pictographic' || path.startsWith('Emoji')) ?
+		require(`unicode-tr51/${ path }.js`) :
+		require(`unicode-10.0.0/${ path }/code-points.js`);
+	return {
+		'p': regenerate(codePoints).toString(),
+		'P': UNICODE_SET.clone().remove(codePoints).toString()
+	};
+};
+
+describe('unicodePropertyEscapes', () => {
+	const features = {
+		'unicodePropertyEscape': true
+	};
+	for (const fixture of unicodePropertyEscapeFixtures) {
+		const expected = getPropertyValuePattern(fixture.path);
+		for (const pattern of fixture.expressions) {
+			const p = `\\p{${ pattern }}`;
+			it('rewrites `/' + p + '/u` correctly', () => {
+				const transpiled = rewritePattern(p, 'u', features);
+				assert(
+					transpiled == expected.p ||
+					transpiled == '(?:' + expected.p + ')'
+				);
+			});
+			const P = `\\P{${ pattern }}`;
+			it('rewrites `/' + P + '/u` correctly', () => {
+				const transpiled = rewritePattern(P, 'u', features);
+				assert(
+					transpiled == expected.P ||
+					transpiled == '(?:' + expected.P + ')'
+				);
+			});
+		}
+	}
+	it('transpiles Unicode property escapes within various constructions', () => {
+		assert.equal(
+			rewritePattern('\\p{ASCII_Hex_Digit}', 'u', features),
+			'[0-9A-Fa-f]'
+		);
+		assert.equal(
+			rewritePattern('\\p{Script_Extensions=Anatolian_Hieroglyphs}', 'u', features),
+			'(?:\\uD811[\\uDC00-\\uDE46])'
+		);
+		assert.equal(
+			rewritePattern('\\p{ASCII_Hex_Digit}+', 'u', features),
+			'[0-9A-Fa-f]+'
+		);
+		assert.equal(
+			rewritePattern('\\p{Script_Extensions=Anatolian_Hieroglyphs}+', 'u', features),
+			'(?:\\uD811[\\uDC00-\\uDE46])+'
+		);
+		assert.equal(
+			rewritePattern('[\\p{ASCII_Hex_Digit}_]', 'u', features),
+			'[0-9A-F_a-f]'
+		);
+		assert.equal(
+			rewritePattern('[\\P{Script_Extensions=Anatolian_Hieroglyphs}]', 'u', features),
+			'(?:[\\0-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uD810\\uD812-\\uDBFF][\\uDC00-\\uDFFF]|\\uD811[\\uDE47-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF])'
+		);
+		assert.equal(
+			rewritePattern('[\\p{Script_Extensions=Anatolian_Hieroglyphs}_]', 'u', features),
+			'(?:_|\\uD811[\\uDC00-\\uDE46])'
+		);
+		assert.equal(
+			rewritePattern('[\\P{Script_Extensions=Anatolian_Hieroglyphs}_]', 'u', features),
+			'(?:[\\0-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uD810\\uD812-\\uDBFF][\\uDC00-\\uDFFF]|\\uD811[\\uDE47-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF])'
+		);
+		assert.equal(
+			rewritePattern('(?:\\p{ASCII_Hex_Digit})', 'u', features),
+			'(?:[0-9A-Fa-f])'
+		);
+		assert.equal(
+			rewritePattern('(?:\\p{Script_Extensions=Anatolian_Hieroglyphs})', 'u', features),
+			'(?:(?:\\uD811[\\uDC00-\\uDE46]))'
+		);
+	});
+	it('throws without the `u` flag', () => {
+		assert.throws(() => {
+			rewritePattern('\\p{ASCII_Hex_Digit}', '', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{ASCII_Hex_Digit}', '', features);
+		}, Error);
+	});
+	it('throws without the `unicodePropertyEscape` feature enabled', () => {
+		assert.throws(() => {
+			rewritePattern('\\p{ASCII_Hex_Digit}', 'u');
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{ASCII_Hex_Digit}', 'u');
+		}, Error);
+	});
+	it('throws on unknown binary properties', () => {
+		assert.throws(() => {
+			rewritePattern('\\p{UnknownBinaryProperty}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{UnknownBinaryProperty}', 'u', features);
+		}, Error);
+	});
+	it('throws on explicitly unsupported properties', () => {
+		// https://github.com/tc39/proposal-regexp-unicode-property-escapes/issues/27
+		assert.throws(() => {
+			rewritePattern('\\P{Composition_Exclusion}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\p{Expands_On_NFC}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\p{Expands_On_NFD}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\p{Expands_On_NFKC}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\p{Expands_On_NFKD}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\p{FC_NFKC_Closure}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\p{Full_Composition_Exclusion}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Grapheme_Link}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Hyphen}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_Alphabetic}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_Default_Ignorable_Code_Point}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_Grapheme_Extend}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_ID_Continue}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_ID_Start}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_Lowercase}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_Math}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Other_Uppercase}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{Prepended_Concatenation_Mark}', 'u', features);
+		}, Error);
+	});
+	it('throws on non-binary properties without a value', () => {
+		assert.throws(() => {
+			rewritePattern('\\p{General_Category}', 'u', features);
+		}, Error);
+	});
+	it('throws on unknown property values', () => {
+		assert.throws(() => {
+			rewritePattern('\\p{General_Category=UnknownCategory}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{General_Category=UnknownCategory}', 'u', features);
+		}, Error);
+	});
+	it('throws when loose matching is attempted', () => {
+		assert.throws(() => {
+			rewritePattern('\\p{gc=uppercaseletter}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\p{Block=Superscripts and Subscripts}', 'u', features);
+		}, Error);
+		assert.throws(() => {
+			rewritePattern('\\P{_-_lOwEr_C-A_S-E_-_}', 'u', features);
+		}, Error);
+	});
+	it('simplifies the output using Unicode code point escapes when `useUnicodeFlag` is enabled', () => {
+		assert.equal(
+			rewritePattern('\\p{Script_Extensions=Anatolian_Hieroglyphs}', 'u', {
+				'unicodePropertyEscape': true,
+				'useUnicodeFlag': true
+			}),
+			'[\\u{14400}-\\u{14646}]'
+		);
+	});
+	assert.equal(
+		rewritePattern('\u03B8', 'iu'),
+		'[\\u03B8\\u03F4]'
+	);
+	assert.equal(
+		rewritePattern('\u03B8', 'iu', {
+			'useUnicodeFlag': true
+		}),
+		'\\u03B8'
+	);
+});
+
+const dotAllFlagFixtures = [
+	{
+		'pattern': '.',
+		'flags': 's',
+		'expected': BMP_PATTERN
+	},
+	{
+		'pattern': '.',
+		'flags': 'gimsy',
+		'expected': BMP_PATTERN
+	},
+	{
+		'pattern': '.',
+		'flags': 'su',
+		'expected': UNICODE_PATTERN
+	},
+	{
+		'pattern': '.',
+		'flags': 'gimsuy',
+		'expected': UNICODE_PATTERN
+	}
+];
+
+describe('dotAllFlag', () => {
+	const features = {
+		'dotAllFlag': true
+	};
+	for (const fixture of dotAllFlagFixtures) {
+		const pattern = fixture.pattern;
+		const flags = fixture.flags;
+		it('rewrites `/' + pattern + '/' + flags + '` correctly', () => {
+			const transpiled = rewritePattern(pattern, flags, features);
+			const expected = fixture.expected;
+			assert(
+				transpiled == expected ||
+				transpiled == '(?:' + expected + ')'
+			);
+		});
+	}
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-regexpu-core.git



More information about the Pkg-javascript-commits mailing list