-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinterpolate.js
102 lines (90 loc) · 2.35 KB
/
interpolate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
'use strict'
const compiler = require('@nx-js/compiler-util')
const tokenCache = new Map()
function interpolate (node) {
if (node.nodeType !== 3) return
createTokens(node).forEach(processToken, node)
}
interpolate.$name = 'interpolate'
interpolate.$require = ['observe']
interpolate.$type = 'content'
module.exports = interpolate
function createTokens (node) {
const nodeValue = node.nodeValue
let tokens = tokenCache.get(nodeValue)
if (!tokens) {
tokens = parseValue(node.nodeValue)
tokenCache.set(nodeValue, tokens)
return tokens
}
return tokens.map(cloneToken)
}
function cloneToken (token) {
if (typeof token === 'object') {
return {
observed: token.observed,
expression: token.expression,
toString: token.toString
}
}
return token
}
function processToken (token, index, tokens) {
if (typeof token === 'object') {
const expression = compiler.compileExpression(token.expression)
if (token.observed) {
this.$observe(interpolateToken, expression, token, tokens)
} else {
interpolateToken.call(this, expression, token, tokens)
}
}
}
function interpolateToken (expression, token, tokens) {
let value = expression(this.$state)
value = (value !== undefined) ? value : ''
if (token.value !== value) {
token.value = value
this.nodeValue = (1 < tokens.length) ? tokens.join('') : value
}
}
function parseValue (string) {
const tokens = []
const length = string.length
let expression = false
let anchor = 0
let depth = 0
let token
for (let i = 0; i < length; i++) {
const char = string[i]
if (expression) {
if (char === '{') {
depth++
} else if (char === '}') {
depth--
}
if (depth === 0) {
token.expression = string.slice(anchor, i)
token.toString = tokenToString
tokens.push(token)
anchor = i + 1
expression = false
}
} else {
if (i === length - 1) {
tokens.push(string.slice(anchor, i + 1))
} else if ((char === '$' || char === '@') && string.charAt(i + 1) === '{') {
if (i !== anchor) {
tokens.push(string.slice(anchor, i))
}
token = {observed: (char === '@')}
anchor = i + 2
depth = 0
expression = true
}
}
}
return tokens
}
function tokenToString () {
return String(this.value)
}