var EscapeStore = require('./escape-store'); module.exports = function Expressions() { var expressions = new EscapeStore('EXPRESSION'); var findEnd = function(data, start) { var end = start + 'expression'.length; var level = 0; var quoted = false; while (true) { var next = data[end++]; if (quoted) { quoted = next != '\'' && next != '"'; } else { quoted = next == '\'' || next == '"'; if (next == '(') level++; if (next == ')') level--; if (next == '}' && level == 1) { end--; level--; } } if (level === 0 && next == ')') break; if (!next) { end = data.substring(0, end).lastIndexOf('}'); break; } } return end; }; return { // Escapes expressions by replacing them by a special // marker for further restoring. It's done via string scanning // instead of regexps to speed up the process. escape: function(data) { var nextStart = 0; var nextEnd = 0; var cursor = 0; var tempData = []; for (; nextEnd < data.length;) { nextStart = data.indexOf('expression(', nextEnd); if (nextStart == -1) break; nextEnd = findEnd(data, nextStart); var expression = data.substring(nextStart, nextEnd); var placeholder = expressions.store(expression); tempData.push(data.substring(cursor, nextStart)); tempData.push(placeholder); cursor = nextEnd; } return tempData.length > 0 ? tempData.join('') + data.substring(cursor, data.length) : data; }, restore: function(data) { return data.replace(expressions.placeholderRegExp, expressions.restore); } }; };