From 3cedff10d6b294dfd57c1151c468cc90c3dac036 Mon Sep 17 00:00:00 2001 From: amarcruz Date: Tue, 8 Dec 2015 21:25:21 -0600 Subject: [PATCH] v2.3.15 Fix: when calling the compiler with different brackets, `brackets.array` changes the global configuration (`riot.settings.brackets`) --- CHANGELOG.md | 1 + dist/es6.tmpl.js | 70 ++++++++++++++++++++++++----------------- dist/riot.tmpl.js | 70 ++++++++++++++++++++++++----------------- dist/tmpl.js | 70 ++++++++++++++++++++++++----------------- doc/API.md | 12 ++----- doc/CHANGES.md | 9 +++--- lib/brackets.js | 79 ++++++++++++++++++++++++++++++----------------- package.json | 2 +- 8 files changed, 187 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 825d8f1..e2a6032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,3 +2,4 @@ # v2.3.15 - Fix [riot#1416](https://github.com/riot/riot/issues/1416): Issue with space in expression of `each` +- Fix: when calling the compiler with different brackets, `brackets.array` changes the global configuration (`riot.settings.brackets`) diff --git a/dist/es6.tmpl.js b/dist/es6.tmpl.js index 247d8bc..d7dba6e 100644 --- a/dist/es6.tmpl.js +++ b/dist/es6.tmpl.js @@ -39,36 +39,45 @@ var brackets = (function (UNDEF) { function _loopback(re) { return re } - function _rewrite(re) { + function _rewrite(re, bp) { + if (!bp) bp = _pairs return new RegExp( - re.source.replace(/{/g, _pairs[2]).replace(/}/g, _pairs[3]), re.global ? REGLOB : '' + re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' ) } - function _reset(pair) { - pair = pair || DEFAULT - - if (pair !== _pairs[8]) { - var bp = pair.split(' ') + function _create(pair) { + var + cvt, + arr = pair.split(' ') - if (pair === DEFAULT) { - _pairs = bp.concat(bp) - _regex = _loopback - } - else { - if (bp.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { - throw new Error('Unsupported brackets "' + pair + '"') - } - _pairs = bp.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) - _regex = _rewrite + if (pair === DEFAULT) { + arr[2] = arr[0] + arr[3] = arr[1] + cvt = _loopback + } + else { + if (arr.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { + throw new Error('Unsupported brackets "' + pair + '"') } + arr = arr.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) + cvt = _rewrite + } + arr[4] = cvt(arr[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/, arr) + arr[5] = cvt(/\\({|})/g, arr) + arr[6] = cvt(/(\\?)({)/g, arr) + arr[7] = RegExp('(\\\\?)(?:([[({])|(' + arr[3] + '))|' + S_QBSRC, REGLOB) + arr[8] = pair + return arr + } - _pairs[4] = _regex(_pairs[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/) - _pairs[5] = _regex(/\\({|})/g) - _pairs[6] = _regex(/(\\?)({)/g) - _pairs[7] = RegExp('(\\\\?)(?:([[({])|(' + _pairs[3] + '))|' + S_QBSRC, REGLOB) + function _reset(pair) { + if (!pair) pair = DEFAULT + + if (pair !== _pairs[8]) { + _pairs = _create(pair) + _regex = pair === DEFAULT ? _loopback : _rewrite _pairs[9] = _regex(/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/) - _pairs[8] = pair _brackets._rawOffset = _pairs[0].length } _brackets.settings.brackets = cachedBrackets = pair @@ -79,7 +88,12 @@ var brackets = (function (UNDEF) { return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _pairs[reOrIdx] } - _brackets.split = function split(str, tmpl) { + _brackets.split = function split(str, tmpl, _bp) { + // istanbul ignore next: _bp is for the compiler + if (!_bp) { + _reset(_brackets.settings.brackets) + _bp = _pairs + } var parts = [], @@ -87,7 +101,7 @@ var brackets = (function (UNDEF) { isexpr, start, pos, - re = _brackets(6) + re = _bp[6] isexpr = start = re.lastIndex = 0 @@ -109,7 +123,7 @@ var brackets = (function (UNDEF) { if (!match[1]) { unescapeStr(str.slice(start, pos)) start = re.lastIndex - re = _pairs[6 + (isexpr ^= 1)] + re = _bp[6 + (isexpr ^= 1)] re.lastIndex = start } } @@ -122,7 +136,7 @@ var brackets = (function (UNDEF) { function unescapeStr(str) { if (tmpl || isexpr) - parts.push(str && str.replace(_pairs[5], '$1')) + parts.push(str && str.replace(_bp[5], '$1')) else parts.push(str) } @@ -153,8 +167,8 @@ var brackets = (function (UNDEF) { } _brackets.array = function array(pair) { - _reset(pair || _brackets.settings.brackets) - return _pairs + if (!pair) pair = _brackets.settings.brackets + return _create(pair) } /* istanbul ignore next: in the node version riot is not in the scope */ diff --git a/dist/riot.tmpl.js b/dist/riot.tmpl.js index a70e403..10fbee8 100644 --- a/dist/riot.tmpl.js +++ b/dist/riot.tmpl.js @@ -39,36 +39,45 @@ var brackets = (function (UNDEF) { function _loopback(re) { return re } - function _rewrite(re) { + function _rewrite(re, bp) { + if (!bp) bp = _pairs return new RegExp( - re.source.replace(/{/g, _pairs[2]).replace(/}/g, _pairs[3]), re.global ? REGLOB : '' + re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' ) } - function _reset(pair) { - pair = pair || DEFAULT - - if (pair !== _pairs[8]) { - var bp = pair.split(' ') + function _create(pair) { + var + cvt, + arr = pair.split(' ') - if (pair === DEFAULT) { - _pairs = bp.concat(bp) - _regex = _loopback - } - else { - if (bp.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { - throw new Error('Unsupported brackets "' + pair + '"') - } - _pairs = bp.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) - _regex = _rewrite + if (pair === DEFAULT) { + arr[2] = arr[0] + arr[3] = arr[1] + cvt = _loopback + } + else { + if (arr.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { + throw new Error('Unsupported brackets "' + pair + '"') } + arr = arr.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) + cvt = _rewrite + } + arr[4] = cvt(arr[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/, arr) + arr[5] = cvt(/\\({|})/g, arr) + arr[6] = cvt(/(\\?)({)/g, arr) + arr[7] = RegExp('(\\\\?)(?:([[({])|(' + arr[3] + '))|' + S_QBSRC, REGLOB) + arr[8] = pair + return arr + } - _pairs[4] = _regex(_pairs[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/) - _pairs[5] = _regex(/\\({|})/g) - _pairs[6] = _regex(/(\\?)({)/g) - _pairs[7] = RegExp('(\\\\?)(?:([[({])|(' + _pairs[3] + '))|' + S_QBSRC, REGLOB) + function _reset(pair) { + if (!pair) pair = DEFAULT + + if (pair !== _pairs[8]) { + _pairs = _create(pair) + _regex = pair === DEFAULT ? _loopback : _rewrite _pairs[9] = _regex(/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/) - _pairs[8] = pair _brackets._rawOffset = _pairs[0].length } _brackets.settings.brackets = cachedBrackets = pair @@ -79,7 +88,12 @@ var brackets = (function (UNDEF) { return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _pairs[reOrIdx] } - _brackets.split = function split(str, tmpl) { + _brackets.split = function split(str, tmpl, _bp) { + // istanbul ignore next: _bp is for the compiler + if (!_bp) { + _reset(_brackets.settings.brackets) + _bp = _pairs + } var parts = [], @@ -87,7 +101,7 @@ var brackets = (function (UNDEF) { isexpr, start, pos, - re = _brackets(6) + re = _bp[6] isexpr = start = re.lastIndex = 0 @@ -109,7 +123,7 @@ var brackets = (function (UNDEF) { if (!match[1]) { unescapeStr(str.slice(start, pos)) start = re.lastIndex - re = _pairs[6 + (isexpr ^= 1)] + re = _bp[6 + (isexpr ^= 1)] re.lastIndex = start } } @@ -122,7 +136,7 @@ var brackets = (function (UNDEF) { function unescapeStr(str) { if (tmpl || isexpr) - parts.push(str && str.replace(_pairs[5], '$1')) + parts.push(str && str.replace(_bp[5], '$1')) else parts.push(str) } @@ -153,8 +167,8 @@ var brackets = (function (UNDEF) { } _brackets.array = function array(pair) { - _reset(pair || _brackets.settings.brackets) - return _pairs + if (!pair) pair = _brackets.settings.brackets + return _create(pair) } /* istanbul ignore next: in the node version riot is not in the scope */ diff --git a/dist/tmpl.js b/dist/tmpl.js index 3cdaaed..8281c3a 100644 --- a/dist/tmpl.js +++ b/dist/tmpl.js @@ -37,36 +37,45 @@ function _loopback(re) { return re } - function _rewrite(re) { + function _rewrite(re, bp) { + if (!bp) bp = _pairs return new RegExp( - re.source.replace(/{/g, _pairs[2]).replace(/}/g, _pairs[3]), re.global ? REGLOB : '' + re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' ) } - function _reset(pair) { - pair = pair || DEFAULT - - if (pair !== _pairs[8]) { - var bp = pair.split(' ') + function _create(pair) { + var + cvt, + arr = pair.split(' ') - if (pair === DEFAULT) { - _pairs = bp.concat(bp) - _regex = _loopback - } - else { - if (bp.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { - throw new Error('Unsupported brackets "' + pair + '"') - } - _pairs = bp.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) - _regex = _rewrite + if (pair === DEFAULT) { + arr[2] = arr[0] + arr[3] = arr[1] + cvt = _loopback + } + else { + if (arr.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { + throw new Error('Unsupported brackets "' + pair + '"') } + arr = arr.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) + cvt = _rewrite + } + arr[4] = cvt(arr[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/, arr) + arr[5] = cvt(/\\({|})/g, arr) + arr[6] = cvt(/(\\?)({)/g, arr) + arr[7] = RegExp('(\\\\?)(?:([[({])|(' + arr[3] + '))|' + S_QBSRC, REGLOB) + arr[8] = pair + return arr + } - _pairs[4] = _regex(_pairs[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/) - _pairs[5] = _regex(/\\({|})/g) - _pairs[6] = _regex(/(\\?)({)/g) - _pairs[7] = RegExp('(\\\\?)(?:([[({])|(' + _pairs[3] + '))|' + S_QBSRC, REGLOB) + function _reset(pair) { + if (!pair) pair = DEFAULT + + if (pair !== _pairs[8]) { + _pairs = _create(pair) + _regex = pair === DEFAULT ? _loopback : _rewrite _pairs[9] = _regex(/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/) - _pairs[8] = pair _brackets._rawOffset = _pairs[0].length } _brackets.settings.brackets = cachedBrackets = pair @@ -77,7 +86,12 @@ return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _pairs[reOrIdx] } - _brackets.split = function split(str, tmpl) { + _brackets.split = function split(str, tmpl, _bp) { + // istanbul ignore next: _bp is for the compiler + if (!_bp) { + _reset(_brackets.settings.brackets) + _bp = _pairs + } var parts = [], @@ -85,7 +99,7 @@ isexpr, start, pos, - re = _brackets(6) + re = _bp[6] isexpr = start = re.lastIndex = 0 @@ -107,7 +121,7 @@ if (!match[1]) { unescapeStr(str.slice(start, pos)) start = re.lastIndex - re = _pairs[6 + (isexpr ^= 1)] + re = _bp[6 + (isexpr ^= 1)] re.lastIndex = start } } @@ -120,7 +134,7 @@ function unescapeStr(str) { if (tmpl || isexpr) - parts.push(str && str.replace(_pairs[5], '$1')) + parts.push(str && str.replace(_bp[5], '$1')) else parts.push(str) } @@ -151,8 +165,8 @@ } _brackets.array = function array(pair) { - _reset(pair || _brackets.settings.brackets) - return _pairs + if (!pair) pair = _brackets.settings.brackets + return _create(pair) } /* istanbul ignore next: in the node version riot is not in the scope */ diff --git a/doc/API.md b/doc/API.md index 2f34f34..97f1686 100644 --- a/doc/API.md +++ b/doc/API.md @@ -93,16 +93,10 @@ This function checks their parameter and reconfigures the internal state immedia _parameters_ -* `brackets_pair` : string - new custom brackets pair. The start and end is separated with a space character. +* `brackets_pair` : string - (optional) new custom brackets pair. The start and end is separated with a space character. - -### `settings` property - -_Type:_ object - -Mirror the `riot.settings` object or other user object where read or write the current brackets string. Unlike with `brackets.set`, reconfiguration for changes in `brackets.settings.brackets` or `riot.settings.brackets` will be applied in the next use of the `brackets` function. - -**NOTE:** `riot.settings.brackets` and `brackets.settings` will be deprecated in future versions, please use brackets.set in new code. +**NOTE:** +`riot.settings.brackets` and `brackets.settings` will be deprecated in future versions, please use `brackets.set` in new code. ### `R_MLCOMMS` property diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 1ab608b..f1dae81 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -43,9 +43,11 @@ Ref: [riot#871](https://github.com/riot/riot/issues/871), [riot#1189](https://gi brackets 2.3 combines the behavior of brackets 2.2 with a new one, based on a function to make immediate, more secure changes to custom brackets. There is a performance penalty in supporting both schemes, but compatibility is maintained. -If riot is available when `brackets` is instantiated, `brackets` will use the configuration in `riot.settings`. If not, you can link a configuration later, through the new `brackets.settings` property, which accepts a reference to `riot.settings` or other object where read and write new brackets values. In this way, brackets works as in previous versions. +If riot is available when `brackets` is instantiated, `brackets` uses the configuration in `riot.settings`. In this way, `brackets` works as in previous versions and the reconfiguration is delayed to the first use. +If riot is not available, you can change the brackets through the new `brackets.set` function, which accepts the same parameter as `riot.settings.brackets` and makes the reconfiguration immediately. -The other, recommended option, is call to the new `breackets.set` function with the value for the brackets. The only difference is `brackets.set` checks and make the changes immediately, while using the `settings` property the reconfiguration is delayed to first use. +**NOTE:** +`breackets.set` is the recommended and long term option to change the brackets, it is likely that `riot.settings` is deprecated in future versions. It is all, syntax and behavior are the same as older versions: `brackets(regex_or_number)`. @@ -60,7 +62,7 @@ This is the list of invalid characters: - Single and double quotes, comma, semicolon and backslash `'`, `"`, `,`, `;`, `\`, for obvious reasons - The dangerous `<` and `>` characters, reserved for use in markup and strictly prohibited in unquoted text for any other purpose -- out of CDATA sections. -Typically, by using '<>' the browser will send to riot something different to what the user wants. With preprocessors such as ASP, no problems. But riot is not one of them, even with precompiled tags, it's a postprocessor. See the difference: +Typically, by using `<>` the browser will send to riot something different to what the user wants. With preprocessors such as ASP, no problems. But riot is not one of them, even with precompiled tags, it's a postprocessor. See the difference: #### ASP @@ -68,7 +70,6 @@ Source –> | ASP parser –> | Browser -------------------|----------------|----------- `

