|
|
@@ -0,0 +1,117 @@
|
|
|
+var Cache = require('../cache')
|
|
|
+var config = require('../config')
|
|
|
+var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g
|
|
|
+var cache, tagRE, htmlRE, firstChar, lastChar
|
|
|
+
|
|
|
+/**
|
|
|
+ * Escape a string so it can be used in a RegExp
|
|
|
+ * constructor.
|
|
|
+ *
|
|
|
+ * @param {String} str
|
|
|
+ */
|
|
|
+
|
|
|
+function escapeRegex (str) {
|
|
|
+ return str.replace(regexEscapeRE, '\\$&')
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Compile the interpolation tag regex.
|
|
|
+ *
|
|
|
+ * @return {RegExp}
|
|
|
+ */
|
|
|
+
|
|
|
+function compileRegex () {
|
|
|
+ config._delimitersChanged = false
|
|
|
+ var open = config.delimiters[0]
|
|
|
+ var close = config.delimiters[1]
|
|
|
+ firstChar = open.charAt(0)
|
|
|
+ lastChar = close.charAt(close.length - 1)
|
|
|
+ var firstCharRE = escapeRegex(firstChar)
|
|
|
+ var lastCharRE = escapeRegex(lastChar)
|
|
|
+ var openRE = escapeRegex(open)
|
|
|
+ var closeRE = escapeRegex(close)
|
|
|
+ tagRE = new RegExp(
|
|
|
+ firstCharRE + '?' + openRE +
|
|
|
+ '(.+?)' +
|
|
|
+ closeRE + lastCharRE + '?',
|
|
|
+ 'g'
|
|
|
+ )
|
|
|
+ htmlRE = new RegExp(
|
|
|
+ '^' + firstCharRE + openRE +
|
|
|
+ '.*' +
|
|
|
+ closeRE + lastCharRE + '$'
|
|
|
+ )
|
|
|
+ // reset cache
|
|
|
+ cache = new Cache(1000)
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Parse a template text string into an array of tokens.
|
|
|
+ *
|
|
|
+ * @param {String} text
|
|
|
+ * @return {Array<Object> | null}
|
|
|
+ * - {String} type
|
|
|
+ * - {String} value
|
|
|
+ * - {Boolean} [html]
|
|
|
+ * - {Boolean} [oneTime]
|
|
|
+ */
|
|
|
+
|
|
|
+exports.parse = function (text) {
|
|
|
+ if (config._delimitersChanged) {
|
|
|
+ compileRegex()
|
|
|
+ }
|
|
|
+ var hit = cache.get(text)
|
|
|
+ if (hit) {
|
|
|
+ return hit
|
|
|
+ }
|
|
|
+ if (!tagRE.test(text)) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ var tokens = []
|
|
|
+ var lastIndex = tagRE.lastIndex = 0
|
|
|
+ var match, index, value, oneTime
|
|
|
+ while (match = tagRE.exec(text)) {
|
|
|
+ index = match.index
|
|
|
+ // push text token
|
|
|
+ if (index > lastIndex) {
|
|
|
+ tokens.push({
|
|
|
+ value: text.slice(lastIndex, index)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // tag token
|
|
|
+ value = match[1].trim()
|
|
|
+ oneTime = value.charAt(0) === '*'
|
|
|
+ tokens.push({
|
|
|
+ tag: true,
|
|
|
+ value: oneTime ? value.slice(1) : value,
|
|
|
+ html: htmlRE.test(match[0]),
|
|
|
+ oneTime: oneTime
|
|
|
+ })
|
|
|
+ lastIndex = index + match[0].length
|
|
|
+ }
|
|
|
+ if (lastIndex < text.length - 1) {
|
|
|
+ tokens.push({
|
|
|
+ value: text.slice(lastIndex)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ cache.put(text, tokens)
|
|
|
+ return tokens
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Parse a template text string into an expression
|
|
|
+ *
|
|
|
+ * @param {String} text
|
|
|
+ * @return {String}
|
|
|
+ */
|
|
|
+
|
|
|
+exports.textToExpression = function (text) {
|
|
|
+ var tokens = exports.parse(text)
|
|
|
+ if (tokens) {
|
|
|
+ return tokens.map(function (token) {
|
|
|
+ return token.tag
|
|
|
+ ? token.value
|
|
|
+ : ('"' + token.value + '"')
|
|
|
+ }).join('+')
|
|
|
+ }
|
|
|
+}
|