babel-plugin-wallace 0.0.1 → 0.0.2
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/README.md +3 -0
- package/lib/_config/directives.js +356 -0
- package/lib/_config/index.js +2 -0
- package/lib/_config/loader.js +43 -0
- package/lib/_config/parse_directives.js +63 -0
- package/lib/config.js +263 -0
- package/lib/convert.js +27 -0
- package/lib/definitions/constants.js +73 -0
- package/lib/definitions/node_data.js +183 -0
- package/lib/definitions/watcher.js +26 -0
- package/lib/generate/code_generator.js +333 -0
- package/lib/generate/statement_builders.js +130 -0
- package/lib/help-system/browser-code.js +50 -0
- package/lib/help-system/entry.js +92 -0
- package/lib/help-system/error-display.js +20 -0
- package/lib/help-system/styles.css +25 -0
- package/lib/import-checker.js +35 -0
- package/lib/index.js +39 -5
- package/lib/jsx/component_dom.js +40 -0
- package/lib/jsx/contexts.js +121 -0
- package/lib/jsx/extract.js +214 -0
- package/lib/jsx/parse.js +98 -0
- package/lib/parse/component_templates.js +44 -0
- package/lib/parse/inline_directives.js +318 -0
- package/lib/parse/parse_node.js +73 -0
- package/lib/polyfills.js +10 -0
- package/lib/utils/babel.js +100 -0
- package/lib/utils/dom.js +174 -0
- package/lib/utils/misc.js +152 -0
- package/lib_old/handlers.js +52 -0
- package/lib_old/index.js +145 -0
- package/package.json +3 -3
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The object which holds the directive definitions.
|
|
3
|
+
*
|
|
4
|
+
* A directive definition's handler's "this" is a NodeData instance.
|
|
5
|
+
*/
|
|
6
|
+
const {RequestsHelp, alwaysUpdate, neverUpdate} = require('../definitions/constants')
|
|
7
|
+
const componentRefVariable = 'c'; // The variable name by which the component will be known.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const old = {
|
|
11
|
+
// What is this for?
|
|
12
|
+
"bind": {
|
|
13
|
+
params: 'watch, event?',
|
|
14
|
+
handle: function(watch, event='change') {
|
|
15
|
+
this.addWatch(watch, undefined, 'value')
|
|
16
|
+
this.addEventListener(event, `${watch} = w.getValue()`)
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"checked": {
|
|
20
|
+
params: 'watch, converter?',
|
|
21
|
+
handle: function(watch, converter) {
|
|
22
|
+
this.addWatch(watch, converter, 'checked')
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"css": {
|
|
26
|
+
params: 'watch, converter?',
|
|
27
|
+
handle: function(watch, converter) {
|
|
28
|
+
this.addWatch(watch, converter, 'css')
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"css-f": {
|
|
32
|
+
params: 'value',
|
|
33
|
+
handle: function(value) {
|
|
34
|
+
this.addWatch(neverUpdate, value, 'css')
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
// "el": {
|
|
38
|
+
// handle: function(arg) {
|
|
39
|
+
// this.saveAs = arg
|
|
40
|
+
// }
|
|
41
|
+
// },
|
|
42
|
+
// "hide": {
|
|
43
|
+
// params: 'watch',
|
|
44
|
+
// handle: function(watch) {
|
|
45
|
+
// this.shieldQuery = watch
|
|
46
|
+
// }
|
|
47
|
+
// },
|
|
48
|
+
"helper": {
|
|
49
|
+
handle: function(watch, converter) {
|
|
50
|
+
throw new RequestsHelp(helpTopic)
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"inner": {
|
|
54
|
+
params: 'watch, converter',
|
|
55
|
+
handle: function(watch, converter) {
|
|
56
|
+
this.addWatch(watch, converter, 'inner')
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"items": {
|
|
60
|
+
params: 'watch, converter?',
|
|
61
|
+
handle: function(watch, converter) {
|
|
62
|
+
this.addWatch(watch, converter, 'items', componentRefVariable)
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
// "on": {
|
|
66
|
+
// params: 'event, callbackStr',
|
|
67
|
+
// handle: function(event, callbackStr) {
|
|
68
|
+
// this.addEventListener(event, callbackStr)
|
|
69
|
+
// }
|
|
70
|
+
// },
|
|
71
|
+
// "pool": {
|
|
72
|
+
// params: 'poolInstance',
|
|
73
|
+
// handle: function(poolInstance) {
|
|
74
|
+
// this.chainedCalls.push(`pool(${poolInstance})`)
|
|
75
|
+
// }
|
|
76
|
+
// },
|
|
77
|
+
// "props": {
|
|
78
|
+
// params: 'args',
|
|
79
|
+
// handle: function(args) {
|
|
80
|
+
// this.props = this.expandProps(args)
|
|
81
|
+
// }
|
|
82
|
+
// },
|
|
83
|
+
"replace": {
|
|
84
|
+
params: 'componentCls, props?',
|
|
85
|
+
handle: function(componentCls, props) {
|
|
86
|
+
this.replaceWith = componentCls
|
|
87
|
+
if (props) {
|
|
88
|
+
this.props = this.expandProps(props)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
// "show": {
|
|
93
|
+
// params: 'watch',
|
|
94
|
+
// handle: function(watch) {
|
|
95
|
+
// this.shieldQuery = watch
|
|
96
|
+
// this.reverseShield = 1
|
|
97
|
+
// }
|
|
98
|
+
// },
|
|
99
|
+
"stub": {
|
|
100
|
+
params: 'stubName',
|
|
101
|
+
handle: function(stubName) {
|
|
102
|
+
this.stubName = stubName
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"swap": {
|
|
106
|
+
params: 'watch, mappings, fallback?',
|
|
107
|
+
handle: function(watch, mappings, fallback) {
|
|
108
|
+
let args = this.expandDots(mappings)
|
|
109
|
+
if (fallback) {
|
|
110
|
+
args += ', ' + this.expandDots(fallback)
|
|
111
|
+
}
|
|
112
|
+
this.chainedCalls.push(`pool(component.__ic(${args}))`)
|
|
113
|
+
this.addWatch(watch, undefined, 'swap', componentRefVariable)
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
// Only for repeat items
|
|
117
|
+
"use": {
|
|
118
|
+
params: 'componentDef, key?',
|
|
119
|
+
handle: function(componentDef, key) {
|
|
120
|
+
this.chainedCalls.push(`pool(${this.buildPoolInit(componentDef, key)})`)
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"value": {
|
|
124
|
+
params: 'watch, converter?',
|
|
125
|
+
handle: function(watch, converter) {
|
|
126
|
+
this.addWatch(watch, converter, 'value')
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"watch": {
|
|
130
|
+
params: 'watch, converter, wrapperMethod?',
|
|
131
|
+
handle: function(watch, converter, wrapperMethod) {
|
|
132
|
+
this.addWatch(watch, converter, wrapperMethod)
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
// "wrapper": {
|
|
136
|
+
// params: 'cls, args?',
|
|
137
|
+
// handle: function(cls, args) {
|
|
138
|
+
// this.customWrapperClass = cls
|
|
139
|
+
// this.customWrapperArgs = args
|
|
140
|
+
// }
|
|
141
|
+
// }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
const callData = {
|
|
146
|
+
value: "str", // if type str
|
|
147
|
+
args: "str", // if type expr
|
|
148
|
+
qualifier: "str|undefined", // foo:qualifier
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
const schema = {
|
|
153
|
+
help: "...",
|
|
154
|
+
allowNull: false,
|
|
155
|
+
allowQualifier: false,
|
|
156
|
+
requireQualifier: false,
|
|
157
|
+
requireNull: false,
|
|
158
|
+
handle: "function(nodeData, callData)",
|
|
159
|
+
args: "array", // only if type "expr"
|
|
160
|
+
argSets: "array", // in case it allows multiple args
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Do not create directive which allows or requires null which has the same name as a
|
|
165
|
+
* normal attribute.
|
|
166
|
+
*/
|
|
167
|
+
const directives = {
|
|
168
|
+
att: {
|
|
169
|
+
help: `
|
|
170
|
+
Sets an HTML attribute on the element:
|
|
171
|
+
|
|
172
|
+
/h <div _att:hidden="x > 3"></div>
|
|
173
|
+
`,
|
|
174
|
+
requireQualifier: true,
|
|
175
|
+
handle: function(nodeData, attInfo) {
|
|
176
|
+
nodeData.addWatch(attInfo.args[0], undefined, `@${attInfo.qualifier}`)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
},
|
|
180
|
+
call: {
|
|
181
|
+
help: `
|
|
182
|
+
Watch a value and call a wrapper method if it changes.
|
|
183
|
+
|
|
184
|
+
/h <div _call:method={watch, tranform}></div>
|
|
185
|
+
|
|
186
|
+
Variables for watch: c, p
|
|
187
|
+
Variables for callback: c, p, n, o, w
|
|
188
|
+
`,
|
|
189
|
+
requireQualifier: true,
|
|
190
|
+
handle: function(nodeData, attInfo) {
|
|
191
|
+
nodeData.addWatch(attInfo.args[0], attInfo.args[1], attInfo.qualifier)
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
checked: {
|
|
195
|
+
help: `
|
|
196
|
+
Sets the "checked" status of the element:
|
|
197
|
+
|
|
198
|
+
/h <input _checked={c.active} type="checkbox"/>
|
|
199
|
+
`,
|
|
200
|
+
handle: function(nodeData, attInfo) {
|
|
201
|
+
nodeData.addWatch(attInfo.args[0], undefined, 'checked')
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
// disabled: {
|
|
205
|
+
// help: `
|
|
206
|
+
// Sets the "disabled" status of the element:
|
|
207
|
+
|
|
208
|
+
// /h <button _disabled={!c.active}>...</button>
|
|
209
|
+
// `,
|
|
210
|
+
// allowedTypes: "expr",
|
|
211
|
+
// handle: function(nodeData, attInfo) {
|
|
212
|
+
// nodeData.addWatch(attInfo.args[0], undefined, 'disabled')
|
|
213
|
+
// }
|
|
214
|
+
// },
|
|
215
|
+
el: {
|
|
216
|
+
help: `
|
|
217
|
+
Gives the wrapper for this element a name so it can be accessed later:
|
|
218
|
+
|
|
219
|
+
/h <div _el:user></div>
|
|
220
|
+
|
|
221
|
+
/j c.el.user.text("Wallace")
|
|
222
|
+
`,
|
|
223
|
+
allowNull: true,
|
|
224
|
+
requireQualifier: true,
|
|
225
|
+
handle: function(nodeData, attInfo) {
|
|
226
|
+
nodeData.saveAs = attInfo.qualifier
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
foreach: {
|
|
230
|
+
help: `
|
|
231
|
+
Repeats a nested component:
|
|
232
|
+
|
|
233
|
+
/h <div>
|
|
234
|
+
/h <Child _for={c.items|id} />
|
|
235
|
+
/h </div>
|
|
236
|
+
|
|
237
|
+
`,
|
|
238
|
+
handle: function(nodeData, attInfo) {
|
|
239
|
+
const parent = nodeData.parentNodeData
|
|
240
|
+
if (parent === undefined) {
|
|
241
|
+
// TODO: throw better error, and assert parent has no other chldren.
|
|
242
|
+
throw Error("For must be used under a parent.")
|
|
243
|
+
}
|
|
244
|
+
const componentDef = nodeData.nestedClass
|
|
245
|
+
const data = attInfo.args[0]
|
|
246
|
+
const key = attInfo.args[1]
|
|
247
|
+
parent.chainedCalls.push(`pool(${parent.buildPoolInit(componentDef, key)})`)
|
|
248
|
+
parent.addWatch(alwaysUpdate, data, 'items', componentRefVariable)
|
|
249
|
+
nodeData.isRepeat = true
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
hidden: {
|
|
253
|
+
help: `
|
|
254
|
+
Hides an element:
|
|
255
|
+
|
|
256
|
+
/h <div hidden={x > 10}></div>
|
|
257
|
+
|
|
258
|
+
Available args are: c, p
|
|
259
|
+
`,
|
|
260
|
+
handle: function(nodeData, attInfo) {
|
|
261
|
+
nodeData.shieldQuery = attInfo.args[0]
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
on: {
|
|
265
|
+
help: `
|
|
266
|
+
Creates an event handler:
|
|
267
|
+
|
|
268
|
+
/h <div on:click={alert('hello')}></div>
|
|
269
|
+
|
|
270
|
+
Available args are: w, e
|
|
271
|
+
`,
|
|
272
|
+
requireQualifier: true,
|
|
273
|
+
handle: function(nodeData, attInfo) {
|
|
274
|
+
nodeData.addEventListener(attInfo.qualifier, attInfo.args[0])
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
// TODO: change this because we may use a special wrapper?
|
|
279
|
+
pool: {
|
|
280
|
+
help: `
|
|
281
|
+
Specify a pool object for repeat items:
|
|
282
|
+
|
|
283
|
+
/h <div pool={poolObject}></div>
|
|
284
|
+
|
|
285
|
+
`,
|
|
286
|
+
handle: function(nodeData, attInfo) {
|
|
287
|
+
nodeData.chainedCalls.push(`pool(${attInfo.args[0]})`)
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
props: {
|
|
291
|
+
help: `
|
|
292
|
+
Specify props for a nested component:
|
|
293
|
+
|
|
294
|
+
/h <NestedComponent props={{foo: 'bar'}} />
|
|
295
|
+
|
|
296
|
+
`,
|
|
297
|
+
handle: function(nodeData, attInfo) {
|
|
298
|
+
nodeData.props = nodeData.expandProps(attInfo.args[0])
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
show: {
|
|
302
|
+
help: `
|
|
303
|
+
Shows an element:
|
|
304
|
+
|
|
305
|
+
/h <div show={x > 10}></div>
|
|
306
|
+
|
|
307
|
+
Variables are: c, p
|
|
308
|
+
`,
|
|
309
|
+
handle: function(nodeData, attInfo) {
|
|
310
|
+
nodeData.shieldQuery = attInfo.args[0]
|
|
311
|
+
nodeData.reverseShield = 1
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
style: {
|
|
315
|
+
help: `
|
|
316
|
+
Sets the style directive:
|
|
317
|
+
|
|
318
|
+
/h <div style:color={p.color}></div>
|
|
319
|
+
|
|
320
|
+
Variables are: c, p
|
|
321
|
+
`,
|
|
322
|
+
requireQualifier: true,
|
|
323
|
+
handle: function(nodeData, attInfo) {
|
|
324
|
+
nodeData.addWatch(attInfo.args[0], undefined, 'style', `'${attInfo.qualifier}'`)
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
watch: {
|
|
328
|
+
help: `
|
|
329
|
+
Watch a value and call
|
|
330
|
+
|
|
331
|
+
/h <div watch={watch, callback}></div>
|
|
332
|
+
|
|
333
|
+
Variables for watch: c, p
|
|
334
|
+
Variables for callback: c, p, n, o, w
|
|
335
|
+
`,
|
|
336
|
+
handle: function(nodeData, attInfo) {
|
|
337
|
+
nodeData.addWatch(...attInfo.args)
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
wrapper: {
|
|
341
|
+
help: `
|
|
342
|
+
Specify an alternative wrapper class:
|
|
343
|
+
|
|
344
|
+
/h <div wrapper={MyCustomWrapper}></div>
|
|
345
|
+
|
|
346
|
+
Available args are: c, p
|
|
347
|
+
`,
|
|
348
|
+
handle: function(nodeData, attInfo) {
|
|
349
|
+
nodeData.customWrapperClass = attInfo.args[0]
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Do not import directly, only through index so we get custom directives too.
|
|
355
|
+
module.exports = {directives}
|
|
356
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const {directives} = require('./directives');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const config = {
|
|
7
|
+
options: {
|
|
8
|
+
inlineDelimiters: ['{', '}']
|
|
9
|
+
},
|
|
10
|
+
aliases: {
|
|
11
|
+
'': 'watch'
|
|
12
|
+
},
|
|
13
|
+
directives: directives
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Use custom config file if there is one.
|
|
17
|
+
const customConfigFile = path.join(process.cwd(), 'wallace.config.js')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if (fs.existsSync(customConfigFile)) {
|
|
21
|
+
|
|
22
|
+
var customConfig = require(customConfigFile)
|
|
23
|
+
if (customConfig.directives) {
|
|
24
|
+
Object.assign(config.directives, customConfig.directives)
|
|
25
|
+
}
|
|
26
|
+
// TODO: check options are valid.
|
|
27
|
+
if (customConfig.options) {
|
|
28
|
+
Object.assign(config.options, customConfig.options)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const key of Object.keys(config.directives)) {
|
|
33
|
+
if (key.toLowerCase().startsWith("on") && key !== "on") {
|
|
34
|
+
throw new Error(`Directive "${key}" may not start with 'on' as this is reserved for event handlers.`)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// const directives = config.directives
|
|
39
|
+
// for (const [key, value] of Object.entries(config.aliases)) {
|
|
40
|
+
// directives[':' + key] = directives[':' + value]
|
|
41
|
+
// }
|
|
42
|
+
|
|
43
|
+
module.exports = {config}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module deals with parsing the directives in the config file,
|
|
3
|
+
* and helping them parse arguments.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const {isFunc, isUnd, splitTrim} = require('../utils/misc')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Used internally to
|
|
10
|
+
*
|
|
11
|
+
* @param {string} directiveName
|
|
12
|
+
* @param {*} directive
|
|
13
|
+
* @param {*} attVal
|
|
14
|
+
*/
|
|
15
|
+
const processDirective = (nodeData, directiveName, directive, attVal) => {
|
|
16
|
+
if (!isFunc(directive.handle)) {
|
|
17
|
+
throw new Error('handle must be a function')
|
|
18
|
+
}
|
|
19
|
+
let args = attVal
|
|
20
|
+
if (directive.hasOwnProperty('params')) {
|
|
21
|
+
let params = splitTrim(directive.params, ',')
|
|
22
|
+
args = parseDirectiveArguments(params, attVal)
|
|
23
|
+
directive.handle.apply(nodeData, args)
|
|
24
|
+
} else {
|
|
25
|
+
directive.handle.apply(nodeData, [args])
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Return array of args based on definitions
|
|
31
|
+
*
|
|
32
|
+
* @param {Array} params The parameters as strings
|
|
33
|
+
* @param {String} attVal The raw attribute value.
|
|
34
|
+
*/
|
|
35
|
+
const parseDirectiveArguments = (params, attVal) => {
|
|
36
|
+
const args = []
|
|
37
|
+
const chunks = splitTrim(attVal, '|')
|
|
38
|
+
for (let i=0, il=params.length; i<il; i++) {
|
|
39
|
+
let param = params[i]
|
|
40
|
+
let raw = chunks[i]
|
|
41
|
+
let value = parseArgValue(param, raw, i)
|
|
42
|
+
args.push(value)
|
|
43
|
+
}
|
|
44
|
+
return args
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const parseArgValue = (param, raw, i) => {
|
|
48
|
+
if ((!param.endsWith('?')) && (isUnd(raw))) {
|
|
49
|
+
throw new Error(`Argument ${param} is required`)
|
|
50
|
+
}
|
|
51
|
+
return raw
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const extractDocumentation = (name, directive) => {
|
|
55
|
+
return {
|
|
56
|
+
name: name,
|
|
57
|
+
params: directive.params
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
module.exports = {processDirective, extractDocumentation}
|