diff --git a/CHANGELOG b/CHANGELOG index 3e65271..03e9737 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Add RegExp.escape for escaping regular expression strings. Closes #9094. [Ken Snyder] + * Make the eventName and handler arguments to Event.stopObserving optional. If no handler is specified, all handlers for the given event are unregistered. If no event name is specified, all observed events on the element are unregistered. [sam] * Add cross-support for the DOMContentLoaded event through a Prototype custom event on document called "contentloaded". The DOMContentLoaded event fires before window.load, when the entire HTML document, but not necessarily its images, stylesheets or other assets, has loaded. Based on [6596]. [sam, Mislav Marohnić] diff --git a/src/base.js b/src/base.js index 4902023..e3a37c9 100644 --- a/src/base.js +++ b/src/base.js @@ -221,6 +221,10 @@ var Try = { RegExp.prototype.match = RegExp.prototype.test; +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; + /*--------------------------------------------------------------------------*/ var PeriodicalExecuter = Class.create({ diff --git a/test/unit/base.html b/test/unit/base.html index 1dea816..a0b13c8 100644 --- a/test/unit/base.html +++ b/test/unit/base.html @@ -283,6 +283,47 @@ assertEqual('\"1969-12-31T19:00:00\"', new Date(1969, 11, 31, 19).toJSON()); }}, + testRegExpEscape: function() {with(this) { + assertEqual('word', RegExp.escape('word')); + assertEqual('\\/slashes\\/', RegExp.escape('/slashes/')); + assertEqual('\\\\backslashes\\\\', RegExp.escape('\\backslashes\\')); + assertEqual('\\\\border of word', RegExp.escape('\\border of word')); + + assertEqual('\\(\\?\\:non-capturing\\)', RegExp.escape('(?:non-capturing)')); + assertEqual('non-capturing', new RegExp(RegExp.escape('(?:') + '([^)]+)').exec('(?:non-capturing)')[1]); + + assertEqual('\\(\\?\\=positive-lookahead\\)', RegExp.escape('(?=positive-lookahead)')); + assertEqual('positive-lookahead', new RegExp(RegExp.escape('(?=') + '([^)]+)').exec('(?=positive-lookahead)')[1]); + + assertEqual('\\(\\?<\\=positive-lookbehind\\)', RegExp.escape('(?<=positive-lookbehind)')); + assertEqual('positive-lookbehind', new RegExp(RegExp.escape('(?<=') + '([^)]+)').exec('(?<=positive-lookbehind)')[1]); + + assertEqual('\\(\\?\\!negative-lookahead\\)', RegExp.escape('(?!negative-lookahead)')); + assertEqual('negative-lookahead', new RegExp(RegExp.escape('(?!') + '([^)]+)').exec('(?!negative-lookahead)')[1]); + + assertEqual('\\(\\?<\\!negative-lookbehind\\)', RegExp.escape('(?', new RegExp(RegExp.escape('
')).exec('
')[0]); + + assertEqual('false', RegExp.escape(false)); + assertEqual('undefined', RegExp.escape()); + assertEqual('null', RegExp.escape(null)); + assertEqual('42', RegExp.escape(42)); + + assertEqual('\\\\n\\\\r\\\\t', RegExp.escape('\\n\\r\\t')); + assertEqual('\n\r\t', RegExp.escape('\n\r\t')); + assertEqual('\\{5,2\\}', RegExp.escape('{5,2}')); + + assertEqual( + '\\/\\(\\[\\.\\*\\+\\?\\^\\=\\!\\:\\$\\{\\}\\(\\)\\|\\[\\\\\\]\\\\\\\/\\\\\\\\\\]\\)\\/g', + RegExp.escape('/([.*+?^=!:${}()|[\\]\\/\\\\])/g') + ); + }}, + testBrowserDetection: function() {with(this) { var results = $H(Prototype.Browser).map(function(engine){ return engine;