UNPKG

11.5 kBJavaScriptView Raw
1
2const babylon = require('babylon');
3const traverse = require('@babel/traverse')["default"];
4const generate = require('@babel/generator')["default"];
5// traverse path的时候解析path
6const parseTemplate = require('./parser/index.js');
7// 对于模板的预处理 - 后置处理 - 等正则的一些替换;
8const processTemplate = require('./common/process-template.js')
9// 目前事件的处理有两处:第一,c-bind,第二c-model,两者互相不影响;借鉴于此,需要新增处理事件支持传参的形式,而此时就需要处理c-bind;
10const cliUtils = require('chameleon-tool-utils');
11exports.compileTemplateForCml = function (source, type, options) {
12 let errorInfo = processTemplate.preCheckTemplateSyntax(source, type, options)
13 if (errorInfo) {
14 // throw new Error(`${errorInfo} in ${options.filePath}`)
15 cliUtils.log.warn(`${errorInfo} in ${options.filePath}`);
16 }
17 // source
18 // 预处理html模板中的注释,jsx不支持,这个需要优先处理,防止解析 < > 的时候出现问题;
19 source = processTemplate.preDisappearAnnotation(source);
20 // 预处理:< > ==> _cml_lt_lmc_ _cml_gt_lmc_,这么做的目的为了防止 preParseMustache 解析 > < 中间的内容报错,所以需要将 > < 先转化 gt lt的形式,等 preParseMustache 解析完毕之后即可将其转化回来;
21 source = processTemplate.preParseGtLt(source);
22 source = processTemplate.preParseDiffPlatformTag(source, type);
23 // 预处理:属性 jsx不支持 :name="sth" ==> v-bind:name="sth"
24 source = processTemplate.preParseBindAttr(source);
25 // 预处理vue事件 @click="handleClick" ==> c-bind:click="handleClick"
26 source = processTemplate.preParseVueEvent(source);
27 // 预处理 标签内的 {{item.id}} 这种语法jsx无法识别,转化为 _cml{item.id}lmc_
28 source = processTemplate.preParseMustache(source);
29 // 预处理:解析_cml_lt_lmc_ ==> <; _cml_gt_lmc_ ==> >
30 source = processTemplate.postParseLtGt(source);
31 // 预处理c-animation 标签,给这个标签增加一个 c-bind:transitionend = "_animationCb(value,$event)",注意这个必须在所有预处理的最后,因为前面的预处理兼容了jsx的语法;
32 source = processTemplate.preParseAnimation(source, type);
33 source = processTemplate.preParseAliComponent(source, type, options);
34 if (type === 'web') {
35 source = compileWebTemplate(source, type, options).code;
36 }
37 if (type === 'weex') {
38 source = compileWeexTemplate(source, type, options).code;
39 }
40 if (type === 'wx') {
41 source = compileWxTemplate(source, type, options).code;
42 }
43 if (type === 'qq') {
44 source = compileQqTemplate(source, type, options).code;
45 }
46 if (type === 'alipay') {
47 source = compileAliPayTemplate(source, type, options).code;
48 }
49 if (type === 'baidu') {
50 source = compileBaiduTemplate(source, type, options).code;
51 }
52 // 后置处理,解析origin-tag ==> tag
53 source = processTemplate.postParseOriginTag(source)
54 // 后置处理:解析_cml{str}lmc_ ==> {{str}}
55 source = processTemplate.postParseMustache(source)
56 // 后置处理:用于处理 \u ,便于解析unicode 中文
57 source = processTemplate.postParseUnicode(source);
58 // 后置处理,所有的 __CML_NATIVE_EVENTS__ ==> .native
59 source = processTemplate.transformNativeEvent(source)
60 return {
61 source,
62 usedBuildInTagMap: options.usedBuildInTagMap
63 }
64}
65function compileWebTemplate(source, type, options) {
66
67 const ast = babylon.parse(source, {
68 plugins: ['jsx']
69 })
70 traverse(ast, {
71 enter(path) {
72 parseTemplate.parseClassStatement(path, type, options);
73 parseTemplate.parseTagForSlider(path, type, options);
74
75 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
76
77 parseTemplate.parseTag(path, type, options);// 替换标签;
78
79 parseTemplate.parseAnimationStatement(path, type, options);
80 parseTemplate.parseConditionalStatement(path, type, options);// 替换c-if c-else
81 parseTemplate.parseEventListener(path, type, options) // 处理 c-bind c-catch
82 parseTemplate.parseIterationStatement(path, type, options);// 处理 c-for
83
84 // 解析c-model ==> v-bind:value="modelValue" v-on:input="_cmlModelEventProxy($event,modelKey)"
85 parseTemplate.parseDirectiveStatement(path, type, options);
86
87 parseTemplate.parseStyleStatement(path, type, options);
88 // wx alipay 的 {{}}语法中转换成vue属性表达式 所有的响应式属性的处理成vue识别的; propname="a{{b}}" -> :propname = "'a'+(b)"
89 parseTemplate.parseAttributeStatement(path, type, options);
90 // 最后处理模板中的标签 block-->template
91 parseTemplate.afterParseTag(path, type, options);
92 }
93 })
94 return generate(ast);
95}
96function compileWeexTemplate(source, type, options) {
97
98 const ast = babylon.parse(source, {
99 plugins: ['jsx']
100 })
101 traverse(ast, {
102 enter(path) {
103 parseTemplate.parseClassStatement(path, type, options);
104
105 // 这个最优先;
106 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
107 parseTemplate.parseTag(path, type, options);// 替换标签;
108
109 parseTemplate.parseAnimationStatement(path, type, options);
110 parseTemplate.parseConditionalStatement(path, type, options);// 替换c-if c-else
111 parseTemplate.parseEventListener(path, type, options)
112 parseTemplate.parseIterationStatement(path, type, options);
113 // 解析c-model ==> v-bind:value="modelValue" v-on:input="_cmlModelEventProxy($event,modelKey)"
114 parseTemplate.parseDirectiveStatement(path, type, options);
115 // style的处理判断是否是动态和静态的依赖{{}} 需要在parseAttributeStatement之前执行,parseAttributeStatement会处理掉{{}}
116 parseTemplate.parseStyleStatement(path, type, options)
117 // {{}}中转换成vue属性表达式 class="a{{b}}" -> :class = "'a'+(b)"
118 parseTemplate.parseAttributeStatement(path, type, options);
119 parseTemplate.afterParseTag(path, type, options);
120 }
121 })
122 return generate(ast);
123}
124function compileWxTemplate(source, type, options) {
125
126 const ast = babylon.parse(source, {
127 plugins: ['jsx']
128 })
129 traverse(ast, {
130 enter(path) {
131 parseTemplate.parseClassStatement(path, type, options);
132
133 // 微信端支持安震 slider
134 parseTemplate.parseTagForSlider(path, type, options);
135 // 微信端支持ref
136 parseTemplate.parseRefStatement(path, type, options)
137
138 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
139 // 微信端需要特殊处理支持 component
140
141 parseTemplate.parseTag(path, type, options);// 替换标签;
142
143 parseTemplate.parseAnimationStatement(path, type, options);
144
145 parseTemplate.afterParseTag(path, type, options);
146 parseTemplate.parseConditionalStatement(path, type, options);// 替换c-if c-else
147 parseTemplate.parseEventListener(path, type, options);
148
149 // 解析c-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
150 parseTemplate.parseDirectiveStatement(path, type, options);
151
152 parseTemplate.parseIterationStatement(path, type, options);
153 //
154 parseTemplate.parseStyleStatement(path, type, options);
155 // <component is="{{currentComp}}"></component>
156 parseTemplate.parseVue2WxStatement(path, type, options);
157 }
158 })
159 return generate(ast);
160}
161function compileQqTemplate(source, type, options) {
162
163 const ast = babylon.parse(source, {
164 plugins: ['jsx']
165 })
166 traverse(ast, {
167 enter(path) {
168 parseTemplate.parseClassStatement(path, type, options);
169
170 // 微信端支持安震 slider
171 parseTemplate.parseTagForSlider(path, type, options);
172 // 微信端支持ref
173 parseTemplate.parseRefStatement(path, type, options)
174
175 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
176 // 微信端需要特殊处理支持 component
177
178 parseTemplate.parseTag(path, type, options);// 替换标签;
179
180 parseTemplate.parseAnimationStatement(path, type, options);
181
182 parseTemplate.afterParseTag(path, type, options);
183 parseTemplate.parseConditionalStatement(path, type, options);// 替换c-if c-else
184 parseTemplate.parseEventListener(path, type, options);
185
186 // 解析c-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
187 parseTemplate.parseDirectiveStatement(path, type, options);
188
189 parseTemplate.parseIterationStatement(path, type, options);
190 //
191 parseTemplate.parseStyleStatement(path, type, options);
192 // <component is="{{currentComp}}"></component>
193 parseTemplate.parseVue2WxStatement(path, type, options);
194 }
195 })
196 return generate(ast);
197}
198function compileAliPayTemplate(source, type, options) {
199 const ast = babylon.parse(source, {
200 plugins: ['jsx']
201 })
202 traverse(ast, {
203 enter(path) {
204 parseTemplate.parseClassStatement(path, type, options);
205
206 // 微信端支持安震 slider
207 parseTemplate.parseTagForSlider(path, type, options);
208 // 微信端支持ref
209 parseTemplate.parseRefStatement(path, type, options)
210
211 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
212 // 微信端需要特殊处理支持 component
213
214 parseTemplate.parseTag(path, type, options);// 替换标签;
215
216 parseTemplate.parseAnimationStatement(path, type, options);
217
218 parseTemplate.afterParseTag(path, type, options);
219 parseTemplate.parseConditionalStatement(path, type, options);// 替换c-if c-else
220 parseTemplate.parseEventListener(path, type, options);
221
222 // 解析c-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
223 parseTemplate.parseDirectiveStatement(path, type, options);
224
225 parseTemplate.parseIterationStatement(path, type, options);
226 //
227 parseTemplate.parseStyleStatement(path, type, options);
228 // 用于支持 <component is="{{currentComp}}"></component>
229 parseTemplate.parseVue2WxStatement(path, type, options);
230 }
231 })
232 return generate(ast);
233}
234function compileBaiduTemplate(source, type, options) {
235 const ast = babylon.parse(source, {
236 plugins: ['jsx']
237 })
238 traverse(ast, {
239 enter(path) {
240 parseTemplate.parseClassStatement(path, type, options);
241
242 // 微信端支持安震 slider
243 parseTemplate.parseTagForSlider(path, type, options);
244 // 微信端支持ref
245 parseTemplate.parseRefStatement(path, type, options)
246
247 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
248 // 微信端需要特殊处理支持 component
249
250 parseTemplate.parseTag(path, type, options);// 替换标签;
251
252 parseTemplate.parseAnimationStatement(path, type, options);
253
254 parseTemplate.afterParseTag(path, type, options);
255 parseTemplate.parseConditionalStatement(path, type, options);// 替换c-if c-else
256 parseTemplate.parseEventListener(path, type, options);
257
258 // 解析c-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
259 parseTemplate.parseDirectiveStatement(path, type, options);
260
261 parseTemplate.parseIterationStatement(path, type, options);
262 //
263 parseTemplate.parseStyleStatement(path, type, options);
264 // <component is="{{currentComp}}"></component>
265 parseTemplate.parseVue2WxStatement(path, type, options);
266 }
267 })
268 return generate(ast);
269}