From 30aa7a653293d7ab1357666125da6047b3f76ca1 Mon Sep 17 00:00:00 2001 From: Sam Stephenson Date: Sat, 4 Aug 2007 07:31:52 +0000 Subject: [PATCH] prototype: Add RegExp.escape for escaping regular expression strings. Closes #9094. --- CHANGELOG | 2 ++ src/base.js | 4 ++++ test/unit/base.html | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) 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;