boxwood 0.60.2 → 0.61.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/README.md +0 -358
- package/index.js +402 -4
- package/package.json +12 -37
- package/src/Bundler.js +0 -13
- package/src/Cache.js +0 -35
- package/src/Compiler.js +0 -28
- package/src/Importer.js +0 -142
- package/src/Optimizer.js +0 -96
- package/src/Scope.js +0 -20
- package/src/Statistics.js +0 -58
- package/src/bundlers/esbuild/index.js +0 -55
- package/src/bundlers/esbuild/plugins/css.js +0 -40
- package/src/bundlers/esbuild/plugins/html.js +0 -27
- package/src/bundlers/esbuild/plugins/image.js +0 -38
- package/src/bundlers/esbuild/plugins/resolve.js +0 -11
- package/src/bundlers/esbuild/plugins/yaml.js +0 -38
- package/src/bundlers/esbuild/utilities/asset.js +0 -19
- package/src/bundlers/rollup.js +0 -38
- package/src/compile.js +0 -6
- package/src/compilers/any/Compiler.js +0 -16
- package/src/compilers/compile.js +0 -17
- package/src/compilers/html/Analyzer.js +0 -24
- package/src/compilers/html/Compiler.js +0 -47
- package/src/compilers/html/Generator.js +0 -19
- package/src/compilers/html/Parser.js +0 -11
- package/src/compilers/html/Preprocessor.js +0 -130
- package/src/compilers/html/Renderer.js +0 -167
- package/src/compilers/html/Transpiler.js +0 -76
- package/src/compilers/js/Bundler.js +0 -84
- package/src/compilers/js/Compiler/index.js +0 -27
- package/src/conditions/isEqual.js +0 -5
- package/src/lexers/html.js +0 -49
- package/src/lexers/internal.js +0 -49
- package/src/linters/html/bracket.js +0 -36
- package/src/linters/html/component.js +0 -43
- package/src/linters/html/import.js +0 -35
- package/src/linters/html/index.js +0 -19
- package/src/linters/html/tag.js +0 -36
- package/src/optimizers/html.js +0 -15
- package/src/plugins/BoxModelPlugin/index.js +0 -109
- package/src/plugins/CurlyStylesPlugin/index.js +0 -39
- package/src/plugins/DataPlugin/index.js +0 -53
- package/src/plugins/InlinePlugin/css.js +0 -131
- package/src/plugins/InlinePlugin/index.js +0 -39
- package/src/plugins/InternationalizationPlugin/index.js +0 -111
- package/src/plugins/Plugin.js +0 -22
- package/src/plugins/ScopedStylesPlugin/css.js +0 -56
- package/src/plugins/ScopedStylesPlugin/html.js +0 -112
- package/src/plugins/ScopedStylesPlugin/index.js +0 -48
- package/src/plugins/SwappedStylesPlugin/index.js +0 -20
- package/src/render.js +0 -48
- package/src/tags/case.js +0 -28
- package/src/tags/catch.js +0 -17
- package/src/tags/data.js +0 -7
- package/src/tags/default.js +0 -20
- package/src/tags/doctype.js +0 -8
- package/src/tags/else.js +0 -18
- package/src/tags/elseif.js +0 -25
- package/src/tags/elseunless.js +0 -30
- package/src/tags/font.js +0 -37
- package/src/tags/for.js +0 -90
- package/src/tags/foreach.js +0 -80
- package/src/tags/if.js +0 -19
- package/src/tags/img.js +0 -25
- package/src/tags/index.js +0 -53
- package/src/tags/link.js +0 -14
- package/src/tags/script/index.js +0 -83
- package/src/tags/script/scoped.js +0 -26
- package/src/tags/slot.js +0 -9
- package/src/tags/style.js +0 -9
- package/src/tags/switch.js +0 -13
- package/src/tags/template.js +0 -22
- package/src/tags/translate.js +0 -22
- package/src/tags/translation.js +0 -38
- package/src/tags/try.js +0 -17
- package/src/tags/unless.js +0 -24
- package/src/tags/var.js +0 -32
- package/src/transpilers/css/index.js +0 -34
- package/src/transpilers/html/expression.js +0 -101
- package/src/transpilers/html/index.js +0 -189
- package/src/transpilers/html/node.js +0 -46
- package/src/transpilers/html/tags/any.js +0 -53
- package/src/transpilers/html/tags/comment.js +0 -7
- package/src/transpilers/html/tags/doctype.js +0 -6
- package/src/transpilers/html/tags/for.js +0 -30
- package/src/transpilers/html/tags/if.js +0 -55
- package/src/transpilers/html/tags/import.js +0 -7
- package/src/transpilers/html/tags/index.js +0 -13
- package/src/transpilers/html/tags/partial.js +0 -17
- package/src/transpilers/html/tags/slot.js +0 -7
- package/src/transpilers/html/tags/text.js +0 -6
- package/src/transpilers/html/tags/try.js +0 -30
- package/src/transpilers/html/tags/unless.js +0 -58
- package/src/transpilers/html/utilities/path.js +0 -9
- package/src/utilities/action.js +0 -208
- package/src/utilities/array.js +0 -80
- package/src/utilities/assets.js +0 -18
- package/src/utilities/ast.js +0 -13
- package/src/utilities/attributes.js +0 -23
- package/src/utilities/collect.js +0 -404
- package/src/utilities/conditions.js +0 -159
- package/src/utilities/convert.js +0 -359
- package/src/utilities/data.js +0 -55
- package/src/utilities/enum.js +0 -103
- package/src/utilities/errors.js +0 -96
- package/src/utilities/factory.js +0 -237
- package/src/utilities/files.js +0 -55
- package/src/utilities/filters.js +0 -140
- package/src/utilities/globals.js +0 -43
- package/src/utilities/html.js +0 -60
- package/src/utilities/inline.js +0 -200
- package/src/utilities/js.js +0 -15
- package/src/utilities/keywords.js +0 -35
- package/src/utilities/log.js +0 -31
- package/src/utilities/node.js +0 -149
- package/src/utilities/object.js +0 -8
- package/src/utilities/optimize.js +0 -268
- package/src/utilities/options.js +0 -99
- package/src/utilities/request.js +0 -13
- package/src/utilities/string.js +0 -144
- package/src/utilities/style.js +0 -15
- package/src/utilities/translations.js +0 -78
- package/src/utilities/url.js +0 -24
- package/src/vdom/browser/app.js +0 -19
- package/src/vdom/browser/diff.js +0 -104
- package/src/vdom/browser/index.js +0 -15
- package/src/vdom/browser/mount.js +0 -10
- package/src/vdom/browser/render.js +0 -66
- package/src/vdom/browser/replace.js +0 -7
- package/src/vdom/node.js +0 -10
- package/src/vdom/nodes.js +0 -116
- package/src/vdom/server/State.js +0 -21
- package/src/vdom/server/boxwood.js +0 -5
- package/src/vdom/server/index.js +0 -19
- package/src/vdom/server/render.js +0 -66
- package/src/vdom/tag.js +0 -33
- package/src/vdom/utilities/classes.js +0 -22
- package/src/vdom/utilities/css.js +0 -17
- package/src/vdom/utilities/escape.js +0 -50
package/index.js
CHANGED
|
@@ -1,9 +1,407 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
1
|
+
const csstree = require('css-tree')
|
|
2
|
+
const toHash = require('string-hash')
|
|
3
|
+
|
|
4
|
+
async function compile(path) {
|
|
5
|
+
const fn = require(path)
|
|
6
|
+
return {
|
|
7
|
+
template() {
|
|
8
|
+
const tree = fn(...arguments)
|
|
9
|
+
const nodes = {}
|
|
10
|
+
const styles = []
|
|
11
|
+
const scripts = []
|
|
12
|
+
const find = (node) => {
|
|
13
|
+
if (node.name === 'head') {
|
|
14
|
+
nodes.head = node
|
|
15
|
+
}
|
|
16
|
+
if (node.name === 'style') {
|
|
17
|
+
styles.push(node.children)
|
|
18
|
+
node.ignore = true
|
|
19
|
+
}
|
|
20
|
+
if (node.name === 'script') {
|
|
21
|
+
scripts.push(node.children)
|
|
22
|
+
node.ignore = true
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(node)) {
|
|
25
|
+
node.forEach(find)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
walk(tree, find)
|
|
29
|
+
if (nodes.head) {
|
|
30
|
+
if (styles.length > 0) {
|
|
31
|
+
nodes.head.children.push({
|
|
32
|
+
name: 'style',
|
|
33
|
+
children: styles.join(''),
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
if (scripts.length > 0) {
|
|
37
|
+
nodes.head.children.push({
|
|
38
|
+
name: 'script',
|
|
39
|
+
children: scripts.join(''),
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return render(tree)
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function walk(tree, callback) {
|
|
49
|
+
callback(tree)
|
|
50
|
+
if (Array.isArray(tree.children)) {
|
|
51
|
+
tree.children.map((node) => walk(node, callback))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const ENTITIES = {
|
|
56
|
+
'&': '&',
|
|
57
|
+
'<': '<',
|
|
58
|
+
'>': '>',
|
|
59
|
+
"'": ''',
|
|
60
|
+
'"': '"',
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const REGEXP = /[&<>'"]/g
|
|
64
|
+
|
|
65
|
+
const escape = (string) => {
|
|
66
|
+
return String.prototype.replace.call(string, REGEXP, function (character) {
|
|
67
|
+
return ENTITIES[character]
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const BOOLEAN_ATTRIBUTES = [
|
|
72
|
+
'async',
|
|
73
|
+
'autofocus',
|
|
74
|
+
'autoplay',
|
|
75
|
+
'border',
|
|
76
|
+
'challenge',
|
|
77
|
+
'checked',
|
|
78
|
+
'compact',
|
|
79
|
+
'contenteditable',
|
|
80
|
+
'controls',
|
|
81
|
+
'default',
|
|
82
|
+
'defer',
|
|
83
|
+
'disabled',
|
|
84
|
+
'formnovalidate',
|
|
85
|
+
'frameborder',
|
|
86
|
+
'hidden',
|
|
87
|
+
'indeterminate',
|
|
88
|
+
'ismap',
|
|
89
|
+
'loop',
|
|
90
|
+
'multiple',
|
|
91
|
+
'muted',
|
|
92
|
+
'nohref',
|
|
93
|
+
'noresize',
|
|
94
|
+
'noshade',
|
|
95
|
+
'novalidate',
|
|
96
|
+
'nowrap',
|
|
97
|
+
'open',
|
|
98
|
+
'readonly',
|
|
99
|
+
'required',
|
|
100
|
+
'reversed',
|
|
101
|
+
'scoped',
|
|
102
|
+
'scrolling',
|
|
103
|
+
'seamless',
|
|
104
|
+
'selected',
|
|
105
|
+
'sortable',
|
|
106
|
+
'spellcheck',
|
|
107
|
+
'translate',
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
const attributes = (options) => {
|
|
111
|
+
const result = []
|
|
112
|
+
for (const key in options) {
|
|
113
|
+
if (BOOLEAN_ATTRIBUTES.includes(key)) {
|
|
114
|
+
result.push(key)
|
|
115
|
+
} else {
|
|
116
|
+
result.push(key + '=' + '"' + options[key] + '"')
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result.join(' ')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const SELF_CLOSING_TAGS = [
|
|
123
|
+
'area',
|
|
124
|
+
'base',
|
|
125
|
+
'br',
|
|
126
|
+
'col',
|
|
127
|
+
'command',
|
|
128
|
+
'embed',
|
|
129
|
+
'hr',
|
|
130
|
+
'img',
|
|
131
|
+
'input',
|
|
132
|
+
'keygen',
|
|
133
|
+
'link',
|
|
134
|
+
'meta',
|
|
135
|
+
'param',
|
|
136
|
+
'source',
|
|
137
|
+
'track',
|
|
138
|
+
'wbr',
|
|
139
|
+
'!DOCTYPE html',
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
const render = (input) => {
|
|
143
|
+
if (input.ignore) {
|
|
144
|
+
return ''
|
|
145
|
+
}
|
|
146
|
+
if (Array.isArray(input)) {
|
|
147
|
+
return input.filter(Boolean).map(render).join('')
|
|
148
|
+
}
|
|
149
|
+
if (typeof input === 'number') {
|
|
150
|
+
return input.toString()
|
|
151
|
+
}
|
|
152
|
+
if (typeof input === 'string') {
|
|
153
|
+
return escape(input)
|
|
154
|
+
}
|
|
155
|
+
if (input.name === 'fragment') {
|
|
156
|
+
return render(input.children)
|
|
157
|
+
}
|
|
158
|
+
if (SELF_CLOSING_TAGS.includes(input.name)) {
|
|
159
|
+
if (input.attributes) {
|
|
160
|
+
return `<${input.name} ` + attributes(input.attributes) + '>'
|
|
161
|
+
}
|
|
162
|
+
return `<${input.name}>`
|
|
163
|
+
}
|
|
164
|
+
if (input.attributes && input.children) {
|
|
165
|
+
return (
|
|
166
|
+
`<${input.name} ` +
|
|
167
|
+
attributes(input.attributes) +
|
|
168
|
+
'>' +
|
|
169
|
+
render(input.children) +
|
|
170
|
+
`</${input.name}>`
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
if (input.attributes) {
|
|
174
|
+
return (
|
|
175
|
+
`<${input.name} ` + attributes(input.attributes) + `></${input.name}>`
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
if (input.children) {
|
|
179
|
+
return `<${input.name}>` + render(input.children) + `</${input.name}>`
|
|
180
|
+
}
|
|
181
|
+
return `<${input.name}></${input.name}>`
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const fragment = (children) => {
|
|
185
|
+
return { name: 'fragment', children }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const tag = (a, b, c) => {
|
|
189
|
+
if (a && b && c) {
|
|
190
|
+
const name = a
|
|
191
|
+
const attributes = b
|
|
192
|
+
const children = c
|
|
193
|
+
return {
|
|
194
|
+
name,
|
|
195
|
+
children,
|
|
196
|
+
attributes,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const name = a
|
|
200
|
+
const children = b
|
|
201
|
+
if (SELF_CLOSING_TAGS.includes(name)) {
|
|
202
|
+
return {
|
|
203
|
+
name,
|
|
204
|
+
attributes: children,
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
name,
|
|
209
|
+
children,
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function css(inputs) {
|
|
214
|
+
let result = ''
|
|
215
|
+
for (let i = 0, ilen = inputs.length; i < ilen; i += 1) {
|
|
216
|
+
const input = inputs[i]
|
|
217
|
+
const value = arguments[i + 1]
|
|
218
|
+
if (value) {
|
|
219
|
+
result += input + value
|
|
220
|
+
} else {
|
|
221
|
+
result += input
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const hash = toHash(result).toString(36).substr(0, 5)
|
|
225
|
+
const tree = csstree.parse(result)
|
|
226
|
+
const classes = {}
|
|
227
|
+
|
|
228
|
+
csstree.walk(tree, (node) => {
|
|
229
|
+
if (node.type === 'ClassSelector') {
|
|
230
|
+
const name = `__${node.name}__${hash}`
|
|
231
|
+
classes[node.name] = name
|
|
232
|
+
node.name = name
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
...classes,
|
|
238
|
+
css: tag('style', csstree.generate(tree)),
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function js(inputs) {
|
|
243
|
+
let result = ''
|
|
244
|
+
for (let i = 0, ilen = inputs.length; i < ilen; i += 1) {
|
|
245
|
+
const input = inputs[i]
|
|
246
|
+
const value = arguments[i + 1]
|
|
247
|
+
if (value) {
|
|
248
|
+
result += input + value
|
|
249
|
+
} else {
|
|
250
|
+
result += input
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
js: tag('script', result),
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const node = (name) => (options, children) => tag(name, options, children)
|
|
259
|
+
const doctype = node('!DOCTYPE html')
|
|
260
|
+
|
|
261
|
+
const nodes = [
|
|
262
|
+
'a',
|
|
263
|
+
'abbr',
|
|
264
|
+
'address',
|
|
265
|
+
'area',
|
|
266
|
+
'article',
|
|
267
|
+
'aside',
|
|
268
|
+
'audio',
|
|
269
|
+
'b',
|
|
270
|
+
'base',
|
|
271
|
+
'bdi',
|
|
272
|
+
'bdo',
|
|
273
|
+
'blockquote',
|
|
274
|
+
'body',
|
|
275
|
+
'br',
|
|
276
|
+
'button',
|
|
277
|
+
'canvas',
|
|
278
|
+
'caption',
|
|
279
|
+
'cite',
|
|
280
|
+
'code',
|
|
281
|
+
'col',
|
|
282
|
+
'colgroup',
|
|
283
|
+
'data',
|
|
284
|
+
'datalist',
|
|
285
|
+
'dd',
|
|
286
|
+
'del',
|
|
287
|
+
'details',
|
|
288
|
+
'dfn',
|
|
289
|
+
'dialog',
|
|
290
|
+
'div',
|
|
291
|
+
'dl',
|
|
292
|
+
'dt',
|
|
293
|
+
'em',
|
|
294
|
+
'embed',
|
|
295
|
+
'fieldset',
|
|
296
|
+
'figcaption',
|
|
297
|
+
'figure',
|
|
298
|
+
'footer',
|
|
299
|
+
'form',
|
|
300
|
+
'h1',
|
|
301
|
+
'h2',
|
|
302
|
+
'h3',
|
|
303
|
+
'h4',
|
|
304
|
+
'h5',
|
|
305
|
+
'h6',
|
|
306
|
+
'head',
|
|
307
|
+
'header',
|
|
308
|
+
'hr',
|
|
309
|
+
'html',
|
|
310
|
+
'i',
|
|
311
|
+
'iframe',
|
|
312
|
+
'img',
|
|
313
|
+
'input',
|
|
314
|
+
'ins',
|
|
315
|
+
'kbd',
|
|
316
|
+
'label',
|
|
317
|
+
'legend',
|
|
318
|
+
'li',
|
|
319
|
+
'link',
|
|
320
|
+
'main',
|
|
321
|
+
'map',
|
|
322
|
+
'mark',
|
|
323
|
+
'meta',
|
|
324
|
+
'meter',
|
|
325
|
+
'nav',
|
|
326
|
+
'noscript',
|
|
327
|
+
'object',
|
|
328
|
+
'ol',
|
|
329
|
+
'optgroup',
|
|
330
|
+
'option',
|
|
331
|
+
'output',
|
|
332
|
+
'p',
|
|
333
|
+
'param',
|
|
334
|
+
'picture',
|
|
335
|
+
'pre',
|
|
336
|
+
'progress',
|
|
337
|
+
'q',
|
|
338
|
+
'rp',
|
|
339
|
+
'rt',
|
|
340
|
+
'ruby',
|
|
341
|
+
's',
|
|
342
|
+
'samp',
|
|
343
|
+
'script',
|
|
344
|
+
'section',
|
|
345
|
+
'select',
|
|
346
|
+
'small',
|
|
347
|
+
'source',
|
|
348
|
+
'span',
|
|
349
|
+
'strong',
|
|
350
|
+
'style',
|
|
351
|
+
'sub',
|
|
352
|
+
'summary',
|
|
353
|
+
'sup',
|
|
354
|
+
'svg',
|
|
355
|
+
'table',
|
|
356
|
+
'tbody',
|
|
357
|
+
'td',
|
|
358
|
+
'template',
|
|
359
|
+
'textarea',
|
|
360
|
+
'tfoot',
|
|
361
|
+
'th',
|
|
362
|
+
'thead',
|
|
363
|
+
'time',
|
|
364
|
+
'title',
|
|
365
|
+
'tr',
|
|
366
|
+
'track',
|
|
367
|
+
'u',
|
|
368
|
+
'ul',
|
|
369
|
+
'var',
|
|
370
|
+
'video',
|
|
371
|
+
'wbr',
|
|
372
|
+
].reduce((result, name) => {
|
|
373
|
+
result[name] = node(name)
|
|
374
|
+
return result
|
|
375
|
+
}, {})
|
|
376
|
+
|
|
377
|
+
function classes() {
|
|
378
|
+
const array = []
|
|
379
|
+
for (let i = 0, ilen = arguments.length; i < ilen; i += 1) {
|
|
380
|
+
const arg = arguments[i]
|
|
381
|
+
if (!arg) {
|
|
382
|
+
continue
|
|
383
|
+
}
|
|
384
|
+
const type = typeof arg
|
|
385
|
+
if (type === 'string') {
|
|
386
|
+
array.push(arg)
|
|
387
|
+
} else if (type === 'object') {
|
|
388
|
+
for (const key in arg) {
|
|
389
|
+
if (arg[key]) {
|
|
390
|
+
array.push(key)
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return array.join(' ')
|
|
396
|
+
}
|
|
4
397
|
|
|
5
398
|
module.exports = {
|
|
6
399
|
compile,
|
|
400
|
+
classes,
|
|
401
|
+
doctype,
|
|
7
402
|
escape,
|
|
8
|
-
|
|
403
|
+
fragment,
|
|
404
|
+
css,
|
|
405
|
+
js,
|
|
406
|
+
...nodes,
|
|
9
407
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "boxwood",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"description": "Compile HTML templates into JS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"test": "ava 'test/spec/**/*.spec.js' 'src/**/*.spec.js' --no-worker-threads",
|
|
7
|
+
"test": "ava '**/*.spec.js'",
|
|
9
8
|
"coverage": "nyc npm test",
|
|
10
|
-
"benchmark": "ava test/benchmark.
|
|
9
|
+
"benchmark": "ava test/benchmark/index.js --verbose",
|
|
11
10
|
"watch": "npm test -- --watch",
|
|
12
|
-
"prepush": "npm
|
|
13
|
-
"typecheck": "tsc --checkJs index.js --noEmit --esModuleInterop --target es5"
|
|
11
|
+
"prepush": "npm test"
|
|
14
12
|
},
|
|
15
13
|
"ava": {
|
|
16
14
|
"files": [
|
|
@@ -46,43 +44,16 @@
|
|
|
46
44
|
"url": "https://github.com/buxlabs/boxwood/issues"
|
|
47
45
|
},
|
|
48
46
|
"homepage": "https://github.com/buxlabs/boxwood#readme",
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"@rollup/plugin-commonjs": "^21.0.1",
|
|
51
|
-
"@rollup/plugin-node-resolve": "^13.1.3",
|
|
52
|
-
"abstract-syntax-tree": "^2.20.5",
|
|
53
|
-
"ansi-colors": "^4.1.1",
|
|
54
|
-
"axios": "^0.25.0",
|
|
55
|
-
"axios-extensions": "3.1.3",
|
|
56
|
-
"css-tree": "^1.1.3",
|
|
57
|
-
"csso": "^5.0.2",
|
|
58
|
-
"esbuild": "^0.14.11",
|
|
59
|
-
"himalaya": "1.1.0",
|
|
60
|
-
"himalaya-walk": "1.0.0",
|
|
61
|
-
"html-lexer": "^0.4.1",
|
|
62
|
-
"html-minifier": "4.0.0",
|
|
63
|
-
"memoizee": "0.4.15",
|
|
64
|
-
"negate-sentence": "0.2.0",
|
|
65
|
-
"path-to-regexp": "6.2.0",
|
|
66
|
-
"pure-conditions": "1.2.1",
|
|
67
|
-
"pure-utilities": "^1.2.4",
|
|
68
|
-
"rollup": "^2.64.0",
|
|
69
|
-
"rollup-plugin-includepaths": "0.2.4",
|
|
70
|
-
"string-hash": "1.1.3",
|
|
71
|
-
"yaml": "^1.10.2"
|
|
72
|
-
},
|
|
73
47
|
"devDependencies": {
|
|
74
|
-
"ava": "^
|
|
48
|
+
"ava": "^5.1.0",
|
|
75
49
|
"benchmark": "2.1.4",
|
|
76
|
-
"
|
|
77
|
-
"express": "^4.17.2",
|
|
50
|
+
"express": "^4.18.2",
|
|
78
51
|
"handlebars": "^4.7.7",
|
|
52
|
+
"jsdom": "^20.0.3",
|
|
79
53
|
"lodash.template": "4.5.0",
|
|
80
54
|
"mustache": "^4.2.0",
|
|
81
55
|
"nyc": "15.1.0",
|
|
82
|
-
"
|
|
83
|
-
"standard": "^16.0.4",
|
|
84
|
-
"typescript": "^4.5.4",
|
|
85
|
-
"underscore": "^1.13.2"
|
|
56
|
+
"underscore": "^1.13.6"
|
|
86
57
|
},
|
|
87
58
|
"standard": {
|
|
88
59
|
"ignore": [
|
|
@@ -90,5 +61,9 @@
|
|
|
90
61
|
"test/spec/**/*",
|
|
91
62
|
"src/**/*.spec.js"
|
|
92
63
|
]
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"css-tree": "^2.3.0",
|
|
67
|
+
"string-hash": "^1.1.3"
|
|
93
68
|
}
|
|
94
69
|
}
|
package/src/Bundler.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const esbuild = require('./bundlers/esbuild')
|
|
4
|
-
const rollup = require('./bundlers/rollup')
|
|
5
|
-
|
|
6
|
-
class Bundler {
|
|
7
|
-
async bundle (source, options = {}) {
|
|
8
|
-
const bundler = options.bundler === 'rollup' ? rollup : esbuild
|
|
9
|
-
return bundler.bundle(source, options)
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = Bundler
|
package/src/Cache.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
// basic cache implementation
|
|
4
|
-
|
|
5
|
-
// ideally the cache should be dependent not only on the key, but also on the options that are passed to the compiler
|
|
6
|
-
// you can get a different output depending on the options
|
|
7
|
-
|
|
8
|
-
// there are other edge cases too:
|
|
9
|
-
// - http calls could fail (might want to retry them?)
|
|
10
|
-
// - errors and/or warnings could be present (could avoid caching in this case)
|
|
11
|
-
// - timeouts?
|
|
12
|
-
|
|
13
|
-
class Cache {
|
|
14
|
-
constructor () {
|
|
15
|
-
this.memory = {}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
set (key, value) {
|
|
19
|
-
this.memory[key] = value
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get (key) {
|
|
23
|
-
return this.memory[key]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
has (key) {
|
|
27
|
-
return !!this.get(key)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
remove (key) {
|
|
31
|
-
delete this.memory[key]
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = Cache
|
package/src/Compiler.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Cache = require('./Cache')
|
|
4
|
-
const { getOptions } = require('./utilities/options')
|
|
5
|
-
const compile = require('./compilers/compile')
|
|
6
|
-
|
|
7
|
-
const cache = new Cache()
|
|
8
|
-
|
|
9
|
-
class Compiler {
|
|
10
|
-
constructor (options) {
|
|
11
|
-
this.options = getOptions(options)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async compile (input) {
|
|
15
|
-
const { options } = this
|
|
16
|
-
if (options.cache === true && cache.has(input)) { return { ...cache.get(input), from: 'cache' } }
|
|
17
|
-
const output = await compile(input, options)
|
|
18
|
-
if (output.dynamic === false) {
|
|
19
|
-
output.html = output.template()
|
|
20
|
-
}
|
|
21
|
-
if (options.cache === true) {
|
|
22
|
-
cache.set(input, output)
|
|
23
|
-
}
|
|
24
|
-
return { ...output, from: 'generator' }
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
module.exports = Compiler
|
package/src/Importer.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { join, dirname } = require('path')
|
|
4
|
-
const { readFile, readFileWithCache, resolveAlias } = require('./utilities/files')
|
|
5
|
-
const { flatten } = require('pure-utilities/collection')
|
|
6
|
-
const Transpiler = require('./compilers/html/Transpiler')
|
|
7
|
-
const { lint } = require('./linters/html')
|
|
8
|
-
const request = require('./utilities/request')
|
|
9
|
-
const { getFullRemoteUrl, isRemotePath } = require('./utilities/url')
|
|
10
|
-
const { mergeAssets } = require('./utilities/assets')
|
|
11
|
-
|
|
12
|
-
const { getComponentNames } = require('./utilities/attributes')
|
|
13
|
-
const { getAssetPaths, getImportNodes } = require('./utilities/node')
|
|
14
|
-
const { parse } = require('./utilities/html')
|
|
15
|
-
const transpiler = new Transpiler()
|
|
16
|
-
|
|
17
|
-
let id = 1
|
|
18
|
-
|
|
19
|
-
function getBase64Data (buffer) {
|
|
20
|
-
return buffer.toString('base64')
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function loadComponent (node, path, isRemote, remoteUrl, options, paths = []) {
|
|
24
|
-
path = resolveAlias(path, options.aliases)
|
|
25
|
-
if (isRemotePath(path) || isRemote) {
|
|
26
|
-
try {
|
|
27
|
-
const url = getFullRemoteUrl(remoteUrl, path)
|
|
28
|
-
const response = await request.get(url, {
|
|
29
|
-
responseType: 'arraybuffer',
|
|
30
|
-
cache: options.cache
|
|
31
|
-
})
|
|
32
|
-
if (response.status === 200) {
|
|
33
|
-
const buffer = Buffer.from(response.data, 'binary') // TODO: parse response to the buffer
|
|
34
|
-
const base64 = getBase64Data(buffer)
|
|
35
|
-
id += 1
|
|
36
|
-
return {
|
|
37
|
-
path,
|
|
38
|
-
source: transpiler.transpile(buffer.toString()),
|
|
39
|
-
buffer,
|
|
40
|
-
base64,
|
|
41
|
-
remote: true,
|
|
42
|
-
url,
|
|
43
|
-
id
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
} catch (exception) {}
|
|
47
|
-
} else {
|
|
48
|
-
const read = options.cache ? readFileWithCache : readFile
|
|
49
|
-
for (const option of paths) {
|
|
50
|
-
try {
|
|
51
|
-
const location = join(option, path)
|
|
52
|
-
options.hooks.onBeforeFile(location)
|
|
53
|
-
const file = {}
|
|
54
|
-
file.path = location
|
|
55
|
-
file.buffer = await read(location)
|
|
56
|
-
file.base64 = getBase64Data(file.buffer)
|
|
57
|
-
// TODO: Read once convert base64
|
|
58
|
-
const source = await read(location, 'utf8')
|
|
59
|
-
file.source = transpiler.transpile(source)
|
|
60
|
-
file.remote = false
|
|
61
|
-
id += 1
|
|
62
|
-
file.id = id
|
|
63
|
-
options.hooks.onAfterFile(file)
|
|
64
|
-
return file
|
|
65
|
-
} catch (exception) {}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return {}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async function fetch (node, kind, context, isRemote, remoteUrl, options) {
|
|
72
|
-
const paths = options.paths || []
|
|
73
|
-
const names = kind === 'IMPORT' ? getComponentNames(node.attributes) : ['']
|
|
74
|
-
return Promise.all(names.map(async name => {
|
|
75
|
-
const type = kind === 'IMPORT' ? 'COMPONENT' : kind
|
|
76
|
-
const dir = dirname(context)
|
|
77
|
-
const assetPaths = getAssetPaths(node, name)
|
|
78
|
-
return Promise.all(assetPaths.map(async assetPath => {
|
|
79
|
-
const { source, path, base64, remote, url, buffer, id } = await loadComponent(node, assetPath, isRemote, remoteUrl, options, [dir, ...paths])
|
|
80
|
-
if (!path) {
|
|
81
|
-
const isNodeStylesheet = node.attributes.some(({ key, value }) => key === 'rel' && value === 'stylesheet') && node.attributes.some(({ key }) => key === 'inline')
|
|
82
|
-
|
|
83
|
-
if (isNodeStylesheet) {
|
|
84
|
-
return {
|
|
85
|
-
warnings: [{ type: 'STYLESHEET_NOT_FOUND', message: `Stylesheet not found: ${isRemotePath(assetPath) ? assetPath : name}` }]
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
return {
|
|
89
|
-
warnings: [{ type: 'COMPONENT_NOT_FOUND', message: `Component not found: ${isRemotePath(assetPath) ? assetPath : name}` }]
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const tree = parse(source)
|
|
94
|
-
const files = [context]
|
|
95
|
-
const warnings = []
|
|
96
|
-
return { name, source, base64, remote, url, buffer, path, files, warnings, tree, type, id }
|
|
97
|
-
}))
|
|
98
|
-
}))
|
|
99
|
-
}
|
|
100
|
-
const MAXIMUM_IMPORT_DEPTH = 50
|
|
101
|
-
async function recursiveImport (tree, source, path, options, depth, remote, url) {
|
|
102
|
-
if (depth > MAXIMUM_IMPORT_DEPTH) {
|
|
103
|
-
return {
|
|
104
|
-
assets: [],
|
|
105
|
-
warnings: [{
|
|
106
|
-
type: 'MAXIMUM_IMPORT_DEPTH_EXCEEDED',
|
|
107
|
-
message: 'Maximum import depth exceeded',
|
|
108
|
-
severity: 'critical'
|
|
109
|
-
}]
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
const imports = getImportNodes(tree, options)
|
|
113
|
-
const isHtmlPath = path === '.' || path.endsWith('.html')
|
|
114
|
-
const warnings = isHtmlPath ? lint(source, imports.map(({ node }) => node), options) : []
|
|
115
|
-
const assets = await Promise.all(imports.map(({ node, kind }) => fetch(node, kind, path, remote, url, options)))
|
|
116
|
-
const current = flatten(assets)
|
|
117
|
-
const nested = await Promise.all(current.filter(element => element.tree).map(async element => {
|
|
118
|
-
return recursiveImport(element.tree, element.source, element.path, options, depth + 1, element.remote, element.url)
|
|
119
|
-
}))
|
|
120
|
-
let nestedAssets = current.concat(flatten(nested.map(object => object.assets)))
|
|
121
|
-
nestedAssets = mergeAssets(nestedAssets)
|
|
122
|
-
const nestedWarnings = warnings.concat(flatten(nested.map(object => object.warnings)))
|
|
123
|
-
return {
|
|
124
|
-
assets: nestedAssets,
|
|
125
|
-
warnings: nestedWarnings.concat(
|
|
126
|
-
flatten(nestedAssets.map(file => file.warnings)),
|
|
127
|
-
flatten(current.map(element => element.warnings))
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = class Importer {
|
|
133
|
-
constructor (source, options = {}) {
|
|
134
|
-
this.source = source
|
|
135
|
-
this.tree = parse(source)
|
|
136
|
-
this.options = options
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async import () {
|
|
140
|
-
return recursiveImport(this.tree, this.source, '.', this.options, 0, false, null)
|
|
141
|
-
}
|
|
142
|
-
}
|