-
-
Notifications
You must be signed in to change notification settings - Fork 66
/
compile-string.ts
112 lines (94 loc) · 2.97 KB
/
compile-string.ts
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
103
104
105
106
107
108
109
110
111
112
import Parse from './parse'
/* TYPES */
import type { EtaConfig } from './config'
import type { AstObject } from './parse'
/* END TYPES */
/**
* Compiles a template string to a function string. Most often users just use `compile()`, which calls `compileToString` and creates a new function using the result
*
* **Example**
*
* ```js
* compileToString("Hi <%= it.user %>", eta.config)
* // "var tR='',include=E.include.bind(E),includeFile=E.includeFile.bind(E);tR+='Hi ';tR+=E.e(it.user);if(cb){cb(null,tR)} return tR"
* ```
*/
export default function compileToString(str: string, config: EtaConfig): string {
const buffer: Array<AstObject> = Parse(str, config)
let res =
"var tR='',__l,__lP" +
(config.include ? ',include=E.include.bind(E)' : '') +
(config.includeFile ? ',includeFile=E.includeFile.bind(E)' : '') +
'\nfunction layout(p,d){__l=p;__lP=d}\n' +
(config.useWith ? 'with(' + config.varName + '||{}){' : '') +
compileScope(buffer, config) +
(config.includeFile
? 'if(__l)tR=' +
(config.async ? 'await ' : '') +
`includeFile(__l,Object.assign(${config.varName},{body:tR},__lP))\n`
: config.include
? 'if(__l)tR=' +
(config.async ? 'await ' : '') +
`include(__l,Object.assign(${config.varName},{body:tR},__lP))\n`
: '') +
'if(cb){cb(null,tR)} return tR' +
(config.useWith ? '}' : '')
if (config.plugins) {
for (let i = 0; i < config.plugins.length; i++) {
const plugin = config.plugins[i]
if (plugin.processFnString) {
res = plugin.processFnString(res, config)
}
}
}
return res
}
/**
* Loops through the AST generated by `parse` and transform each item into JS calls
*
* **Example**
*
* ```js
* // AST version of 'Hi <%= it.user %>'
* let templateAST = ['Hi ', { val: 'it.user', t: 'i' }]
* compileScope(templateAST, eta.config)
* // "tR+='Hi ';tR+=E.e(it.user);"
* ```
*/
function compileScope(buff: Array<AstObject>, config: EtaConfig) {
let i = 0
const buffLength = buff.length
let returnStr = ''
for (i; i < buffLength; i++) {
const currentBlock = buff[i]
if (typeof currentBlock === 'string') {
const str = currentBlock
// we know string exists
returnStr += "tR+='" + str + "'\n"
} else {
const type = currentBlock.t // ~, s, !, ?, r
let content = currentBlock.val || ''
if (type === 'r') {
// raw
if (config.filter) {
content = 'E.filter(' + content + ')'
}
returnStr += 'tR+=' + content + '\n'
} else if (type === 'i') {
// interpolate
if (config.filter) {
content = 'E.filter(' + content + ')'
}
if (config.autoEscape) {
content = 'E.e(' + content + ')'
}
returnStr += 'tR+=' + content + '\n'
// reference
} else if (type === 'e') {
// execute
returnStr += content + '\n' // you need a \n in case you have <% } %>
}
}
}
return returnStr
}