babel-plugin-mettle 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/License +1 -1
- package/dist/babel-plugin-mettle.js +1 -284
- package/package.json +4 -8
- package/dist/babel-plugin-mettle.mjs +0 -284
package/License
CHANGED
|
@@ -1,284 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
const MODE_TEXT = 1;
|
|
3
|
-
const MODE_WHITESPACE = 2;
|
|
4
|
-
const MODE_TAGNAME = 3;
|
|
5
|
-
const MODE_COMMENT = 4;
|
|
6
|
-
const MODE_PROP_SET = 5;
|
|
7
|
-
const MODE_PROP_APPEND = 6;
|
|
8
|
-
const CHILD_APPEND = 0;
|
|
9
|
-
const CHILD_RECURSE = 2;
|
|
10
|
-
const TAG_SET = 3;
|
|
11
|
-
const PROPS_ASSIGN = 4;
|
|
12
|
-
const PROP_SET = MODE_PROP_SET;
|
|
13
|
-
const PROP_APPEND = MODE_PROP_APPEND;
|
|
14
|
-
const treeify = function (built, fields) {
|
|
15
|
-
const _treeify = function (built) {
|
|
16
|
-
let tag = '';
|
|
17
|
-
let currentProps = null;
|
|
18
|
-
const props = [];
|
|
19
|
-
const children = [];
|
|
20
|
-
for (let i = 1; i < built.length; i++) {
|
|
21
|
-
const type = built[i++];
|
|
22
|
-
const value = built[i] ? fields[built[i++] - 1] : built[++i];
|
|
23
|
-
if (type === TAG_SET) {
|
|
24
|
-
tag = value;
|
|
25
|
-
} else if (type === PROPS_ASSIGN) {
|
|
26
|
-
props.push(value);
|
|
27
|
-
currentProps = null;
|
|
28
|
-
} else if (type === PROP_SET) {
|
|
29
|
-
if (!currentProps) {
|
|
30
|
-
currentProps = Object.create(null);
|
|
31
|
-
props.push(currentProps);
|
|
32
|
-
}
|
|
33
|
-
currentProps[built[++i]] = [value];
|
|
34
|
-
} else if (type === PROP_APPEND) {
|
|
35
|
-
currentProps[built[++i]].push(value);
|
|
36
|
-
} else if (type === CHILD_RECURSE) {
|
|
37
|
-
children.push(_treeify(value));
|
|
38
|
-
} else if (type === CHILD_APPEND) {
|
|
39
|
-
children.push(value);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
tag: tag,
|
|
44
|
-
props: props,
|
|
45
|
-
children: children
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
const {
|
|
49
|
-
children
|
|
50
|
-
} = _treeify(built);
|
|
51
|
-
return children.length > 1 ? children : children[0];
|
|
52
|
-
};
|
|
53
|
-
const build = function (statics) {
|
|
54
|
-
let mode = MODE_TEXT;
|
|
55
|
-
let buffer = '';
|
|
56
|
-
let quote = '';
|
|
57
|
-
let current = [0];
|
|
58
|
-
let char, propName;
|
|
59
|
-
const commit = function (field) {
|
|
60
|
-
if (mode === MODE_TEXT && (field || (buffer = buffer.replace(/^\s*\n\s*|\s*\n\s*$/g, '')))) {
|
|
61
|
-
current.push(CHILD_APPEND, field, buffer);
|
|
62
|
-
} else if (mode === MODE_TAGNAME && (field || buffer)) {
|
|
63
|
-
current.push(TAG_SET, field, buffer);
|
|
64
|
-
mode = MODE_WHITESPACE;
|
|
65
|
-
} else if (mode === MODE_WHITESPACE && buffer === '...' && field) {
|
|
66
|
-
current.push(PROPS_ASSIGN, field, 0);
|
|
67
|
-
} else if (mode === MODE_WHITESPACE && buffer && !field) {
|
|
68
|
-
current.push(PROP_SET, 0, true, buffer);
|
|
69
|
-
} else if (mode >= MODE_PROP_SET) {
|
|
70
|
-
if (buffer || !field && mode === MODE_PROP_SET) {
|
|
71
|
-
current.push(mode, 0, buffer, propName);
|
|
72
|
-
mode = MODE_PROP_APPEND;
|
|
73
|
-
}
|
|
74
|
-
if (field) {
|
|
75
|
-
current.push(mode, field, 0, propName);
|
|
76
|
-
mode = MODE_PROP_APPEND;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
buffer = '';
|
|
80
|
-
};
|
|
81
|
-
for (let i = 0; i < statics.length; i++) {
|
|
82
|
-
if (i) {
|
|
83
|
-
if (mode === MODE_TEXT) {
|
|
84
|
-
commit();
|
|
85
|
-
}
|
|
86
|
-
commit(i);
|
|
87
|
-
}
|
|
88
|
-
for (let j = 0; j < statics[i].length; j++) {
|
|
89
|
-
char = statics[i][j];
|
|
90
|
-
if (mode === MODE_TEXT) {
|
|
91
|
-
if (char === '<') {
|
|
92
|
-
commit();
|
|
93
|
-
current = [current];
|
|
94
|
-
mode = MODE_TAGNAME;
|
|
95
|
-
} else {
|
|
96
|
-
buffer += char;
|
|
97
|
-
}
|
|
98
|
-
} else if (mode === MODE_COMMENT) {
|
|
99
|
-
if (buffer === '--' && char === '>') {
|
|
100
|
-
mode = MODE_TEXT;
|
|
101
|
-
buffer = '';
|
|
102
|
-
} else {
|
|
103
|
-
buffer = char + buffer[0];
|
|
104
|
-
}
|
|
105
|
-
} else if (quote) {
|
|
106
|
-
if (char === quote) {
|
|
107
|
-
quote = '';
|
|
108
|
-
} else {
|
|
109
|
-
buffer += char;
|
|
110
|
-
}
|
|
111
|
-
} else if (char === '"' || char === "'") {
|
|
112
|
-
quote = char;
|
|
113
|
-
} else if (char === '>') {
|
|
114
|
-
commit();
|
|
115
|
-
mode = MODE_TEXT;
|
|
116
|
-
} else if (!mode) ; else if (char === '=') {
|
|
117
|
-
mode = MODE_PROP_SET;
|
|
118
|
-
propName = buffer;
|
|
119
|
-
buffer = '';
|
|
120
|
-
} else if (char === '/' && (mode < MODE_PROP_SET || statics[i][j + 1] === '>')) {
|
|
121
|
-
commit();
|
|
122
|
-
if (mode === MODE_TAGNAME) {
|
|
123
|
-
current = current[0];
|
|
124
|
-
}
|
|
125
|
-
mode = current;
|
|
126
|
-
(current = current[0]).push(CHILD_RECURSE, 0, mode);
|
|
127
|
-
mode = MODE_SLASH;
|
|
128
|
-
} else if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
|
|
129
|
-
// <a disabled>
|
|
130
|
-
commit();
|
|
131
|
-
mode = MODE_WHITESPACE;
|
|
132
|
-
} else {
|
|
133
|
-
buffer += char;
|
|
134
|
-
}
|
|
135
|
-
if (mode === MODE_TAGNAME && buffer === '!--') {
|
|
136
|
-
mode = MODE_COMMENT;
|
|
137
|
-
current = current[0];
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
commit();
|
|
142
|
-
return current;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @param {Babel} babel
|
|
147
|
-
* @param {object} options
|
|
148
|
-
* @param {string} [options.tag=html] The tagged template "tag" function name to process.
|
|
149
|
-
*/
|
|
150
|
-
|
|
151
|
-
function mettleBabelPlugin({
|
|
152
|
-
types: t
|
|
153
|
-
}, options = {}) {
|
|
154
|
-
function patternStringToRegExp(str) {
|
|
155
|
-
const parts = str.split('/').slice(1);
|
|
156
|
-
const end = parts.pop() || '';
|
|
157
|
-
return new RegExp(parts.join('/'), end);
|
|
158
|
-
}
|
|
159
|
-
function propertyName(key) {
|
|
160
|
-
if (t.isValidIdentifier(key)) {
|
|
161
|
-
return t.identifier(key);
|
|
162
|
-
}
|
|
163
|
-
return t.stringLiteral(key);
|
|
164
|
-
}
|
|
165
|
-
function objectProperties(obj) {
|
|
166
|
-
return Object.keys(obj).map(function (key) {
|
|
167
|
-
const values = obj[key].map(function (valueOrNode) {
|
|
168
|
-
return t.isNode(valueOrNode) ? valueOrNode : t.valueToNode(valueOrNode);
|
|
169
|
-
});
|
|
170
|
-
let node = values[0];
|
|
171
|
-
if (values.length > 1 && !t.isStringLiteral(node) && !t.isStringLiteral(values[1])) {
|
|
172
|
-
node = t.binaryExpression('+', t.stringLiteral(''), node);
|
|
173
|
-
}
|
|
174
|
-
values.slice(1).forEach(function (value) {
|
|
175
|
-
node = t.binaryExpression('+', node, value);
|
|
176
|
-
});
|
|
177
|
-
return t.objectProperty(propertyName(key), node);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
function stringValue(str) {
|
|
181
|
-
return t.stringLiteral(str);
|
|
182
|
-
}
|
|
183
|
-
function createVNode(tag, props, children) {
|
|
184
|
-
if (children.elements.length === 1) {
|
|
185
|
-
children = children.elements[0];
|
|
186
|
-
} else if (children.elements.length === 0) {
|
|
187
|
-
children = t.nullLiteral();
|
|
188
|
-
}
|
|
189
|
-
let key = null;
|
|
190
|
-
if (props && props.properties && Array.isArray(props.properties)) {
|
|
191
|
-
props.properties.forEach(item => {
|
|
192
|
-
if (item.key.type === 'StringLiteral' && item.key.value === 'key') {
|
|
193
|
-
key = item.value;
|
|
194
|
-
} else if (item.key.type === 'Identifier' && item.key.name === 'key') {
|
|
195
|
-
key = item.value;
|
|
196
|
-
} else {
|
|
197
|
-
key = t.nullLiteral();
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
} else {
|
|
201
|
-
key = t.nullLiteral();
|
|
202
|
-
}
|
|
203
|
-
return t.objectExpression([false, t.objectProperty(propertyName('tag'), tag), t.objectProperty(propertyName('props'), props), t.objectProperty(propertyName('children'), children), t.objectProperty(propertyName('key'), key), t.objectProperty(propertyName('el'), t.nullLiteral()), false].filter(Boolean));
|
|
204
|
-
}
|
|
205
|
-
function spreadNode(args, state) {
|
|
206
|
-
if (args.length === 0) {
|
|
207
|
-
return t.nullLiteral();
|
|
208
|
-
}
|
|
209
|
-
if (args.length > 0 && t.isNode(args[0])) {
|
|
210
|
-
args.unshift({});
|
|
211
|
-
} // 'Object.assign(x)', can be collapsed to 'x'.
|
|
212
|
-
|
|
213
|
-
if (args.length === 1) {
|
|
214
|
-
return propsNode(args[0]);
|
|
215
|
-
} // 'Object.assign({}, x)', can be collapsed to 'x'.
|
|
216
|
-
|
|
217
|
-
if (args.length === 2 && !t.isNode(args[0]) && Object.keys(args[0]).length === 0) {
|
|
218
|
-
return propsNode(args[1]);
|
|
219
|
-
}
|
|
220
|
-
const helper = state.addHelper('extends');
|
|
221
|
-
return t.callExpression(helper, args.map(propsNode));
|
|
222
|
-
}
|
|
223
|
-
function propsNode(props) {
|
|
224
|
-
return t.isNode(props) ? props : t.objectExpression(objectProperties(props));
|
|
225
|
-
}
|
|
226
|
-
function transform(node, state) {
|
|
227
|
-
if (t.isNode(node)) {
|
|
228
|
-
return node;
|
|
229
|
-
}
|
|
230
|
-
if (typeof node === 'string') {
|
|
231
|
-
return stringValue(node);
|
|
232
|
-
}
|
|
233
|
-
if (typeof node === 'undefined') {
|
|
234
|
-
return t.identifier('undefined');
|
|
235
|
-
}
|
|
236
|
-
const {
|
|
237
|
-
tag,
|
|
238
|
-
props,
|
|
239
|
-
children
|
|
240
|
-
} = node;
|
|
241
|
-
const newTag = typeof tag === 'string' ? t.stringLiteral(tag) : tag;
|
|
242
|
-
const newProps = spreadNode(props, state);
|
|
243
|
-
const newChildren = t.arrayExpression(children.map(child => transform(child, state)));
|
|
244
|
-
return createVNode(newTag, newProps, newChildren);
|
|
245
|
-
}
|
|
246
|
-
const tagName = options.tag || 'html';
|
|
247
|
-
return {
|
|
248
|
-
name: 'mettle',
|
|
249
|
-
visitor: {
|
|
250
|
-
TaggedTemplateExpression(path, state) {
|
|
251
|
-
const tag = path.node.tag.name;
|
|
252
|
-
if (tagName[0] === '/' ? patternStringToRegExp(tagName).test(tag) : tag === tagName) {
|
|
253
|
-
const statics = path.node.quasi.quasis.map(e => e.value.raw);
|
|
254
|
-
const expr = path.node.quasi.expressions;
|
|
255
|
-
const tree = treeify(build(statics), expr);
|
|
256
|
-
const node = !Array.isArray(tree) ? transform(tree, state) : t.arrayExpression(tree.map(root => transform(root, state)));
|
|
257
|
-
path.replaceWith(node);
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
CallExpression(path, state) {
|
|
261
|
-
const callee = path.node.callee;
|
|
262
|
-
const args = path.node.arguments;
|
|
263
|
-
const argsArr = Array.from(args);
|
|
264
|
-
// The parameter is a template string
|
|
265
|
-
if (callee.name === 'tem_h') {
|
|
266
|
-
const statics = argsArr[0].quasis.map(e => e.value.raw);
|
|
267
|
-
const expr = argsArr[0].expressions;
|
|
268
|
-
const tree = treeify(build(statics), expr);
|
|
269
|
-
const node = !Array.isArray(tree) ? transform(tree, state) : t.arrayExpression(tree.map(root => transform(root, state)));
|
|
270
|
-
path.replaceWith(node);
|
|
271
|
-
}
|
|
272
|
-
// The parameter is a regular string
|
|
273
|
-
else if (callee.name === 'str_h') {
|
|
274
|
-
const statics = argsArr[0].extra.rawValue;
|
|
275
|
-
const tree = treeify(build([statics]), []);
|
|
276
|
-
const node = !Array.isArray(tree) ? transform(tree, state) : t.arrayExpression(tree.map(root => transform(root, state)));
|
|
277
|
-
path.replaceWith(node);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
module.exports = mettleBabelPlugin;
|
|
1
|
+
module.exports=function({types:t}){return{name:"babel-plugin-mettle",visitor:{FunctionDeclaration(n){if(n.node.id&&/^[A-Z]/.test(n.node.id.name)){const e=n.node.body.body.find(n=>t.isReturnStatement(n));if(e&&e.argument){const n=t.functionExpression(null,[],t.blockStatement([t.returnStatement(e.argument)]));e.argument=n}}}}}};
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-plugin-mettle",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "",
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"main": "dist/babel-plugin-mettle.js",
|
|
6
|
-
"module": "dist/babel-plugin-mettle.mjs",
|
|
7
6
|
"scripts": {
|
|
8
|
-
"build": "microbundle src/index.js -f
|
|
7
|
+
"build": "microbundle src/index.js -f cjs --target node --compress --no-sourcemap"
|
|
9
8
|
},
|
|
10
9
|
"files": [
|
|
11
10
|
"dist"
|
|
@@ -19,16 +18,13 @@
|
|
|
19
18
|
},
|
|
20
19
|
"homepage": "https://github.com/maomincoding/babel-plugin-mettle#readme",
|
|
21
20
|
"keywords": [
|
|
22
|
-
"Hyperscript Tagged Markup",
|
|
23
|
-
"tagged template",
|
|
24
|
-
"template literals",
|
|
25
21
|
"virtual dom",
|
|
26
|
-
"hyperscript",
|
|
27
22
|
"babel",
|
|
28
23
|
"babel plugin",
|
|
29
24
|
"babel-plugin",
|
|
30
25
|
"mettle",
|
|
31
26
|
"mettle-js",
|
|
27
|
+
"jsx",
|
|
32
28
|
"babel-plugin-mettle"
|
|
33
29
|
],
|
|
34
30
|
"author": "maomincoding",
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
const MODE_SLASH = 0;
|
|
2
|
-
const MODE_TEXT = 1;
|
|
3
|
-
const MODE_WHITESPACE = 2;
|
|
4
|
-
const MODE_TAGNAME = 3;
|
|
5
|
-
const MODE_COMMENT = 4;
|
|
6
|
-
const MODE_PROP_SET = 5;
|
|
7
|
-
const MODE_PROP_APPEND = 6;
|
|
8
|
-
const CHILD_APPEND = 0;
|
|
9
|
-
const CHILD_RECURSE = 2;
|
|
10
|
-
const TAG_SET = 3;
|
|
11
|
-
const PROPS_ASSIGN = 4;
|
|
12
|
-
const PROP_SET = MODE_PROP_SET;
|
|
13
|
-
const PROP_APPEND = MODE_PROP_APPEND;
|
|
14
|
-
const treeify = function (built, fields) {
|
|
15
|
-
const _treeify = function (built) {
|
|
16
|
-
let tag = '';
|
|
17
|
-
let currentProps = null;
|
|
18
|
-
const props = [];
|
|
19
|
-
const children = [];
|
|
20
|
-
for (let i = 1; i < built.length; i++) {
|
|
21
|
-
const type = built[i++];
|
|
22
|
-
const value = built[i] ? fields[built[i++] - 1] : built[++i];
|
|
23
|
-
if (type === TAG_SET) {
|
|
24
|
-
tag = value;
|
|
25
|
-
} else if (type === PROPS_ASSIGN) {
|
|
26
|
-
props.push(value);
|
|
27
|
-
currentProps = null;
|
|
28
|
-
} else if (type === PROP_SET) {
|
|
29
|
-
if (!currentProps) {
|
|
30
|
-
currentProps = Object.create(null);
|
|
31
|
-
props.push(currentProps);
|
|
32
|
-
}
|
|
33
|
-
currentProps[built[++i]] = [value];
|
|
34
|
-
} else if (type === PROP_APPEND) {
|
|
35
|
-
currentProps[built[++i]].push(value);
|
|
36
|
-
} else if (type === CHILD_RECURSE) {
|
|
37
|
-
children.push(_treeify(value));
|
|
38
|
-
} else if (type === CHILD_APPEND) {
|
|
39
|
-
children.push(value);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
tag: tag,
|
|
44
|
-
props: props,
|
|
45
|
-
children: children
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
const {
|
|
49
|
-
children
|
|
50
|
-
} = _treeify(built);
|
|
51
|
-
return children.length > 1 ? children : children[0];
|
|
52
|
-
};
|
|
53
|
-
const build = function (statics) {
|
|
54
|
-
let mode = MODE_TEXT;
|
|
55
|
-
let buffer = '';
|
|
56
|
-
let quote = '';
|
|
57
|
-
let current = [0];
|
|
58
|
-
let char, propName;
|
|
59
|
-
const commit = function (field) {
|
|
60
|
-
if (mode === MODE_TEXT && (field || (buffer = buffer.replace(/^\s*\n\s*|\s*\n\s*$/g, '')))) {
|
|
61
|
-
current.push(CHILD_APPEND, field, buffer);
|
|
62
|
-
} else if (mode === MODE_TAGNAME && (field || buffer)) {
|
|
63
|
-
current.push(TAG_SET, field, buffer);
|
|
64
|
-
mode = MODE_WHITESPACE;
|
|
65
|
-
} else if (mode === MODE_WHITESPACE && buffer === '...' && field) {
|
|
66
|
-
current.push(PROPS_ASSIGN, field, 0);
|
|
67
|
-
} else if (mode === MODE_WHITESPACE && buffer && !field) {
|
|
68
|
-
current.push(PROP_SET, 0, true, buffer);
|
|
69
|
-
} else if (mode >= MODE_PROP_SET) {
|
|
70
|
-
if (buffer || !field && mode === MODE_PROP_SET) {
|
|
71
|
-
current.push(mode, 0, buffer, propName);
|
|
72
|
-
mode = MODE_PROP_APPEND;
|
|
73
|
-
}
|
|
74
|
-
if (field) {
|
|
75
|
-
current.push(mode, field, 0, propName);
|
|
76
|
-
mode = MODE_PROP_APPEND;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
buffer = '';
|
|
80
|
-
};
|
|
81
|
-
for (let i = 0; i < statics.length; i++) {
|
|
82
|
-
if (i) {
|
|
83
|
-
if (mode === MODE_TEXT) {
|
|
84
|
-
commit();
|
|
85
|
-
}
|
|
86
|
-
commit(i);
|
|
87
|
-
}
|
|
88
|
-
for (let j = 0; j < statics[i].length; j++) {
|
|
89
|
-
char = statics[i][j];
|
|
90
|
-
if (mode === MODE_TEXT) {
|
|
91
|
-
if (char === '<') {
|
|
92
|
-
commit();
|
|
93
|
-
current = [current];
|
|
94
|
-
mode = MODE_TAGNAME;
|
|
95
|
-
} else {
|
|
96
|
-
buffer += char;
|
|
97
|
-
}
|
|
98
|
-
} else if (mode === MODE_COMMENT) {
|
|
99
|
-
if (buffer === '--' && char === '>') {
|
|
100
|
-
mode = MODE_TEXT;
|
|
101
|
-
buffer = '';
|
|
102
|
-
} else {
|
|
103
|
-
buffer = char + buffer[0];
|
|
104
|
-
}
|
|
105
|
-
} else if (quote) {
|
|
106
|
-
if (char === quote) {
|
|
107
|
-
quote = '';
|
|
108
|
-
} else {
|
|
109
|
-
buffer += char;
|
|
110
|
-
}
|
|
111
|
-
} else if (char === '"' || char === "'") {
|
|
112
|
-
quote = char;
|
|
113
|
-
} else if (char === '>') {
|
|
114
|
-
commit();
|
|
115
|
-
mode = MODE_TEXT;
|
|
116
|
-
} else if (!mode) ; else if (char === '=') {
|
|
117
|
-
mode = MODE_PROP_SET;
|
|
118
|
-
propName = buffer;
|
|
119
|
-
buffer = '';
|
|
120
|
-
} else if (char === '/' && (mode < MODE_PROP_SET || statics[i][j + 1] === '>')) {
|
|
121
|
-
commit();
|
|
122
|
-
if (mode === MODE_TAGNAME) {
|
|
123
|
-
current = current[0];
|
|
124
|
-
}
|
|
125
|
-
mode = current;
|
|
126
|
-
(current = current[0]).push(CHILD_RECURSE, 0, mode);
|
|
127
|
-
mode = MODE_SLASH;
|
|
128
|
-
} else if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
|
|
129
|
-
// <a disabled>
|
|
130
|
-
commit();
|
|
131
|
-
mode = MODE_WHITESPACE;
|
|
132
|
-
} else {
|
|
133
|
-
buffer += char;
|
|
134
|
-
}
|
|
135
|
-
if (mode === MODE_TAGNAME && buffer === '!--') {
|
|
136
|
-
mode = MODE_COMMENT;
|
|
137
|
-
current = current[0];
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
commit();
|
|
142
|
-
return current;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @param {Babel} babel
|
|
147
|
-
* @param {object} options
|
|
148
|
-
* @param {string} [options.tag=html] The tagged template "tag" function name to process.
|
|
149
|
-
*/
|
|
150
|
-
|
|
151
|
-
function mettleBabelPlugin({
|
|
152
|
-
types: t
|
|
153
|
-
}, options = {}) {
|
|
154
|
-
function patternStringToRegExp(str) {
|
|
155
|
-
const parts = str.split('/').slice(1);
|
|
156
|
-
const end = parts.pop() || '';
|
|
157
|
-
return new RegExp(parts.join('/'), end);
|
|
158
|
-
}
|
|
159
|
-
function propertyName(key) {
|
|
160
|
-
if (t.isValidIdentifier(key)) {
|
|
161
|
-
return t.identifier(key);
|
|
162
|
-
}
|
|
163
|
-
return t.stringLiteral(key);
|
|
164
|
-
}
|
|
165
|
-
function objectProperties(obj) {
|
|
166
|
-
return Object.keys(obj).map(function (key) {
|
|
167
|
-
const values = obj[key].map(function (valueOrNode) {
|
|
168
|
-
return t.isNode(valueOrNode) ? valueOrNode : t.valueToNode(valueOrNode);
|
|
169
|
-
});
|
|
170
|
-
let node = values[0];
|
|
171
|
-
if (values.length > 1 && !t.isStringLiteral(node) && !t.isStringLiteral(values[1])) {
|
|
172
|
-
node = t.binaryExpression('+', t.stringLiteral(''), node);
|
|
173
|
-
}
|
|
174
|
-
values.slice(1).forEach(function (value) {
|
|
175
|
-
node = t.binaryExpression('+', node, value);
|
|
176
|
-
});
|
|
177
|
-
return t.objectProperty(propertyName(key), node);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
function stringValue(str) {
|
|
181
|
-
return t.stringLiteral(str);
|
|
182
|
-
}
|
|
183
|
-
function createVNode(tag, props, children) {
|
|
184
|
-
if (children.elements.length === 1) {
|
|
185
|
-
children = children.elements[0];
|
|
186
|
-
} else if (children.elements.length === 0) {
|
|
187
|
-
children = t.nullLiteral();
|
|
188
|
-
}
|
|
189
|
-
let key = null;
|
|
190
|
-
if (props && props.properties && Array.isArray(props.properties)) {
|
|
191
|
-
props.properties.forEach(item => {
|
|
192
|
-
if (item.key.type === 'StringLiteral' && item.key.value === 'key') {
|
|
193
|
-
key = item.value;
|
|
194
|
-
} else if (item.key.type === 'Identifier' && item.key.name === 'key') {
|
|
195
|
-
key = item.value;
|
|
196
|
-
} else {
|
|
197
|
-
key = t.nullLiteral();
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
} else {
|
|
201
|
-
key = t.nullLiteral();
|
|
202
|
-
}
|
|
203
|
-
return t.objectExpression([false, t.objectProperty(propertyName('tag'), tag), t.objectProperty(propertyName('props'), props), t.objectProperty(propertyName('children'), children), t.objectProperty(propertyName('key'), key), t.objectProperty(propertyName('el'), t.nullLiteral()), false].filter(Boolean));
|
|
204
|
-
}
|
|
205
|
-
function spreadNode(args, state) {
|
|
206
|
-
if (args.length === 0) {
|
|
207
|
-
return t.nullLiteral();
|
|
208
|
-
}
|
|
209
|
-
if (args.length > 0 && t.isNode(args[0])) {
|
|
210
|
-
args.unshift({});
|
|
211
|
-
} // 'Object.assign(x)', can be collapsed to 'x'.
|
|
212
|
-
|
|
213
|
-
if (args.length === 1) {
|
|
214
|
-
return propsNode(args[0]);
|
|
215
|
-
} // 'Object.assign({}, x)', can be collapsed to 'x'.
|
|
216
|
-
|
|
217
|
-
if (args.length === 2 && !t.isNode(args[0]) && Object.keys(args[0]).length === 0) {
|
|
218
|
-
return propsNode(args[1]);
|
|
219
|
-
}
|
|
220
|
-
const helper = state.addHelper('extends');
|
|
221
|
-
return t.callExpression(helper, args.map(propsNode));
|
|
222
|
-
}
|
|
223
|
-
function propsNode(props) {
|
|
224
|
-
return t.isNode(props) ? props : t.objectExpression(objectProperties(props));
|
|
225
|
-
}
|
|
226
|
-
function transform(node, state) {
|
|
227
|
-
if (t.isNode(node)) {
|
|
228
|
-
return node;
|
|
229
|
-
}
|
|
230
|
-
if (typeof node === 'string') {
|
|
231
|
-
return stringValue(node);
|
|
232
|
-
}
|
|
233
|
-
if (typeof node === 'undefined') {
|
|
234
|
-
return t.identifier('undefined');
|
|
235
|
-
}
|
|
236
|
-
const {
|
|
237
|
-
tag,
|
|
238
|
-
props,
|
|
239
|
-
children
|
|
240
|
-
} = node;
|
|
241
|
-
const newTag = typeof tag === 'string' ? t.stringLiteral(tag) : tag;
|
|
242
|
-
const newProps = spreadNode(props, state);
|
|
243
|
-
const newChildren = t.arrayExpression(children.map(child => transform(child, state)));
|
|
244
|
-
return createVNode(newTag, newProps, newChildren);
|
|
245
|
-
}
|
|
246
|
-
const tagName = options.tag || 'html';
|
|
247
|
-
return {
|
|
248
|
-
name: 'mettle',
|
|
249
|
-
visitor: {
|
|
250
|
-
TaggedTemplateExpression(path, state) {
|
|
251
|
-
const tag = path.node.tag.name;
|
|
252
|
-
if (tagName[0] === '/' ? patternStringToRegExp(tagName).test(tag) : tag === tagName) {
|
|
253
|
-
const statics = path.node.quasi.quasis.map(e => e.value.raw);
|
|
254
|
-
const expr = path.node.quasi.expressions;
|
|
255
|
-
const tree = treeify(build(statics), expr);
|
|
256
|
-
const node = !Array.isArray(tree) ? transform(tree, state) : t.arrayExpression(tree.map(root => transform(root, state)));
|
|
257
|
-
path.replaceWith(node);
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
CallExpression(path, state) {
|
|
261
|
-
const callee = path.node.callee;
|
|
262
|
-
const args = path.node.arguments;
|
|
263
|
-
const argsArr = Array.from(args);
|
|
264
|
-
// The parameter is a template string
|
|
265
|
-
if (callee.name === 'tem_h') {
|
|
266
|
-
const statics = argsArr[0].quasis.map(e => e.value.raw);
|
|
267
|
-
const expr = argsArr[0].expressions;
|
|
268
|
-
const tree = treeify(build(statics), expr);
|
|
269
|
-
const node = !Array.isArray(tree) ? transform(tree, state) : t.arrayExpression(tree.map(root => transform(root, state)));
|
|
270
|
-
path.replaceWith(node);
|
|
271
|
-
}
|
|
272
|
-
// The parameter is a regular string
|
|
273
|
-
else if (callee.name === 'str_h') {
|
|
274
|
-
const statics = argsArr[0].extra.rawValue;
|
|
275
|
-
const tree = treeify(build([statics]), []);
|
|
276
|
-
const node = !Array.isArray(tree) ? transform(tree, state) : t.arrayExpression(tree.map(root => transform(root, state)));
|
|
277
|
-
path.replaceWith(node);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
export { mettleBabelPlugin as default };
|