Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

various minor

  • Loading branch information...
commit 07686cd42a8d29e249f214d948ef81caebf64354 1 parent 549b310
@slevithan authored
View
6 .gitignore
@@ -2,9 +2,5 @@
*.pyc
# Folder view configuration files
-Desktop.ini
+desktop.ini
.DS_Store
-
-# Thumbnail cache files
-Thumbs.db
-._*
View
44 src/addons/build.js
@@ -1,16 +1,16 @@
/*!
- * XRegExp 2.1.0-rc: XRegExp.build
+ * XRegExp.build 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
* Inspired by Lea Verou's RegExp.create <http://lea.verou.me/>
*/
(function (XRegExp) {
'use strict';
- var subparts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
- parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subparts], 'g');
+ var REGEX_DATA = 'xregexp',
+ subParts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
+ parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subParts], 'g');
/**
* Strips a leading `^` and trailing unescaped `$`, if both are present.
@@ -19,8 +19,8 @@
* @returns {String} Pattern with edge anchors removed.
*/
function deanchor(pattern) {
- var startAnchor = /^(?:\(\?:\))*\^/, // Leading `^` or `(?:)^` (handles /x cruft)
- endAnchor = /\$(?:\(\?:\))*$/; // Trailing `$` or `$(?:)` (handles /x cruft)
+ var startAnchor = /^(?:\(\?:\))*\^/, // Leading `^` or `(?:)^` (handles token cruft)
+ endAnchor = /\$(?:\(\?:\))*$/; // Trailing `$` or `$(?:)` (handles token cruft)
// Ensure that the trailing `$` isn't escaped
if (startAnchor.test(pattern) && endAnchor.test(pattern.replace(/\\[\s\S]/g, ''))) {
return pattern.replace(startAnchor, '').replace(endAnchor, '');
@@ -29,15 +29,18 @@
}
/**
- * Converts the provided value to an XRegExp.
+ * Converts the provided value to an XRegExp. Native RegExp flags are not preserved.
* @private
* @param {String|RegExp} value Value to convert.
* @returns {RegExp} XRegExp object with XRegExp syntax applied.
*/
function asXRegExp(value) {
return XRegExp.isRegExp(value) ?
- (value.xregexp && !value.xregexp.isNative ? value : XRegExp(value.source)) :
- XRegExp(value);
+ (value[REGEX_DATA] && !value[REGEX_DATA].isNative ?
+ value : // No need to recompile
+ XRegExp(value.source) // Recompile native RegExp as XRegExp
+ ) :
+ XRegExp(value); // Compile string as XRegExp
}
/**
@@ -86,21 +89,24 @@
for (p in subs) {
if (subs.hasOwnProperty(p)) {
- // Passing to XRegExp enables extended syntax for subpatterns provided as strings
- // and ensures independent validity, lest an unescaped `(`, `)`, `[`, or trailing
- // `\` breaks the `(?:)` wrapper. For subpatterns provided as regexes, it dies on
- // octals and adds the `xregexp` property, for simplicity
+ // Passing to XRegExp enables extended syntax and ensures independent validity,
+ // lest an unescaped `(`, `)`, `[`, or trailing `\` breaks the `(?:)` wrapper. For
+ // subpatterns provided as native regexes, it dies on octals and adds the property
+ // used to hold extended regex instance data, for simplicity
sub = asXRegExp(subs[p]);
- // Deanchoring allows embedding independently useful anchored regexes. If you
- // really need to keep your anchors, double them (i.e., `^^...$$`)
- data[p] = {pattern: deanchor(sub.source), names: sub.xregexp.captureNames || []};
+ data[p] = {
+ // Deanchoring allows embedding independently useful anchored regexes. If you
+ // really need to keep your anchors, double them (i.e., `^^...$$`)
+ pattern: deanchor(sub.source),
+ names: sub[REGEX_DATA].captureNames || []
+ };
}
}
// Passing to XRegExp dies on octals and ensures the outer pattern is independently valid;
// helps keep this simple. Named captures will be put back
pattern = asXRegExp(pattern);
- outerCapNames = pattern.xregexp.captureNames || [];
+ outerCapNames = pattern[REGEX_DATA].captureNames || [];
pattern = pattern.source.replace(parts, function ($0, $1, $2, $3, $4) {
var subName = $1 || $2, capName, intro;
// Named subpattern
@@ -119,7 +125,7 @@
intro = '(?:';
}
numPriorCaps = numCaps;
- return intro + data[subName].pattern.replace(subparts, function (match, paren, backref) {
+ return intro + data[subName].pattern.replace(subParts, function (match, paren, backref) {
// Capturing group
if (paren) {
capName = data[subName].names[numCaps - numPriorCaps];
View
9 src/addons/matchrecursive.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: XRegExp.matchRecursive
+ * XRegExp.matchRecursive 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2009-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2009-2012 MIT License
*/
(function (XRegExp) {
@@ -100,8 +99,8 @@
// Using `XRegExp.union` safely rewrites backreferences in `left` and `right`
esc = new RegExp(
'(?:' + escapeChar + '[\\S\\s]|(?:(?!' +
- XRegExp.union([left, right]).source +
- ')[^' + escapeChar + '])+)+',
+ XRegExp.union([left, right]).source +
+ ')[^' + escapeChar + '])+)+',
// Flags `gy` not needed here
flags.replace(/[^im]+/g, '')
);
View
5 src/addons/prototypes.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: Prototypes
+ * XRegExp Prototypes 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
*/
/**
View
17 src/addons/unicode/unicode-base.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: Unicode Base
+ * XRegExp Unicode Base 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2008-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2008-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -51,8 +50,8 @@
function charCode(chr) {
var esc = /^\\[xu](.+)/.exec(chr);
return esc ?
- dec(esc[1]) :
- chr.charCodeAt(chr.charAt(0) === '\\' ? 1 : 0);
+ dec(esc[1]) :
+ chr.charCodeAt(chr.charAt(0) === '\\' ? 1 : 0);
}
// Inverts a list of BMP characters and ranges
@@ -102,8 +101,8 @@
}
// Astral Unicode tokens always match a code point, never a code unit
return negated ?
- '(?:(?!' + combined + ')(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))' :
- '(?:' + combined + ')';
+ '(?:(?!' + combined + ')(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))' :
+ '(?:' + combined + ')';
}
// Builds a complete astral pattern on first use
@@ -145,8 +144,8 @@
return cacheAstral(slug, negated);
}
return scope === 'class' ?
- (negated ? cacheInvertedBmp(slug) : item.bmp) :
- (negated ? '[^' : '[') + item.bmp + ']';
+ (negated ? cacheInvertedBmp(slug) : item.bmp) :
+ (negated ? '[^' : '[') + item.bmp + ']';
},
{
scope: 'all',
View
5 src/addons/unicode/unicode-blocks.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: Unicode Blocks
+ * XRegExp Unicode Blocks 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2010-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
View
5 src/addons/unicode/unicode-categories.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: Unicode Categories
+ * XRegExp Unicode Categories 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2010-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
View
7 src/addons/unicode/unicode-properties.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: Unicode Properties
+ * XRegExp Unicode Properties 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -31,7 +30,7 @@
bmp: 'A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05B0-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0657\u0659-\u065F\u066E-\u06D3\u06D5-\u06DC\u06E1-\u06E8\u06ED-\u06EF\u06FA-\u06FC\u06FF\u0710-\u073F\u074D-\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0817\u081A-\u082C\u0840-\u0858\u08A0\u08A2-\u08AC\u08E4-\u08E9\u08F0-\u08FE\u0900-\u093B\u093D-\u094C\u094E-\u0950\u0955-\u0963\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD-\u09C4\u09C7\u09C8\u09CB\u09CC\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09F0\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3E-\u0A42\u0A47\u0A48\u0A4B\u0A4C\u0A51\u0A59-\u0A5C\u0A5E\u0A70-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD-\u0AC5\u0AC7-\u0AC9\u0ACB\u0ACC\u0AD0\u0AE0-\u0AE3\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D-\u0B44\u0B47\u0B48\u0B4B\u0B4C\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD0\u0BD7\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4C\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCC\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4C\u0D4E\u0D57\u0D60-\u0D63\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E46\u0E4D\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0ECD\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F71-\u0F81\u0F88-\u0F97\u0F99-\u0FBC\u1000-\u1036\u1038\u103B-\u103F\u1050-\u1062\u1065-\u1068\u106E-\u1086\u108E\u109C\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1713\u1720-\u1733\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17B3\u17B6-\u17C8\u17D7\u17DC\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B\u1930-\u1938\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A1B\u1A20-\u1A5E\u1A61-\u1A74\u1AA7\u1B00-\u1B33\u1B35-\u1B43\u1B45-\u1B4B\u1B80-\u1BA9\u1BAC-\u1BAF\u1BBA-\u1BE5\u1BE7-\u1BF1\u1C00-\u1C35\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u24B6-\u24E9\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA674-\uA67B\uA67F-\uA697\uA69F-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA827\uA840-\uA873\uA880-\uA8C3\uA8F2-\uA8F7\uA8FB\uA90A-\uA92A\uA930-\uA952\uA960-\uA97C\uA980-\uA9B2\uA9B4-\uA9BF\uA9CF\uAA00-\uAA36\uAA40-\uAA4D\uAA60-\uAA76\uAA7A\uAA80-\uAABE\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF5\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC',
astral: '\uD803[\uDC00-\uDC48]|\uD801[\uDC00-\uDC9D]|\uD809[\uDC00-\uDC62]|\uD81A[\uDC00-\uDE38]|\uD804[\uDC00-\uDC45\uDC82-\uDCB8\uDCD0-\uDCE8\uDD00-\uDD32\uDD80-\uDDBF\uDDC1-\uDDC4]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD87E[\uDC00-\uDE1D]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1E\uDF30-\uDF4A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF93-\uDF9F]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD82C[\uDC00\uDC01]|\uD808[\uDC00-\uDF6E]|\uD805[\uDE80-\uDEB5]'
},
- // NOTE: In BMP-only mode, `[\p{^Any}]` compiles to `[]`
+ // Assert: In BMP-only mode, `[\p{^Any}]` compiles to `[]`
{
name: 'Any',
isBmpLast: true,
View
5 src/addons/unicode/unicode-scripts.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: Unicode Scripts
+ * XRegExp Unicode Scripts 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2010-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
View
15 src/backcompat.js
@@ -1,8 +1,7 @@
/*!
- * XRegExp 2.1.0-rc: BackCompat
+ * XRegExp BackCompat 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
*/
/**
@@ -11,6 +10,8 @@
(function (XRegExp) {
'use strict';
+ var REGEX_DATA = 'xregexp';
+
/**
* XRegExp 2.0.0 doesn't override native methods or allow syntax extensions by default.
*/
@@ -66,8 +67,8 @@
this.source,
/\/([a-z]*)$/i.exec(String(this))[1] + (flags || '')
),
- captureNames = this.xregexp ? this.xregexp.captureNames : null;
- regex.xregexp = {
+ captureNames = this[REGEX_DATA] ? this[REGEX_DATA].captureNames : null;
+ regex[REGEX_DATA] = {
captureNames: captureNames ? captureNames.slice(0) : null,
isNative: false // Always passed through `XRegExp`
};
@@ -100,8 +101,8 @@
*/
RegExp.prototype.execAll = function (str) {
return XRegExp.forEach(str, this, function (match) {
- this.push(match);
- }, []);
+ this.push(match);
+ }, []);
};
}(XRegExp));
View
203 src/xregexp.js
@@ -1,8 +1,7 @@
/*!
* XRegExp 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2007-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2007-2012 MIT License
*/
/**
@@ -20,12 +19,11 @@ var XRegExp = (function () {
var // ...
-// Internal reference to the XRegExp global object
- self,
+// Property name used for extended regex instance data
+ REGEX_DATA = 'xregexp',
-// Shortcuts
- addToken,
- add,
+// Internal reference to the `XRegExp` object
+ self,
// Optional features; can be installed and uninstalled
features = {
@@ -46,10 +44,10 @@ var XRegExp = (function () {
// Storage for fixed/extended native methods
fixed = {},
-// Storage for cached regexes
+// Storage for regexes cached by `XRegExp.cache`
cache = {},
-// Storage for addon tokens
+// Storage for syntax tokens added internally or by `XRegExp.addToken`
tokens = [],
// Token scopes
@@ -59,12 +57,12 @@ var XRegExp = (function () {
// Regexes that match native regex syntax
nativeTokens = {
// Any native multicharacter token in default scope (includes octals, excludes character classes)
- 'default': /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/,
+ 'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??/,
// Any native multicharacter token in character class scope (includes octals)
- 'class': /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/
+ 'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])/
},
-// Any backreference or dollar-prefixed metacharacter in replacement strings
+// Any backreference or dollar-prefixed character in replacement strings
replacementToken = /\$(?:{([\w$]+)}|(\d\d?|[\s\S]))/g,
// Any character with a later instance in the string
@@ -83,7 +81,13 @@ var XRegExp = (function () {
isInsideConstructor = false,
// Storage for known flags, including addon flags
- registeredFlags = 'gim' + (hasNativeY ? 'y' : '');
+ registeredFlags = 'gim' + (hasNativeY ? 'y' : ''),
+
+// Storage for the installed and uninstalled states of `XRegExp.addToken`
+ addToken = {},
+
+// Shortcut to `addToken.on`
+ add;
/*--------------------------------------
* Private helper functions
@@ -113,7 +117,11 @@ var XRegExp = (function () {
}
}
}
- regex.xregexp = {captureNames: captureNames, isNative: !!isNative};
+ regex[REGEX_DATA] = {
+ captureNames: captureNames,
+ // Ensure that `undefined` is type-converted to `false`
+ isNative: !!isNative
+ };
return regex;
}
@@ -141,12 +149,15 @@ var XRegExp = (function () {
// Would need to escape `options.remove` if this was public
flags = nativ.replace.call(flags, new RegExp('[' + options.remove + ']+', 'g'), '');
}
- if (regex.xregexp && !regex.xregexp.isNative) {
+ if (regex[REGEX_DATA] && !regex[REGEX_DATA].isNative) {
// Compiling the current (rather than precompilation) source preserves the effects of
// nonnative source flags
regex = augment(
self(regex.source, flags),
- regex.xregexp.captureNames ? regex.xregexp.captureNames.slice(0) : null,
+ regex[REGEX_DATA].captureNames ?
+ // Create a new copy of the array
+ regex[REGEX_DATA].captureNames.slice(0) :
+ null,
options.addProto
//,false // !isNative
);
@@ -159,7 +170,8 @@ var XRegExp = (function () {
}
/**
- * Returns a new copy of the `xregexp` object used for native nonaugmented regexes.
+ * Returns a new copy of the object used to hold extended regex instance data, tailored for a
+ * native nonaugmented regex.
* @private
* @returns {Object} Object with `captureNames` and `isNative` properties.
*/
@@ -210,8 +222,8 @@ var XRegExp = (function () {
value = value || {};
if (isType(value, 'String')) {
value = self.forEach(value, /[^\s,]+/, function (match) {
- this[match] = true;
- }, {});
+ this[match] = true;
+ }, {});
}
return value;
}
@@ -241,7 +253,7 @@ var XRegExp = (function () {
(t.scope === 'all' || t.scope === scope) &&
(!t.trigger || t.trigger.call(context))
) {
- match = self.exec(pattern, t.pattern, pos, 'sticky');
+ match = self.exec(pattern, t.regex, pos, 'sticky');
if (match) {
result = {
output: t.handler.call(context, match, scope),
@@ -415,33 +427,36 @@ var XRegExp = (function () {
* Public methods/properties
*------------------------------------*/
-// Installed and uninstalled states for `XRegExp.addToken`
- addToken = {
- on: function (regex, handler, options) {
- options = options || {};
- if (regex) {
- tokens.push({
- pattern: copy(regex, {add: 'g' + (hasNativeY ? 'y' : '')}),
- handler: handler,
- scope: options.scope || defaultScope,
- trigger: options.trigger || null
- });
- }
- // Providing `customFlags` with null `regex` and `handler` allows adding flags that do
- // nothing, but don't throw an error
- if (options.customFlags) {
- registeredFlags = nativ.replace.call(
- registeredFlags + options.customFlags,
- duplicateFlags,
- ''
- );
- }
- },
- off: function () {
- throw new Error('Extensibility must be installed before using addToken');
+// Installed state for `XRegExp.addToken` (private)
+ addToken.on = function (regex, handler, options) {
+ options = options || {};
+ if (regex) {
+ // Add to the private list of syntax tokens
+ tokens.push({
+ regex: copy(regex, {add: 'g' + (hasNativeY ? 'y' : '')}),
+ handler: handler,
+ scope: options.scope || defaultScope,
+ trigger: options.trigger || null
+ });
+ }
+ // Assert: By providing `customFlags` with null `regex` and `handler`, you can add no-op
+ // flags that don't throw an error
+ if (options.customFlags) {
+ registeredFlags = nativ.replace.call(
+ registeredFlags + options.customFlags,
+ duplicateFlags,
+ ''
+ );
}
};
+// Uninstalled state for `XRegExp.addToken` (private)
+ addToken.off = function () {
+ // By making extensibility an optional feature, users are able to delete or override
+ // `XRegExp.install` if they want to lock down any further syntax extensions
+ throw new Error('Extensibility must be installed before calling addToken');
+ };
+
/**
* Extends or changes XRegExp syntax and allows custom flags. This is used internally and can be
* used to create XRegExp addons. `XRegExp.install('extensibility')` must be run before calling
@@ -540,10 +555,10 @@ var XRegExp = (function () {
if (hasNativeY && (sticky || (regex.sticky && sticky !== false))) {
cacheFlags += 'y';
}
- regex.xregexp = regex.xregexp || getBaseProps();
+ regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
// Shares cached copies with `XRegExp.match`/`replace`
- r2 = regex.xregexp[cacheFlags] || (
- regex.xregexp[cacheFlags] = copy(regex, {
+ r2 = regex[REGEX_DATA][cacheFlags] || (
+ regex[REGEX_DATA][cacheFlags] = copy(regex, {
add: cacheFlags,
remove: sticky === false ? 'y' : ''
})
@@ -711,10 +726,10 @@ var XRegExp = (function () {
cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''),
result,
r2;
- regex.xregexp = regex.xregexp || getBaseProps();
+ regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
// Shares cached copies with `XRegExp.exec`/`replace`
- r2 = regex.xregexp[cacheFlags || 'noGY'] || (
- regex.xregexp[cacheFlags || 'noGY'] = copy(regex, {
+ r2 = regex[REGEX_DATA][cacheFlags || 'noGY'] || (
+ regex[REGEX_DATA][cacheFlags || 'noGY'] = copy(regex, {
add: cacheFlags,
remove: scope === 'one' ? 'g' : ''
})
@@ -765,8 +780,8 @@ var XRegExp = (function () {
self.forEach(values[i], item.regex, addMatch);
}
return ((level === chain.length - 1) || !matches.length) ?
- matches :
- recurseChain(matches, level + 1);
+ matches :
+ recurseChain(matches, level + 1);
}([str], 0));
};
@@ -823,11 +838,11 @@ var XRegExp = (function () {
s2 = search,
result;
if (isRegex) {
- search.xregexp = search.xregexp || getBaseProps();
+ search[REGEX_DATA] = search[REGEX_DATA] || getBaseProps();
// Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used,
// `search`'s `lastIndex` isn't updated *during* replacement iterations
- s2 = search.xregexp[cacheFlags || 'noGY'] || (
- search.xregexp[cacheFlags || 'noGY'] = copy(search, {
+ s2 = search[REGEX_DATA][cacheFlags || 'noGY'] || (
+ search[REGEX_DATA][cacheFlags || 'noGY'] = copy(search, {
add: cacheFlags,
remove: scope === 'one' ? 'g' : ''
})
@@ -1013,7 +1028,7 @@ var XRegExp = (function () {
pattern = patterns[i];
if (self.isRegExp(pattern)) {
numPriorCaptures = numCaptures;
- captureNames = (pattern.xregexp && pattern.xregexp.captureNames) || [];
+ captureNames = (pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames) || [];
// Rewrite backreferences. Passing to XRegExp dies on octals and ensures patterns
// are independently valid; helps keep this simple. Named captures are put back
output.push(self(pattern.source).source.replace(parts, rewrite));
@@ -1071,10 +1086,10 @@ var XRegExp = (function () {
});
}
// Attach named capture properties
- if (this.xregexp && this.xregexp.captureNames) {
+ if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
// Skip index 0
for (i = 1; i < match.length; ++i) {
- name = this.xregexp.captureNames[i - 1];
+ name = this[REGEX_DATA].captureNames[i - 1];
if (name) {
match[name] = match[i];
}
@@ -1147,8 +1162,8 @@ var XRegExp = (function () {
origLastIndex;
if (isRegex) {
- if (search.xregexp) {
- captureNames = search.xregexp.captureNames;
+ if (search[REGEX_DATA]) {
+ captureNames = search[REGEX_DATA].captureNames;
}
if (!search.global) {
origLastIndex = search.lastIndex;
@@ -1274,13 +1289,11 @@ var XRegExp = (function () {
// Browsers handle nonregex split correctly, so use the faster native method
return nativ.split.apply(this, arguments);
}
-
var str = String(this),
origLastIndex = separator.lastIndex,
output = [],
lastLastIndex = 0,
lastLength;
-
/* Values for `limit`, per the spec:
* If undefined: pow(2,32) - 1
* If 0, Infinity, or NaN: 0
@@ -1289,7 +1302,6 @@ var XRegExp = (function () {
* If other: Type-convert, then use the above rules
*/
limit = (limit === undefined ? -1 : limit) >>> 0;
-
self.forEach(str, separator, function (match) {
// This condition is not the same as `if (match[0].length)`
if ((match.index + match[0].length) > lastLastIndex) {
@@ -1308,9 +1320,7 @@ var XRegExp = (function () {
} else {
output.push(str.slice(lastLastIndex));
}
-
separator.lastIndex = origLastIndex;
-
return output.length > limit ? output.slice(0, limit) : output;
};
@@ -1318,14 +1328,14 @@ var XRegExp = (function () {
* Built-in syntax/flag tokens
*------------------------------------*/
-// Shortcut
add = addToken.on;
/* Letter identity escapes that natively match literal characters: `\a`, `\A`, etc. These should be
* SyntaxErrors but are allowed in web reality. XRegExp makes them errors for cross-browser
* consistency and to reserve their syntax, but lets them be superseded by addons.
*/
- add(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/,
+ add(
+ /\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/,
function (match, scope) {
// \B is allowed in default scope only
if (match[1] === 'B' && scope === defaultScope) {
@@ -1333,33 +1343,39 @@ var XRegExp = (function () {
}
throw new SyntaxError('Invalid escape ' + match[0]);
},
- {scope: 'all'});
+ {scope: 'all'}
+ );
/* Empty character class: `[]` or `[^]`. This fixes a critical cross-browser syntax inconsistency.
* Unless this is standardized (per the ES spec), regex syntax can't be accurately parsed because
* character class endings can't be determined.
*/
- add(/\[(\^?)]/,
+ add(
+ /\[(\^?)]/,
function (match) {
// For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].
// (?!) should work like \b\B, but is unreliable in some versions of Firefox
return match[1] ? '[\\s\\S]' : '\\b\\B';
- });
+ }
+ );
/* Comment pattern: `(?# )`. Inline comments are an alternative to the line comments allowed in
* free-spacing mode (flag x).
*/
- add(/\(\?#[^)]*\)/,
+ add(
+ /\(\?#[^)]*\)/,
function (match) {
// Keep tokens separated unless the following token is a quantifier
return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ?
- '' : '(?:)';
- });
+ '' : '(?:)';
+ }
+ );
/* Named backreference: `\k<name>`. Backreference names can use the characters A-Z, a-z, 0-9, _,
* and $ only.
*/
- add(/\\k<([\w$]+)>/,
+ add(
+ /\\k<([\w$]+)>/,
function (match) {
// Groups with the same name is an error, else would need `lastIndexOf`
var index = isNaN(match[1]) ? (indexOf(this.captureNames, match[1]) + 1) : +match[1],
@@ -1370,28 +1386,32 @@ var XRegExp = (function () {
// Keep backreferences separate from subsequent literal numbers
return '\\' + index + (
endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ?
- '' : '(?:)'
+ '' : '(?:)'
);
- });
+ }
+ );
/* Whitespace and line comments, in free-spacing mode (aka extended mode, flag x) only.
*/
- add(/(?:\s+|#.*)+/,
+ add(
+ /(?:\s+|#.*)+/,
function (match) {
// Keep tokens separated unless the following token is a quantifier
return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ?
- '' : '(?:)';
+ '' : '(?:)';
},
{
trigger: function () {
return this.hasFlag('x');
},
customFlags: 'x'
- });
+ }
+ );
/* Dot, in dotall mode (aka singleline mode, flag s) only.
*/
- add(/\./,
+ add(
+ /\./,
function () {
return '[\\s\\S]';
},
@@ -1400,7 +1420,8 @@ var XRegExp = (function () {
return this.hasFlag('s');
},
customFlags: 's'
- });
+ }
+ );
/* Named capturing group; match the opening delimiter only: `(?<name>`. Capture names can use the
* characters A-Z, a-z, 0-9, _, and $ only. Names can't be integers. Supports Python-style
@@ -1408,7 +1429,8 @@ var XRegExp = (function () {
* Python-style syntax). Otherwise, XRegExp might treat numbered backreferences to Python-style
* named capture as octals.
*/
- add(/\(\?P?<([\w$]+)>/,
+ add(
+ /\(\?P?<([\w$]+)>/,
function (match) {
// Disallow bare integers as names because named backreferences are added to match
// arrays and therefore numeric properties may lead to incorrect lookups
@@ -1421,13 +1443,15 @@ var XRegExp = (function () {
this.captureNames.push(match[1]);
this.hasNamedCapture = true;
return '(';
- });
+ }
+ );
/* Numbered backreference or octal, plus any following digits: `\0`, `\11`, etc. Octals except `\0`
* not followed by 0-9 and backreferences to unopened capture groups throw an error. Other matches
* are returned unaltered. IE < 9 doesn't support backreferences above `\99` in regex syntax.
*/
- add(/\\(\d+)/,
+ add(
+ /\\(\d+)/,
function (match, scope) {
if (
!(
@@ -1438,16 +1462,18 @@ var XRegExp = (function () {
match[1] !== '0'
) {
throw new SyntaxError('Cannot use octal escape or backreference to undefined group ' +
- match[0]);
+ match[0]);
}
return match[0];
},
- {scope: 'all'});
+ {scope: 'all'}
+ );
/* Capturing group; match the opening parenthesis only. Required for support of named capturing
* groups. Also adds explicit capture mode (flag n).
*/
- add(/\((?!\?)/,
+ add(
+ /\((?!\?)/,
function () {
if (this.hasFlag('n')) {
return '(?:';
@@ -1455,7 +1481,8 @@ var XRegExp = (function () {
this.captureNames.push(null);
return '(';
},
- {customFlags: 'n'});
+ {customFlags: 'n'}
+ );
/*--------------------------------------
* Expose XRegExp
View
33 tests/tests.js
@@ -73,30 +73,41 @@ test('XRegExp', function () {
test('XRegExp.addToken', function () {
XRegExp.install('extensibility');
- XRegExp.addToken(/\x01/, function () {return '1';});
- XRegExp.addToken(/\x02/, function () {return '2';}, {scope: 'class'});
- XRegExp.addToken(/\x03/, function () {return '3';}, {scope: 'default'});
- XRegExp.addToken(/\x04/, function () {return '4';}, {scope: 'all'});
- XRegExp.addToken(/\x05/, function () {return '5';}, {
- scope: 'default',
- trigger: function () {return this.hasFlag('5');},
- customFlags: '5'
- });
- XRegExp.addToken(/^\x06/, function () {return '6';});
- XRegExp.uninstall('extensibility');
+ XRegExp.addToken(/\x01/, function () {return '1';});
ok(XRegExp('\x01').test('1'), 'Default scope matches outside class');
ok(!XRegExp('[\x01]').test('1'), 'Default scope does not match inside class');
+
+ XRegExp.addToken(/\x02/, function () {return '2';}, {scope: 'class'});
ok(!XRegExp('\x02').test('2'), 'Explicit class scope does not match outside class');
ok(XRegExp('[\x02]').test('2'), 'Explicit class scope matches inside class');
+
+ XRegExp.addToken(/\x03/, function () {return '3';}, {scope: 'default'});
ok(XRegExp('\x03').test('3'), 'Explicit default scope matches outside class');
ok(!XRegExp('[\x03]').test('3'), 'Explicit default scope does not match inside class');
+
+ XRegExp.addToken(/\x04/, function () {return '4';}, {scope: 'all'});
ok(XRegExp('\x04').test('4'), 'Explicit all scope matches outside class');
ok(XRegExp('[\x04]').test('4'), 'Explicit all scope matches inside class');
+
+ XRegExp.addToken(/\x05/, function () {return '5';}, {
+ trigger: function () {return this.hasFlag('5');},
+ customFlags: '5'
+ });
ok(!XRegExp('\x05').test('5'), 'Trigger with hasFlag skips token when flag is missing');
ok(XRegExp('\x05', '5').test('5'), 'Trigger with hasFlag uses token when flag is included');
+
+ XRegExp.addToken(/^\x06/, function () {return '6';});
ok(XRegExp('\x06').test('6'), 'Token with anchor applied when found at start of pattern');
ok(!XRegExp('a\x06').test('6'), 'Token with anchor not applied when found after start of pattern');
+
+ // Include the `/` delimiters in case of naive string conversion
+ raises(function () {XRegExp.addToken('/7/', function () {return '';});}, TypeError, 'Cannot provide string as regex pattern');
+
+ XRegExp.addToken(/x00/, function () {return 'BOOM';});
+ ok(XRegExp('^x\\x00$').test('x\x00'), 'Native multicharacter token in default scope handled correctly when not overriden');
+
+ XRegExp.uninstall('extensibility');
});
test('XRegExp.cache', function () {
View
300 xregexp-all.js
@@ -5,8 +5,7 @@
/*!
* XRegExp 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2007-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2007-2012 MIT License
*/
/**
@@ -24,12 +23,11 @@ var XRegExp = (function () {
var // ...
-// Internal reference to the XRegExp global object
- self,
+// Property name used for extended regex instance data
+ REGEX_DATA = 'xregexp',
-// Shortcuts
- addToken,
- add,
+// Internal reference to the `XRegExp` object
+ self,
// Optional features; can be installed and uninstalled
features = {
@@ -50,10 +48,10 @@ var XRegExp = (function () {
// Storage for fixed/extended native methods
fixed = {},
-// Storage for cached regexes
+// Storage for regexes cached by `XRegExp.cache`
cache = {},
-// Storage for addon tokens
+// Storage for syntax tokens added internally or by `XRegExp.addToken`
tokens = [],
// Token scopes
@@ -63,12 +61,12 @@ var XRegExp = (function () {
// Regexes that match native regex syntax
nativeTokens = {
// Any native multicharacter token in default scope (includes octals, excludes character classes)
- 'default': /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/,
+ 'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??/,
// Any native multicharacter token in character class scope (includes octals)
- 'class': /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/
+ 'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])/
},
-// Any backreference or dollar-prefixed metacharacter in replacement strings
+// Any backreference or dollar-prefixed character in replacement strings
replacementToken = /\$(?:{([\w$]+)}|(\d\d?|[\s\S]))/g,
// Any character with a later instance in the string
@@ -87,7 +85,13 @@ var XRegExp = (function () {
isInsideConstructor = false,
// Storage for known flags, including addon flags
- registeredFlags = 'gim' + (hasNativeY ? 'y' : '');
+ registeredFlags = 'gim' + (hasNativeY ? 'y' : ''),
+
+// Storage for the installed and uninstalled states of `XRegExp.addToken`
+ addToken = {},
+
+// Shortcut to `addToken.on`
+ add;
/*--------------------------------------
* Private helper functions
@@ -117,7 +121,11 @@ var XRegExp = (function () {
}
}
}
- regex.xregexp = {captureNames: captureNames, isNative: !!isNative};
+ regex[REGEX_DATA] = {
+ captureNames: captureNames,
+ // Ensure that `undefined` is type-converted to `false`
+ isNative: !!isNative
+ };
return regex;
}
@@ -145,12 +153,15 @@ var XRegExp = (function () {
// Would need to escape `options.remove` if this was public
flags = nativ.replace.call(flags, new RegExp('[' + options.remove + ']+', 'g'), '');
}
- if (regex.xregexp && !regex.xregexp.isNative) {
+ if (regex[REGEX_DATA] && !regex[REGEX_DATA].isNative) {
// Compiling the current (rather than precompilation) source preserves the effects of
// nonnative source flags
regex = augment(
self(regex.source, flags),
- regex.xregexp.captureNames ? regex.xregexp.captureNames.slice(0) : null,
+ regex[REGEX_DATA].captureNames ?
+ // Create a new copy of the array
+ regex[REGEX_DATA].captureNames.slice(0) :
+ null,
options.addProto
//,false // !isNative
);
@@ -163,7 +174,8 @@ var XRegExp = (function () {
}
/**
- * Returns a new copy of the `xregexp` object used for native nonaugmented regexes.
+ * Returns a new copy of the object used to hold extended regex instance data, tailored for a
+ * native nonaugmented regex.
* @private
* @returns {Object} Object with `captureNames` and `isNative` properties.
*/
@@ -214,8 +226,8 @@ var XRegExp = (function () {
value = value || {};
if (isType(value, 'String')) {
value = self.forEach(value, /[^\s,]+/, function (match) {
- this[match] = true;
- }, {});
+ this[match] = true;
+ }, {});
}
return value;
}
@@ -245,7 +257,7 @@ var XRegExp = (function () {
(t.scope === 'all' || t.scope === scope) &&
(!t.trigger || t.trigger.call(context))
) {
- match = self.exec(pattern, t.pattern, pos, 'sticky');
+ match = self.exec(pattern, t.regex, pos, 'sticky');
if (match) {
result = {
output: t.handler.call(context, match, scope),
@@ -419,33 +431,36 @@ var XRegExp = (function () {
* Public methods/properties
*------------------------------------*/
-// Installed and uninstalled states for `XRegExp.addToken`
- addToken = {
- on: function (regex, handler, options) {
- options = options || {};
- if (regex) {
- tokens.push({
- pattern: copy(regex, {add: 'g' + (hasNativeY ? 'y' : '')}),
- handler: handler,
- scope: options.scope || defaultScope,
- trigger: options.trigger || null
- });
- }
- // Providing `customFlags` with null `regex` and `handler` allows adding flags that do
- // nothing, but don't throw an error
- if (options.customFlags) {
- registeredFlags = nativ.replace.call(
- registeredFlags + options.customFlags,
- duplicateFlags,
- ''
- );
- }
- },
- off: function () {
- throw new Error('Extensibility must be installed before using addToken');
+// Installed state for `XRegExp.addToken` (private)
+ addToken.on = function (regex, handler, options) {
+ options = options || {};
+ if (regex) {
+ // Add to the private list of syntax tokens
+ tokens.push({
+ regex: copy(regex, {add: 'g' + (hasNativeY ? 'y' : '')}),
+ handler: handler,
+ scope: options.scope || defaultScope,
+ trigger: options.trigger || null
+ });
+ }
+ // Assert: By providing `customFlags` with null `regex` and `handler`, you can add no-op
+ // flags that don't throw an error
+ if (options.customFlags) {
+ registeredFlags = nativ.replace.call(
+ registeredFlags + options.customFlags,
+ duplicateFlags,
+ ''
+ );
}
};
+// Uninstalled state for `XRegExp.addToken` (private)
+ addToken.off = function () {
+ // By making extensibility an optional feature, users are able to delete or override
+ // `XRegExp.install` if they want to lock down any further syntax extensions
+ throw new Error('Extensibility must be installed before calling addToken');
+ };
+
/**
* Extends or changes XRegExp syntax and allows custom flags. This is used internally and can be
* used to create XRegExp addons. `XRegExp.install('extensibility')` must be run before calling
@@ -544,10 +559,10 @@ var XRegExp = (function () {
if (hasNativeY && (sticky || (regex.sticky && sticky !== false))) {
cacheFlags += 'y';
}
- regex.xregexp = regex.xregexp || getBaseProps();
+ regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
// Shares cached copies with `XRegExp.match`/`replace`
- r2 = regex.xregexp[cacheFlags] || (
- regex.xregexp[cacheFlags] = copy(regex, {
+ r2 = regex[REGEX_DATA][cacheFlags] || (
+ regex[REGEX_DATA][cacheFlags] = copy(regex, {
add: cacheFlags,
remove: sticky === false ? 'y' : ''
})
@@ -715,10 +730,10 @@ var XRegExp = (function () {
cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''),
result,
r2;
- regex.xregexp = regex.xregexp || getBaseProps();
+ regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
// Shares cached copies with `XRegExp.exec`/`replace`
- r2 = regex.xregexp[cacheFlags || 'noGY'] || (
- regex.xregexp[cacheFlags || 'noGY'] = copy(regex, {
+ r2 = regex[REGEX_DATA][cacheFlags || 'noGY'] || (
+ regex[REGEX_DATA][cacheFlags || 'noGY'] = copy(regex, {
add: cacheFlags,
remove: scope === 'one' ? 'g' : ''
})
@@ -769,8 +784,8 @@ var XRegExp = (function () {
self.forEach(values[i], item.regex, addMatch);
}
return ((level === chain.length - 1) || !matches.length) ?
- matches :
- recurseChain(matches, level + 1);
+ matches :
+ recurseChain(matches, level + 1);
}([str], 0));
};
@@ -827,11 +842,11 @@ var XRegExp = (function () {
s2 = search,
result;
if (isRegex) {
- search.xregexp = search.xregexp || getBaseProps();
+ search[REGEX_DATA] = search[REGEX_DATA] || getBaseProps();
// Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used,
// `search`'s `lastIndex` isn't updated *during* replacement iterations
- s2 = search.xregexp[cacheFlags || 'noGY'] || (
- search.xregexp[cacheFlags || 'noGY'] = copy(search, {
+ s2 = search[REGEX_DATA][cacheFlags || 'noGY'] || (
+ search[REGEX_DATA][cacheFlags || 'noGY'] = copy(search, {
add: cacheFlags,
remove: scope === 'one' ? 'g' : ''
})
@@ -1017,7 +1032,7 @@ var XRegExp = (function () {
pattern = patterns[i];
if (self.isRegExp(pattern)) {
numPriorCaptures = numCaptures;
- captureNames = (pattern.xregexp && pattern.xregexp.captureNames) || [];
+ captureNames = (pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames) || [];
// Rewrite backreferences. Passing to XRegExp dies on octals and ensures patterns
// are independently valid; helps keep this simple. Named captures are put back
output.push(self(pattern.source).source.replace(parts, rewrite));
@@ -1075,10 +1090,10 @@ var XRegExp = (function () {
});
}
// Attach named capture properties
- if (this.xregexp && this.xregexp.captureNames) {
+ if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
// Skip index 0
for (i = 1; i < match.length; ++i) {
- name = this.xregexp.captureNames[i - 1];
+ name = this[REGEX_DATA].captureNames[i - 1];
if (name) {
match[name] = match[i];
}
@@ -1151,8 +1166,8 @@ var XRegExp = (function () {
origLastIndex;
if (isRegex) {
- if (search.xregexp) {
- captureNames = search.xregexp.captureNames;
+ if (search[REGEX_DATA]) {
+ captureNames = search[REGEX_DATA].captureNames;
}
if (!search.global) {
origLastIndex = search.lastIndex;
@@ -1278,13 +1293,11 @@ var XRegExp = (function () {
// Browsers handle nonregex split correctly, so use the faster native method
return nativ.split.apply(this, arguments);
}
-
var str = String(this),
origLastIndex = separator.lastIndex,
output = [],
lastLastIndex = 0,
lastLength;
-
/* Values for `limit`, per the spec:
* If undefined: pow(2,32) - 1
* If 0, Infinity, or NaN: 0
@@ -1293,7 +1306,6 @@ var XRegExp = (function () {
* If other: Type-convert, then use the above rules
*/
limit = (limit === undefined ? -1 : limit) >>> 0;
-
self.forEach(str, separator, function (match) {
// This condition is not the same as `if (match[0].length)`
if ((match.index + match[0].length) > lastLastIndex) {
@@ -1312,9 +1324,7 @@ var XRegExp = (function () {
} else {
output.push(str.slice(lastLastIndex));
}
-
separator.lastIndex = origLastIndex;
-
return output.length > limit ? output.slice(0, limit) : output;
};
@@ -1322,14 +1332,14 @@ var XRegExp = (function () {
* Built-in syntax/flag tokens
*------------------------------------*/
-// Shortcut
add = addToken.on;
/* Letter identity escapes that natively match literal characters: `\a`, `\A`, etc. These should be
* SyntaxErrors but are allowed in web reality. XRegExp makes them errors for cross-browser
* consistency and to reserve their syntax, but lets them be superseded by addons.
*/
- add(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/,
+ add(
+ /\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/,
function (match, scope) {
// \B is allowed in default scope only
if (match[1] === 'B' && scope === defaultScope) {
@@ -1337,33 +1347,39 @@ var XRegExp = (function () {
}
throw new SyntaxError('Invalid escape ' + match[0]);
},
- {scope: 'all'});
+ {scope: 'all'}
+ );
/* Empty character class: `[]` or `[^]`. This fixes a critical cross-browser syntax inconsistency.
* Unless this is standardized (per the ES spec), regex syntax can't be accurately parsed because
* character class endings can't be determined.
*/
- add(/\[(\^?)]/,
+ add(
+ /\[(\^?)]/,
function (match) {
// For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].
// (?!) should work like \b\B, but is unreliable in some versions of Firefox
return match[1] ? '[\\s\\S]' : '\\b\\B';
- });
+ }
+ );
/* Comment pattern: `(?# )`. Inline comments are an alternative to the line comments allowed in
* free-spacing mode (flag x).
*/
- add(/\(\?#[^)]*\)/,
+ add(
+ /\(\?#[^)]*\)/,
function (match) {
// Keep tokens separated unless the following token is a quantifier
return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ?
- '' : '(?:)';
- });
+ '' : '(?:)';
+ }
+ );
/* Named backreference: `\k<name>`. Backreference names can use the characters A-Z, a-z, 0-9, _,
* and $ only.
*/
- add(/\\k<([\w$]+)>/,
+ add(
+ /\\k<([\w$]+)>/,
function (match) {
// Groups with the same name is an error, else would need `lastIndexOf`
var index = isNaN(match[1]) ? (indexOf(this.captureNames, match[1]) + 1) : +match[1],
@@ -1374,28 +1390,32 @@ var XRegExp = (function () {
// Keep backreferences separate from subsequent literal numbers
return '\\' + index + (
endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ?
- '' : '(?:)'
+ '' : '(?:)'
);
- });
+ }
+ );
/* Whitespace and line comments, in free-spacing mode (aka extended mode, flag x) only.
*/
- add(/(?:\s+|#.*)+/,
+ add(
+ /(?:\s+|#.*)+/,
function (match) {
// Keep tokens separated unless the following token is a quantifier
return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ?
- '' : '(?:)';
+ '' : '(?:)';
},
{
trigger: function () {
return this.hasFlag('x');
},
customFlags: 'x'
- });
+ }
+ );
/* Dot, in dotall mode (aka singleline mode, flag s) only.
*/
- add(/\./,
+ add(
+ /\./,
function () {
return '[\\s\\S]';
},
@@ -1404,7 +1424,8 @@ var XRegExp = (function () {
return this.hasFlag('s');
},
customFlags: 's'
- });
+ }
+ );
/* Named capturing group; match the opening delimiter only: `(?<name>`. Capture names can use the
* characters A-Z, a-z, 0-9, _, and $ only. Names can't be integers. Supports Python-style
@@ -1412,7 +1433,8 @@ var XRegExp = (function () {
* Python-style syntax). Otherwise, XRegExp might treat numbered backreferences to Python-style
* named capture as octals.
*/
- add(/\(\?P?<([\w$]+)>/,
+ add(
+ /\(\?P?<([\w$]+)>/,
function (match) {
// Disallow bare integers as names because named backreferences are added to match
// arrays and therefore numeric properties may lead to incorrect lookups
@@ -1425,13 +1447,15 @@ var XRegExp = (function () {
this.captureNames.push(match[1]);
this.hasNamedCapture = true;
return '(';
- });
+ }
+ );
/* Numbered backreference or octal, plus any following digits: `\0`, `\11`, etc. Octals except `\0`
* not followed by 0-9 and backreferences to unopened capture groups throw an error. Other matches
* are returned unaltered. IE < 9 doesn't support backreferences above `\99` in regex syntax.
*/
- add(/\\(\d+)/,
+ add(
+ /\\(\d+)/,
function (match, scope) {
if (
!(
@@ -1442,16 +1466,18 @@ var XRegExp = (function () {
match[1] !== '0'
) {
throw new SyntaxError('Cannot use octal escape or backreference to undefined group ' +
- match[0]);
+ match[0]);
}
return match[0];
},
- {scope: 'all'});
+ {scope: 'all'}
+ );
/* Capturing group; match the opening parenthesis only. Required for support of named capturing
* groups. Also adds explicit capture mode (flag n).
*/
- add(/\((?!\?)/,
+ add(
+ /\((?!\?)/,
function () {
if (this.hasFlag('n')) {
return '(?:';
@@ -1459,7 +1485,8 @@ var XRegExp = (function () {
this.captureNames.push(null);
return '(';
},
- {customFlags: 'n'});
+ {customFlags: 'n'}
+ );
/*--------------------------------------
* Expose XRegExp
@@ -1477,10 +1504,9 @@ var XRegExp = (function () {
/*---- unicode-base.js ----*/
/*!
- * XRegExp 2.1.0-rc: Unicode Base
+ * XRegExp Unicode Base 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2008-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2008-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -1529,8 +1555,8 @@ var XRegExp = (function () {
function charCode(chr) {
var esc = /^\\[xu](.+)/.exec(chr);
return esc ?
- dec(esc[1]) :
- chr.charCodeAt(chr.charAt(0) === '\\' ? 1 : 0);
+ dec(esc[1]) :
+ chr.charCodeAt(chr.charAt(0) === '\\' ? 1 : 0);
}
// Inverts a list of BMP characters and ranges
@@ -1580,8 +1606,8 @@ var XRegExp = (function () {
}
// Astral Unicode tokens always match a code point, never a code unit
return negated ?
- '(?:(?!' + combined + ')(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))' :
- '(?:' + combined + ')';
+ '(?:(?!' + combined + ')(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))' :
+ '(?:' + combined + ')';
}
// Builds a complete astral pattern on first use
@@ -1623,8 +1649,8 @@ var XRegExp = (function () {
return cacheAstral(slug, negated);
}
return scope === 'class' ?
- (negated ? cacheInvertedBmp(slug) : item.bmp) :
- (negated ? '[^' : '[') + item.bmp + ']';
+ (negated ? cacheInvertedBmp(slug) : item.bmp) :
+ (negated ? '[^' : '[') + item.bmp + ']';
},
{
scope: 'all',
@@ -1691,10 +1717,9 @@ var XRegExp = (function () {
/*---- unicode-categories.js ----*/
/*!
- * XRegExp 2.1.0-rc: Unicode Categories
+ * XRegExp Unicode Categories 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2010-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -1929,10 +1954,9 @@ var XRegExp = (function () {
/*---- unicode-scripts.js ----*/
/*!
- * XRegExp 2.1.0-rc: Unicode Scripts
+ * XRegExp Unicode Scripts 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2010-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -2375,10 +2399,9 @@ var XRegExp = (function () {
/*---- unicode-blocks.js ----*/
/*!
- * XRegExp 2.1.0-rc: Unicode Blocks
+ * XRegExp Unicode Blocks 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2010-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -3285,10 +3308,9 @@ var XRegExp = (function () {
/*---- unicode-properties.js ----*/
/*!
- * XRegExp 2.1.0-rc: Unicode Properties
+ * XRegExp Unicode Properties 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
* Uses Unicode 6.1.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
@@ -3317,7 +3339,7 @@ var XRegExp = (function () {
bmp: 'A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05B0-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0657\u0659-\u065F\u066E-\u06D3\u06D5-\u06DC\u06E1-\u06E8\u06ED-\u06EF\u06FA-\u06FC\u06FF\u0710-\u073F\u074D-\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0817\u081A-\u082C\u0840-\u0858\u08A0\u08A2-\u08AC\u08E4-\u08E9\u08F0-\u08FE\u0900-\u093B\u093D-\u094C\u094E-\u0950\u0955-\u0963\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD-\u09C4\u09C7\u09C8\u09CB\u09CC\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09F0\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3E-\u0A42\u0A47\u0A48\u0A4B\u0A4C\u0A51\u0A59-\u0A5C\u0A5E\u0A70-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD-\u0AC5\u0AC7-\u0AC9\u0ACB\u0ACC\u0AD0\u0AE0-\u0AE3\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D-\u0B44\u0B47\u0B48\u0B4B\u0B4C\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD0\u0BD7\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4C\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCC\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4C\u0D4E\u0D57\u0D60-\u0D63\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E46\u0E4D\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0ECD\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F71-\u0F81\u0F88-\u0F97\u0F99-\u0FBC\u1000-\u1036\u1038\u103B-\u103F\u1050-\u1062\u1065-\u1068\u106E-\u1086\u108E\u109C\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1713\u1720-\u1733\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17B3\u17B6-\u17C8\u17D7\u17DC\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B\u1930-\u1938\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A1B\u1A20-\u1A5E\u1A61-\u1A74\u1AA7\u1B00-\u1B33\u1B35-\u1B43\u1B45-\u1B4B\u1B80-\u1BA9\u1BAC-\u1BAF\u1BBA-\u1BE5\u1BE7-\u1BF1\u1C00-\u1C35\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u24B6-\u24E9\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA674-\uA67B\uA67F-\uA697\uA69F-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA827\uA840-\uA873\uA880-\uA8C3\uA8F2-\uA8F7\uA8FB\uA90A-\uA92A\uA930-\uA952\uA960-\uA97C\uA980-\uA9B2\uA9B4-\uA9BF\uA9CF\uAA00-\uAA36\uAA40-\uAA4D\uAA60-\uAA76\uAA7A\uAA80-\uAABE\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF5\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC',
astral: '\uD803[\uDC00-\uDC48]|\uD801[\uDC00-\uDC9D]|\uD809[\uDC00-\uDC62]|\uD81A[\uDC00-\uDE38]|\uD804[\uDC00-\uDC45\uDC82-\uDCB8\uDCD0-\uDCE8\uDD00-\uDD32\uDD80-\uDDBF\uDDC1-\uDDC4]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD87E[\uDC00-\uDE1D]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1E\uDF30-\uDF4A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF93-\uDF9F]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD82C[\uDC00\uDC01]|\uD808[\uDC00-\uDF6E]|\uD805[\uDE80-\uDEB5]'
},
- // NOTE: In BMP-only mode, `[\p{^Any}]` compiles to `[]`
+ // Assert: In BMP-only mode, `[\p{^Any}]` compiles to `[]`
{
name: 'Any',
isBmpLast: true,
@@ -3361,10 +3383,9 @@ var XRegExp = (function () {
/*---- matchrecursive.js ----*/
/*!
- * XRegExp 2.1.0-rc: XRegExp.matchRecursive
+ * XRegExp.matchRecursive 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2009-2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2009-2012 MIT License
*/
(function (XRegExp) {
@@ -3462,8 +3483,8 @@ var XRegExp = (function () {
// Using `XRegExp.union` safely rewrites backreferences in `left` and `right`
esc = new RegExp(
'(?:' + escapeChar + '[\\S\\s]|(?:(?!' +
- XRegExp.union([left, right]).source +
- ')[^' + escapeChar + '])+)+',
+ XRegExp.union([left, right]).source +
+ ')[^' + escapeChar + '])+)+',
// Flags `gy` not needed here
flags.replace(/[^im]+/g, '')
);
@@ -3555,18 +3576,18 @@ var XRegExp = (function () {
/*---- build.js ----*/
/*!
- * XRegExp 2.1.0-rc: XRegExp.build
+ * XRegExp.build 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
* Inspired by Lea Verou's RegExp.create <http://lea.verou.me/>
*/
(function (XRegExp) {
'use strict';
- var subparts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
- parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subparts], 'g');
+ var REGEX_DATA = 'xregexp',
+ subParts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
+ parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subParts], 'g');
/**
* Strips a leading `^` and trailing unescaped `$`, if both are present.
@@ -3575,8 +3596,8 @@ var XRegExp = (function () {
* @returns {String} Pattern with edge anchors removed.
*/
function deanchor(pattern) {
- var startAnchor = /^(?:\(\?:\))*\^/, // Leading `^` or `(?:)^` (handles /x cruft)
- endAnchor = /\$(?:\(\?:\))*$/; // Trailing `$` or `$(?:)` (handles /x cruft)
+ var startAnchor = /^(?:\(\?:\))*\^/, // Leading `^` or `(?:)^` (handles token cruft)
+ endAnchor = /\$(?:\(\?:\))*$/; // Trailing `$` or `$(?:)` (handles token cruft)
// Ensure that the trailing `$` isn't escaped
if (startAnchor.test(pattern) && endAnchor.test(pattern.replace(/\\[\s\S]/g, ''))) {
return pattern.replace(startAnchor, '').replace(endAnchor, '');
@@ -3585,15 +3606,18 @@ var XRegExp = (function () {
}
/**
- * Converts the provided value to an XRegExp.
+ * Converts the provided value to an XRegExp. Native RegExp flags are not preserved.
* @private
* @param {String|RegExp} value Value to convert.
* @returns {RegExp} XRegExp object with XRegExp syntax applied.
*/
function asXRegExp(value) {
return XRegExp.isRegExp(value) ?
- (value.xregexp && !value.xregexp.isNative ? value : XRegExp(value.source)) :
- XRegExp(value);
+ (value[REGEX_DATA] && !value[REGEX_DATA].isNative ?
+ value : // No need to recompile
+ XRegExp(value.source) // Recompile native RegExp as XRegExp
+ ) :
+ XRegExp(value); // Compile string as XRegExp
}
/**
@@ -3642,21 +3666,24 @@ var XRegExp = (function () {
for (p in subs) {
if (subs.hasOwnProperty(p)) {
- // Passing to XRegExp enables extended syntax for subpatterns provided as strings
- // and ensures independent validity, lest an unescaped `(`, `)`, `[`, or trailing
- // `\` breaks the `(?:)` wrapper. For subpatterns provided as regexes, it dies on
- // octals and adds the `xregexp` property, for simplicity
+ // Passing to XRegExp enables extended syntax and ensures independent validity,
+ // lest an unescaped `(`, `)`, `[`, or trailing `\` breaks the `(?:)` wrapper. For
+ // subpatterns provided as native regexes, it dies on octals and adds the property
+ // used to hold extended regex instance data, for simplicity
sub = asXRegExp(subs[p]);
- // Deanchoring allows embedding independently useful anchored regexes. If you
- // really need to keep your anchors, double them (i.e., `^^...$$`)
- data[p] = {pattern: deanchor(sub.source), names: sub.xregexp.captureNames || []};
+ data[p] = {
+ // Deanchoring allows embedding independently useful anchored regexes. If you
+ // really need to keep your anchors, double them (i.e., `^^...$$`)
+ pattern: deanchor(sub.source),
+ names: sub[REGEX_DATA].captureNames || []
+ };
}
}
// Passing to XRegExp dies on octals and ensures the outer pattern is independently valid;
// helps keep this simple. Named captures will be put back
pattern = asXRegExp(pattern);
- outerCapNames = pattern.xregexp.captureNames || [];
+ outerCapNames = pattern[REGEX_DATA].captureNames || [];
pattern = pattern.source.replace(parts, function ($0, $1, $2, $3, $4) {
var subName = $1 || $2, capName, intro;
// Named subpattern
@@ -3675,7 +3702,7 @@ var XRegExp = (function () {
intro = '(?:';
}
numPriorCaps = numCaps;
- return intro + data[subName].pattern.replace(subparts, function (match, paren, backref) {
+ return intro + data[subName].pattern.replace(subParts, function (match, paren, backref) {
// Capturing group
if (paren) {
capName = data[subName].names[numCaps - numPriorCaps];
@@ -3716,10 +3743,9 @@ var XRegExp = (function () {
/*---- prototypes.js ----*/
/*!
- * XRegExp 2.1.0-rc: Prototypes
+ * XRegExp Prototypes 2.1.0-rc
* <http://xregexp.com/>
- * (c) 2012 Steven Levithan
- * MIT License
+ * Steven Levithan © 2012 MIT License
*/
/**
Please sign in to comment.
Something went wrong with that request. Please try again.