<%= x %>

` | `

X

` | (Renders "X") - ASP takes the value of `x`, does the substitution, and stops here. The browser (HTML parser) receives valid HTML. #### riot diff --git a/lib/brackets.js b/lib/brackets.js index 46d62d5..56b9163 100644 --- a/lib/brackets.js +++ b/lib/brackets.js @@ -80,41 +80,58 @@ var brackets = (function (UNDEF) { * @returns {RegExp} - The new regex with the default brackets replaced. * @private */ - function _rewrite(re) { + function _rewrite(re, bp) { + if (!bp) bp = _pairs return new RegExp( - re.source.replace(/{/g, _pairs[2]).replace(/}/g, _pairs[3]), re.global ? REGLOB : '' + re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' ) } + /** + * Creates an array with strings and regexes based on the received brackets. + * + * @param {string} pair - String with the brackets pair + * @returns {Array} - Array with info for the given brackets + * @private + */ + function _create(pair) { + var + cvt, + arr = pair.split(' ') + + if (pair === DEFAULT) { + arr[2] = arr[0] + arr[3] = arr[1] + cvt = _loopback + } + else { + if (arr.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { + throw new Error('Unsupported brackets "' + pair + '"') + } + arr = arr.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) + cvt = _rewrite + } + arr[$_RIX_TEST] = cvt(arr[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/, arr) + arr[$_RIX_ESC] = cvt(/\\({|})/g, arr) + arr[$_RIX_OPEN] = cvt(/(\\?)({)/g, arr) // for _split() + arr[$_RIX_CLOSE] = RegExp('(\\\\?)(?:([[({])|(' + arr[3] + '))|' + S_QBSRC, REGLOB) + arr[$_RIX_PAIR] = pair + return arr + } + /** * Resets the _pairs array with strings and regexes based on its parameter. + * * @param {string} pair - String with the brackets pair to set * @private */ function _reset(pair) { - pair = pair || DEFAULT + if (!pair) pair = DEFAULT if (pair !== _pairs[$_RIX_PAIR]) { - var bp = pair.split(' ') - - if (pair === DEFAULT) { - _pairs = bp.concat(bp) - _regex = _loopback - } - else { - if (bp.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) { - throw new Error('Unsupported brackets "' + pair + '"') - } - _pairs = bp.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' ')) - _regex = _rewrite - } - //_pairs[$_RIX_TEST] = _regex(_pairs[1].length > 1 ? /(?:^|[^\\]){[\S\s]*?}/ : /(?:^|[^\\]){[^}]*}/) - _pairs[$_RIX_TEST] = _regex(_pairs[1].length > 1 ? /{[^]*?}/ : /{[^}]*}/) - _pairs[$_RIX_ESC] = _regex(/\\({|})/g) - _pairs[$_RIX_OPEN] = _regex(/(\\?)({)/g) // for _split() - _pairs[$_RIX_CLOSE] = RegExp('(\\\\?)(?:([[({])|(' + _pairs[3] + '))|' + S_QBSRC, REGLOB) + _pairs = _create(pair) + _regex = pair === DEFAULT ? _loopback : _rewrite _pairs[$_RIX_LOOP] = _regex(/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/) - _pairs[$_RIX_PAIR] = pair _brackets._rawOffset = _pairs[0].length } _brackets.settings.brackets = cachedBrackets = pair // always set these @@ -143,10 +160,16 @@ var brackets = (function (UNDEF) { * For internal use by tmpl and the riot-compiler. * @param {string} str - Template source to split, can be one expression * @param {number} [tmpl] - 1 if called from tmpl() + * @param {Array} [_bp] - Info of custom brackets to use * @returns {Array} - Array containing alternate template text and expressions. * If str was one unique expression, returns two elements: ["", expression]. */ - _brackets.split = function split(str, tmpl) { + _brackets.split = function split(str, tmpl, _bp) { + // istanbul ignore next: _bp is for the compiler + if (!_bp) { + _reset(_brackets.settings.brackets) + _bp = _pairs + } // Template text is easy: closing brackets are ignored, all we have to do is find // the first unescaped bracket. The real work is with the expressions... @@ -165,7 +188,7 @@ var brackets = (function (UNDEF) { isexpr, // we are in ttext (0) or expression (1) start, // start position of current template or expression pos, // current position (exec() result) - re = _brackets($_RIX_OPEN) // start with *updated* opening bracket + re = _bp[$_RIX_OPEN] // start with *updated* opening bracket isexpr = start = re.lastIndex = 0 // re is reused, we must reset lastIndex @@ -194,7 +217,7 @@ var brackets = (function (UNDEF) { if (!match[1]) { // ignore it if have an escape char unescapeStr(str.slice(start, pos)) // push part, even if empty start = re.lastIndex // next position is the new start - re = _pairs[$_RIX_OPEN + (isexpr ^= 1)] // switch mode and swap regexp + re = _bp[$_RIX_OPEN + (isexpr ^= 1)] // switch mode and swap regexp re.lastIndex = start // update the regex pointer } } @@ -212,7 +235,7 @@ var brackets = (function (UNDEF) { // tmpl, from the HTML part too. function unescapeStr(str) { if (tmpl || isexpr) - parts.push(str && str.replace(_pairs[$_RIX_ESC], '$1')) + parts.push(str && str.replace(_bp[$_RIX_ESC], '$1')) else parts.push(str) } @@ -253,8 +276,8 @@ var brackets = (function (UNDEF) { * @returns {Array} - Brackets array in internal format */ _brackets.array = function array(pair) { - _reset(pair || _brackets.settings.brackets) // fix #1314 - return _pairs + if (!pair) pair = _brackets.settings.brackets // fix #1314 + return _create(pair) } // Inmediate execution diff --git a/package.json b/package.json index 934d856..7b1c0f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "riot-tmpl", - "version": "2.3.14", + "version": "2.3.15", "description": "The riot template engine", "main": "dist/tmpl.js", "jsnext:main": "dist/es6.tmpl.js",