UNPKG

10.4 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.compileTemplateForVue = 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模板中的注释,将其删除;这个需要优先处理,防止解析 < > 的时候出现问题;
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 // 预处理:属性 :name="sth" ==> v-bind:name="sth" jsx无法解析 :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
35 if (type === 'web') {
36 source = compileWebTemplate(source, type, options).code;
37 }
38 if (type === 'weex') {
39 source = compileWeexTemplate(source, type, options).code;
40 }
41 if (type === 'wx') {
42 source = compileWxTemplate(source, type, options).code;
43 }
44 if (type === 'qq') {
45 source = compileQqTemplate(source, type, options).code;
46 }
47 if (type === 'alipay') {
48 source = compileAliPayTemplate(source, type, options).code;
49 }
50 if (type === 'baidu') {
51 source = compileBaiduTemplate(source, type, options).code;
52 }
53 // 后置处理,解析origin-tag ==> tag
54 source = processTemplate.postParseOriginTag(source)
55 // 后置处理:解析_cml{str}lmc_ ==> {{str}}
56 source = processTemplate.postParseMustache(source)
57 // 后置处理:用于处理 \u ,便于解析unicode 中文
58 source = processTemplate.postParseUnicode(source);
59 // 后置处理,所有的 __CML_NATIVE_EVENTS__ ==> .native
60 source = processTemplate.transformNativeEvent(source)
61 return {
62 source,
63 usedBuildInTagMap: options.usedBuildInTagMap
64 }
65}
66function compileWebTemplate(source, type, options) {
67
68 const ast = babylon.parse(source, {
69 plugins: ['jsx']
70 })
71 traverse(ast, {
72 enter(path) {
73 parseTemplate.parseClassStatement(path, type, options);
74 // 微信端支持安震 slider
75 parseTemplate.parseTagForSlider(path, type, options);
76 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
77
78 parseTemplate.parseTag(path, type, options);// 替换标签;
79
80 parseTemplate.parseAnimationStatement(path, type, options);
81
82 parseTemplate.parseEventListener(path, type, options)
83
84 // 解析c-model ==> v-bind:value="modelValue" v-on:input="_cmlModelEventProxy($event,modelKey)"
85 parseTemplate.parseDirectiveStatement(path, type, options);
86 parseTemplate.parseStyleStatement(path, type, options)
87 // wx alipay 的 {{}}语法中转换成vue属性表达式 class="a{{b}}" -> :class = "'a'+(b)"
88 parseTemplate.parseAttributeStatement(path, type, options);
89 // 最后处理模板中的标签 block-->template
90 parseTemplate.afterParseTag(path, type, options);
91 }
92 })
93 return generate(ast);
94}
95function compileWeexTemplate(source, type, options) {
96
97 const ast = babylon.parse(source, {
98 plugins: ['jsx']
99 })
100 traverse(ast, {
101 enter(path) {
102 parseTemplate.parseClassStatement(path, type, options);
103
104 // 这个最优先;
105 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
106 parseTemplate.parseTag(path, type, options);// 替换标签;
107
108 parseTemplate.parseAnimationStatement(path, type, options);
109
110 parseTemplate.parseEventListener(path, type, options)
111 // 解析v-model ==> v-bind:value="modelValue" v-on:input="_cmlModelEventProxy($event,modelKey)"
112 parseTemplate.parseDirectiveStatement(path, type, options);
113 // style的处理判断是否是动态和静态的依赖{{}} 需要在parseAttributeStatement之前执行,parseAttributeStatement会处理掉{{}}
114 parseTemplate.parseStyleStatement(path, type, options)
115 // {{}}中转换成vue属性表达式 class="a{{b}}" -> :class = "'a'+(b)"
116 parseTemplate.parseAttributeStatement(path, type, options);
117 parseTemplate.afterParseTag(path, type, options);
118 }
119 })
120 return generate(ast);
121}
122function compileWxTemplate(source, type, options) {
123
124 const ast = babylon.parse(source, {
125 plugins: ['jsx']
126 })
127 traverse(ast, {
128 enter(path) {
129 parseTemplate.parseClassStatement(path, type, options);
130 // 微信端支持安震 slider
131 parseTemplate.parseTagForSlider(path, type, options);
132 // 微信端支持 ref;
133 parseTemplate.parseRefStatement(path, type, options)
134 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
135 parseTemplate.parseTag(path, type, options);// 替换标签;
136
137 parseTemplate.parseAnimationStatement(path, type, options);
138 parseTemplate.afterParseTag(path, type, options);
139 parseTemplate.parseEventListener(path, type, options);
140 // 解析v-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
141 parseTemplate.parseDirectiveStatement(path, type, options);
142 // parseTemplate.parseIterationStatement(path,type,options);
143 parseTemplate.parseStyleStatement(path, type, options);
144 // 用于支持 v-bind:name="sth" ==> name="{{sth}}" v-for v-if
145 parseTemplate.parseVue2WxStatement(path, type, options);
146 }
147 })
148 return generate(ast);
149}
150function compileQqTemplate(source, type, options) {
151
152 const ast = babylon.parse(source, {
153 plugins: ['jsx']
154 })
155 traverse(ast, {
156 enter(path) {
157 parseTemplate.parseClassStatement(path, type, options);
158 // 微信端支持安震 slider
159 parseTemplate.parseTagForSlider(path, type, options);
160 // 微信端支持 ref;
161 parseTemplate.parseRefStatement(path, type, options)
162 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
163 parseTemplate.parseTag(path, type, options);// 替换标签;
164
165 parseTemplate.parseAnimationStatement(path, type, options);
166 parseTemplate.afterParseTag(path, type, options);
167 parseTemplate.parseEventListener(path, type, options);
168 // 解析v-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
169 parseTemplate.parseDirectiveStatement(path, type, options);
170 // parseTemplate.parseIterationStatement(path,type,options);
171 parseTemplate.parseStyleStatement(path, type, options);
172 // 用于支持 v-bind:name="sth" ==> name="{{sth}}" v-for v-if
173 parseTemplate.parseVue2WxStatement(path, type, options);
174 }
175 })
176 return generate(ast);
177}
178function compileAliPayTemplate(source, type, options) {
179 const ast = babylon.parse(source, {
180 plugins: ['jsx']
181 })
182 traverse(ast, {
183 enter(path) {
184 parseTemplate.parseClassStatement(path, type, options);
185 // 微信端支持安震 slider
186 parseTemplate.parseTagForSlider(path, type, options);
187 // 微信端支持 ref;
188 parseTemplate.parseRefStatement(path, type, options)
189 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
190 parseTemplate.parseTag(path, type, options);// 替换标签;
191
192 parseTemplate.parseAnimationStatement(path, type, options);
193 parseTemplate.afterParseTag(path, type, options);
194 parseTemplate.parseEventListener(path, type, options);
195 // 解析v-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
196 parseTemplate.parseDirectiveStatement(path, type, options);
197 parseTemplate.parseStyleStatement(path, type, options);
198 // 用于支持 v-bind:name="sth" ==> name="{{sth}}" v-for v-if
199 parseTemplate.parseVue2WxStatement(path, type, options);
200 }
201 })
202 return generate(ast);
203}
204function compileBaiduTemplate(source, type, options) {
205 const ast = babylon.parse(source, {
206 plugins: ['jsx']
207 })
208 traverse(ast, {
209 enter(path) {
210 parseTemplate.parseClassStatement(path, type, options);
211 // 微信端支持安震 slider
212 parseTemplate.parseTagForSlider(path, type, options);
213 // 微信端支持 ref;
214 parseTemplate.parseRefStatement(path, type, options)
215 parseTemplate.parseBuildTag(path, type, options) // 解析内置标签;
216 parseTemplate.parseTag(path, type, options);// 替换标签;
217
218 parseTemplate.parseAnimationStatement(path, type, options);
219 parseTemplate.afterParseTag(path, type, options);
220 parseTemplate.parseEventListener(path, type, options);
221 // 解析v-model ==> value="{{modelValue}}" bindinput="_cmlModelEventProxy($event) data-modelkey="modelKey"
222 parseTemplate.parseDirectiveStatement(path, type, options);
223 parseTemplate.parseStyleStatement(path, type, options);
224 // 用于支持 v-bind:name="sth" ==> name="{{sth}}" v-for v-if
225 parseTemplate.parseVue2WxStatement(path, type, options);
226 }
227 })
228 return generate(ast);
229}