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.
Files changed (139) hide show
  1. package/README.md +0 -358
  2. package/index.js +402 -4
  3. package/package.json +12 -37
  4. package/src/Bundler.js +0 -13
  5. package/src/Cache.js +0 -35
  6. package/src/Compiler.js +0 -28
  7. package/src/Importer.js +0 -142
  8. package/src/Optimizer.js +0 -96
  9. package/src/Scope.js +0 -20
  10. package/src/Statistics.js +0 -58
  11. package/src/bundlers/esbuild/index.js +0 -55
  12. package/src/bundlers/esbuild/plugins/css.js +0 -40
  13. package/src/bundlers/esbuild/plugins/html.js +0 -27
  14. package/src/bundlers/esbuild/plugins/image.js +0 -38
  15. package/src/bundlers/esbuild/plugins/resolve.js +0 -11
  16. package/src/bundlers/esbuild/plugins/yaml.js +0 -38
  17. package/src/bundlers/esbuild/utilities/asset.js +0 -19
  18. package/src/bundlers/rollup.js +0 -38
  19. package/src/compile.js +0 -6
  20. package/src/compilers/any/Compiler.js +0 -16
  21. package/src/compilers/compile.js +0 -17
  22. package/src/compilers/html/Analyzer.js +0 -24
  23. package/src/compilers/html/Compiler.js +0 -47
  24. package/src/compilers/html/Generator.js +0 -19
  25. package/src/compilers/html/Parser.js +0 -11
  26. package/src/compilers/html/Preprocessor.js +0 -130
  27. package/src/compilers/html/Renderer.js +0 -167
  28. package/src/compilers/html/Transpiler.js +0 -76
  29. package/src/compilers/js/Bundler.js +0 -84
  30. package/src/compilers/js/Compiler/index.js +0 -27
  31. package/src/conditions/isEqual.js +0 -5
  32. package/src/lexers/html.js +0 -49
  33. package/src/lexers/internal.js +0 -49
  34. package/src/linters/html/bracket.js +0 -36
  35. package/src/linters/html/component.js +0 -43
  36. package/src/linters/html/import.js +0 -35
  37. package/src/linters/html/index.js +0 -19
  38. package/src/linters/html/tag.js +0 -36
  39. package/src/optimizers/html.js +0 -15
  40. package/src/plugins/BoxModelPlugin/index.js +0 -109
  41. package/src/plugins/CurlyStylesPlugin/index.js +0 -39
  42. package/src/plugins/DataPlugin/index.js +0 -53
  43. package/src/plugins/InlinePlugin/css.js +0 -131
  44. package/src/plugins/InlinePlugin/index.js +0 -39
  45. package/src/plugins/InternationalizationPlugin/index.js +0 -111
  46. package/src/plugins/Plugin.js +0 -22
  47. package/src/plugins/ScopedStylesPlugin/css.js +0 -56
  48. package/src/plugins/ScopedStylesPlugin/html.js +0 -112
  49. package/src/plugins/ScopedStylesPlugin/index.js +0 -48
  50. package/src/plugins/SwappedStylesPlugin/index.js +0 -20
  51. package/src/render.js +0 -48
  52. package/src/tags/case.js +0 -28
  53. package/src/tags/catch.js +0 -17
  54. package/src/tags/data.js +0 -7
  55. package/src/tags/default.js +0 -20
  56. package/src/tags/doctype.js +0 -8
  57. package/src/tags/else.js +0 -18
  58. package/src/tags/elseif.js +0 -25
  59. package/src/tags/elseunless.js +0 -30
  60. package/src/tags/font.js +0 -37
  61. package/src/tags/for.js +0 -90
  62. package/src/tags/foreach.js +0 -80
  63. package/src/tags/if.js +0 -19
  64. package/src/tags/img.js +0 -25
  65. package/src/tags/index.js +0 -53
  66. package/src/tags/link.js +0 -14
  67. package/src/tags/script/index.js +0 -83
  68. package/src/tags/script/scoped.js +0 -26
  69. package/src/tags/slot.js +0 -9
  70. package/src/tags/style.js +0 -9
  71. package/src/tags/switch.js +0 -13
  72. package/src/tags/template.js +0 -22
  73. package/src/tags/translate.js +0 -22
  74. package/src/tags/translation.js +0 -38
  75. package/src/tags/try.js +0 -17
  76. package/src/tags/unless.js +0 -24
  77. package/src/tags/var.js +0 -32
  78. package/src/transpilers/css/index.js +0 -34
  79. package/src/transpilers/html/expression.js +0 -101
  80. package/src/transpilers/html/index.js +0 -189
  81. package/src/transpilers/html/node.js +0 -46
  82. package/src/transpilers/html/tags/any.js +0 -53
  83. package/src/transpilers/html/tags/comment.js +0 -7
  84. package/src/transpilers/html/tags/doctype.js +0 -6
  85. package/src/transpilers/html/tags/for.js +0 -30
  86. package/src/transpilers/html/tags/if.js +0 -55
  87. package/src/transpilers/html/tags/import.js +0 -7
  88. package/src/transpilers/html/tags/index.js +0 -13
  89. package/src/transpilers/html/tags/partial.js +0 -17
  90. package/src/transpilers/html/tags/slot.js +0 -7
  91. package/src/transpilers/html/tags/text.js +0 -6
  92. package/src/transpilers/html/tags/try.js +0 -30
  93. package/src/transpilers/html/tags/unless.js +0 -58
  94. package/src/transpilers/html/utilities/path.js +0 -9
  95. package/src/utilities/action.js +0 -208
  96. package/src/utilities/array.js +0 -80
  97. package/src/utilities/assets.js +0 -18
  98. package/src/utilities/ast.js +0 -13
  99. package/src/utilities/attributes.js +0 -23
  100. package/src/utilities/collect.js +0 -404
  101. package/src/utilities/conditions.js +0 -159
  102. package/src/utilities/convert.js +0 -359
  103. package/src/utilities/data.js +0 -55
  104. package/src/utilities/enum.js +0 -103
  105. package/src/utilities/errors.js +0 -96
  106. package/src/utilities/factory.js +0 -237
  107. package/src/utilities/files.js +0 -55
  108. package/src/utilities/filters.js +0 -140
  109. package/src/utilities/globals.js +0 -43
  110. package/src/utilities/html.js +0 -60
  111. package/src/utilities/inline.js +0 -200
  112. package/src/utilities/js.js +0 -15
  113. package/src/utilities/keywords.js +0 -35
  114. package/src/utilities/log.js +0 -31
  115. package/src/utilities/node.js +0 -149
  116. package/src/utilities/object.js +0 -8
  117. package/src/utilities/optimize.js +0 -268
  118. package/src/utilities/options.js +0 -99
  119. package/src/utilities/request.js +0 -13
  120. package/src/utilities/string.js +0 -144
  121. package/src/utilities/style.js +0 -15
  122. package/src/utilities/translations.js +0 -78
  123. package/src/utilities/url.js +0 -24
  124. package/src/vdom/browser/app.js +0 -19
  125. package/src/vdom/browser/diff.js +0 -104
  126. package/src/vdom/browser/index.js +0 -15
  127. package/src/vdom/browser/mount.js +0 -10
  128. package/src/vdom/browser/render.js +0 -66
  129. package/src/vdom/browser/replace.js +0 -7
  130. package/src/vdom/node.js +0 -10
  131. package/src/vdom/nodes.js +0 -116
  132. package/src/vdom/server/State.js +0 -21
  133. package/src/vdom/server/boxwood.js +0 -5
  134. package/src/vdom/server/index.js +0 -19
  135. package/src/vdom/server/render.js +0 -66
  136. package/src/vdom/tag.js +0 -33
  137. package/src/vdom/utilities/classes.js +0 -22
  138. package/src/vdom/utilities/css.js +0 -17
  139. package/src/vdom/utilities/escape.js +0 -50
@@ -1,130 +0,0 @@
1
- const ScopedStylesPlugin = require('../../plugins/ScopedStylesPlugin')
2
- const InlinePlugin = require('../../plugins/InlinePlugin')
3
- const SwappedStylesPlugin = require('../../plugins/SwappedStylesPlugin')
4
-
5
- const plugins = [
6
- new InlinePlugin(),
7
- new ScopedStylesPlugin(),
8
- new SwappedStylesPlugin()
9
- ]
10
-
11
- function walk (node, callback) {
12
- let children
13
- if (Array.isArray(node)) {
14
- children = node
15
- } else {
16
- callback(node)
17
- children = node.children
18
- }
19
- if (children) {
20
- let child = children[0]
21
- let i = 0
22
- while (child) {
23
- walk(child, callback)
24
- child = children[++i]
25
- }
26
- }
27
- }
28
-
29
- function remove (tree, callback) {
30
- tree = tree.map(node => {
31
- if (callback(node)) {
32
- return null
33
- }
34
- return node
35
- }).filter(Boolean)
36
- walk(tree, node => {
37
- if (node.children) {
38
- for (let i = 0, ilen = node.children.length; i < ilen; i++) {
39
- if (callback(node.children[i])) {
40
- node.children[i] = null
41
- }
42
- }
43
- node.children = node.children.filter(Boolean)
44
- }
45
- })
46
- return tree
47
- }
48
-
49
- class Preprocessor {
50
- preprocess (tree, assets, options) {
51
- const references = {}
52
- const styles = []
53
-
54
- // things that are missing
55
- // - use the scoped styles plugin first
56
- // - handle imported components
57
-
58
- // it would be nicer to do this in a more functional way, like `abstract-syntax-tree` lib
59
- //
60
-
61
- plugins.forEach(plugin => {
62
- plugin.depth += 1
63
- plugin.beforeprerun()
64
- })
65
-
66
- walk(tree, node => {
67
- if (node.tagName === 'head') {
68
- references.head = node
69
- } else if (node.tagName === 'style') {
70
- styles.push(node)
71
- plugins.forEach(plugin => {
72
- plugin.prerun({
73
- tag: node.tagName,
74
- keys: node.attributes.map(leaf => leaf.key),
75
- attributes: node.attributes,
76
- attrs: node.attributes,
77
- children: node.children || [],
78
- fragment: node,
79
- assets,
80
- options
81
- })
82
- })
83
- }
84
- })
85
- plugins.forEach(plugin => { plugin.afterprerun() })
86
- plugins.forEach(plugin => { plugin.beforerun() })
87
- walk(tree, node => {
88
- plugins.forEach(plugin => {
89
- plugin.run({
90
- tag: node.tagName,
91
- keys: node.attributes && node.attributes.map(leaf => leaf.key),
92
- fragment: node,
93
- attributes: node.attributes,
94
- assets,
95
- options,
96
- children: node.children || []
97
- })
98
- })
99
- })
100
- plugins.forEach(plugin => {
101
- plugin.afterrun()
102
- plugin.depth -= 1
103
- })
104
-
105
- tree = remove(tree, node => {
106
- return node && node.tagName === 'style'
107
- })
108
-
109
- if (styles.length > 0 && references.head) {
110
- references.head.children.push({
111
- type: 'element',
112
- tagName: 'style',
113
- attributes: [],
114
- children: [
115
- {
116
- type: 'text',
117
- content: styles.reduce((result, style) => {
118
- const { content } = style.children[0]
119
- return result + content
120
- }, '')
121
- }
122
- ]
123
- })
124
- }
125
-
126
- return { tree, styles }
127
- }
128
- }
129
-
130
- module.exports = Preprocessor
@@ -1,167 +0,0 @@
1
- 'use strict'
2
-
3
- const AbstractSyntaxTree = require('abstract-syntax-tree')
4
- const walk = require('himalaya-walk')
5
- const { TEMPLATE_VARIABLE, OBJECT_VARIABLE, ESCAPE_VARIABLE, BUILT_IN_VARIABLES } = require('../../utilities/enum')
6
- const { getTemplateVariableDeclaration, getTemplateReturnStatement, getTemplateAssignmentExpression } = require('../../utilities/factory')
7
- const collect = require('../../utilities/collect')
8
- const { getFilter } = require('../../utilities/filters')
9
- const { concatenateScripts } = require('../../utilities/js')
10
- const { unique } = require('pure-utilities/array')
11
- const Statistics = require('../../Statistics')
12
- const DataPlugin = require('../../plugins/DataPlugin')
13
- const CurlyStylesPlugin = require('../../plugins/CurlyStylesPlugin')
14
- const ScopedStylesPlugin = require('../../plugins/ScopedStylesPlugin')
15
- const InternationalizationPlugin = require('../../plugins/InternationalizationPlugin')
16
- const BoxModelPlugin = require('../../plugins/BoxModelPlugin')
17
- const InlinePlugin = require('../../plugins/InlinePlugin')
18
- const SwappedStylesPlugin = require('../../plugins/SwappedStylesPlugin')
19
- const Importer = require('../../Importer')
20
- const Optimizer = require('../../Optimizer')
21
- const Scope = require('../../Scope')
22
- const { getLiteral } = require('../../utilities/ast')
23
- const Preprocessor = require('./Preprocessor')
24
- const { transpile: transpileCSS } = require('../../transpilers/css')
25
-
26
- function replaceNeedleOrAppend (tree, { needles, needle, tag, content }) {
27
- if (content) {
28
- const all = `<${tag}>${content}</${tag}>`
29
- if (needles[needle]) {
30
- const node = tree.first(`Literal[value=__NEEDLE_${needle.toUpperCase()}__]`)
31
- node.value = all
32
- } else {
33
- tree.append(getTemplateAssignmentExpression(TEMPLATE_VARIABLE, getLiteral(all)))
34
- }
35
- } else {
36
- tree.replace((node) => {
37
- if (node.type === 'ExpressionStatement' &&
38
- node.expression.type === 'AssignmentExpression' &&
39
- node.expression.right.type === 'Literal' &&
40
- node.expression.right.value === `__NEEDLE_${needle.toUpperCase()}__`) {
41
- return null
42
- }
43
- return node
44
- })
45
- }
46
- }
47
-
48
- class Renderer {
49
- async render (source, htmltree, options) {
50
- if (!htmltree) { return null }
51
- const tree = new AbstractSyntaxTree('')
52
- const variables = [
53
- TEMPLATE_VARIABLE,
54
- OBJECT_VARIABLE,
55
- ESCAPE_VARIABLE
56
- ].concat(BUILT_IN_VARIABLES)
57
- const filters = []
58
- const components = []
59
- const statistics = new Statistics()
60
- const importer = new Importer(source, options)
61
- const { assets, warnings } = await importer.import()
62
- assets.forEach(asset => {
63
- if (asset.type === 'COMPONENT') {
64
- statistics.components.push(asset)
65
- } else if (asset.type === 'PARTIAL') {
66
- statistics.partials.push(asset)
67
- } else if (asset.type === 'SCRIPT') {
68
- statistics.scripts.push(asset)
69
- } else if (asset.type === 'STYLESHEET') {
70
- statistics.stylesheets.push(asset)
71
- } else if (asset.type === 'IMAGE') {
72
- statistics.images.push(asset)
73
- } else if (asset.type === 'TRANSLATION') {
74
- statistics.translations.push(asset)
75
- }
76
- })
77
- const scripts = []
78
- const stack = [options.path]
79
- const store = {}
80
- const translations = {}
81
- const needles = {}
82
- const promises = []
83
- const errors = []
84
- const plugins = [
85
- new DataPlugin(),
86
- new InlinePlugin(),
87
- new BoxModelPlugin(options),
88
- new CurlyStylesPlugin(),
89
- new ScopedStylesPlugin(),
90
- new SwappedStylesPlugin(),
91
- new InternationalizationPlugin({ translations, filters, errors })
92
- ]
93
- const depth = 0
94
- tree.append(getTemplateVariableDeclaration(TEMPLATE_VARIABLE))
95
- plugins.forEach(plugin => {
96
- plugin.depth = 0
97
- plugin.beforeprerun()
98
- })
99
- const preprocessor = new Preprocessor()
100
- const output = preprocessor.preprocess(htmltree, assets, options)
101
- htmltree = output.tree
102
- const styles = output.styles
103
- ? output.styles.map(style => style.children[0] && style.children[0].content).filter(Boolean)
104
- : []
105
-
106
- assets.forEach(asset => {
107
- if (asset.type === 'COMPONENT' && asset.path.endsWith('.css')) {
108
- const css = transpileCSS(asset.source)
109
- styles.push(css)
110
- }
111
- })
112
- walk(htmltree, async fragment => {
113
- try {
114
- const attrs = fragment.attributes || []
115
- plugins.forEach(plugin => {
116
- plugin.prerun({
117
- source,
118
- tag: fragment.tagName,
119
- keys: attrs.map(attribute => attribute.key),
120
- attrs,
121
- fragment,
122
- options,
123
- assets,
124
- stack,
125
- errors,
126
- ...fragment,
127
- pass: 'renderer'
128
- })
129
- })
130
- } catch (exception) {
131
- errors.push(exception)
132
- }
133
- })
134
- plugins.forEach(plugin => { plugin.afterprerun() })
135
-
136
- const severities = warnings.map(warning => warning.severity)
137
- if (!severities.includes('critical')) {
138
- walk(htmltree, async fragment => {
139
- await collect({ source, tree, fragment, assets, variables, filters, components, styles, scripts, translations, plugins, stack, store, depth, options, promises, errors, warnings, needles })
140
- })
141
- await Promise.all(promises)
142
-
143
- const style = unique(styles).join(' ')
144
- replaceNeedleOrAppend(tree, { needles, needle: 'head', tag: 'style', content: style })
145
-
146
- const script = concatenateScripts(scripts)
147
- replaceNeedleOrAppend(tree, { needles, needle: 'body', tag: 'script', content: script })
148
-
149
- const used = []
150
- unique(filters).forEach(name => {
151
- const filter = getFilter(name, translations, options)
152
- if (filter && !used.includes(filter.id.name)) {
153
- tree.prepend(filter)
154
- used.push(filter.id.name)
155
- }
156
- })
157
- }
158
- tree.append(getTemplateReturnStatement())
159
- const scope = new Scope()
160
- scope.flatten(tree)
161
- const optimizer = new Optimizer()
162
- optimizer.optimize(tree)
163
- return { tree, statistics, warnings, errors }
164
- }
165
- }
166
-
167
- module.exports = Renderer
@@ -1,76 +0,0 @@
1
- 'use strict'
2
-
3
- const { isCurlyTag, getTagValue } = require('../../utilities/string')
4
- const { SPECIAL_TAGS } = require('../../utilities/enum')
5
- const tokenize = require('../../lexers/html')
6
-
7
- const transform = (tokens) => {
8
- const output = []
9
- const contexts = []
10
- const imports = []
11
- let lastTag
12
- tokens.forEach((token, index) => {
13
- const [type, value] = token
14
- const next = tokens[index + 1]
15
- if (type === 'tagName') {
16
- lastTag = value
17
- if (value === 'if' || value === 'unless') {
18
- contexts.push(value)
19
- } else if (value === 'elseif' || value === 'else' || value === 'elseunless') {
20
- const context = contexts[contexts.length - 1]
21
- if (context === 'if' || context === 'elseif' || context === 'unless') {
22
- const last = output.pop()
23
- output.push(['beginEndTag', '</'])
24
- output.push(['tagName', context])
25
- output.push(['finishTag', '>'])
26
- output.push(last)
27
- contexts.push(value)
28
- }
29
- } else if (value === 'end') {
30
- const context = contexts[contexts.length - 1]
31
- if (context === 'if' || context === 'unless' || context === 'elseunless' || context === 'else' || context === 'elseif') {
32
- tokens[index - 1][0] = 'beginEndTag'
33
- tokens[index - 1][1] = '</'
34
- token[1] = context
35
- contexts.pop()
36
- }
37
- }
38
- output.push(token)
39
- } else if (type === 'attributeName' && (lastTag === 'import' || lastTag === 'require')) {
40
- const [, value] = token
41
- if (value !== 'from' && value !== '{' && value !== '}') {
42
- // TODO unify with getComponentNames
43
- const parts = value.replace('{', '').replace('}', '').split(/,/g).map(key => key.trim()).filter(Boolean)
44
- parts.forEach(part => imports.push(part))
45
- }
46
- output.push(token)
47
- } else if (type === 'attributeName' && isCurlyTag(value) && next && next[0] !== 'attributeAssign') {
48
- const tags = SPECIAL_TAGS.filter(tag => !imports.includes(tag))
49
- if (tags.includes(lastTag)) {
50
- output.push(token)
51
- } else {
52
- output.push(['attributeName', getTagValue(value)])
53
- output.push(['attributeAssign', '='])
54
- output.push(['beginAttributeValue', '"'])
55
- output.push(['attributeData', value])
56
- output.push(['finishAttributeValue', '"'])
57
- }
58
- } else {
59
- output.push(token)
60
- }
61
- })
62
- return output
63
- }
64
-
65
- const stringify = (tokens) => {
66
- return tokens.map(([type, value]) => value).join('')
67
- }
68
-
69
- class Transpiler {
70
- transpile (source) {
71
- const tokens = tokenize(source)
72
- return stringify(transform(tokens))
73
- }
74
- }
75
-
76
- module.exports = Transpiler
@@ -1,84 +0,0 @@
1
- const AbstractSyntaxTree = require('abstract-syntax-tree')
2
- const { join } = require('path')
3
- const ESBundler = require('../../Bundler')
4
- const { OBJECT_VARIABLE } = require('../../utilities/enum')
5
-
6
- const { CallExpression, ExpressionStatement, FunctionExpression, Identifier, ImportDeclaration, ImportSpecifier, Literal } = AbstractSyntaxTree
7
-
8
- function getRenderImportSpecifier () {
9
- const identifier = new Identifier('render')
10
- return new ImportSpecifier({
11
- local: identifier,
12
- imported: identifier
13
- })
14
- }
15
-
16
- function getRenderCallExpression (node) {
17
- return new CallExpression({
18
- callee: new Identifier('render'),
19
- arguments: [
20
- new CallExpression({
21
- callee: new FunctionExpression(node.declaration),
22
- arguments: [new Identifier(OBJECT_VARIABLE)]
23
- })
24
- ]
25
- })
26
- }
27
-
28
- function isBoxwoodImportDeclaration (node) {
29
- return AbstractSyntaxTree.match(node, 'ImportDeclaration[source.value="boxwood"]')
30
- }
31
-
32
- function getBoxwoodImportDeclaration () {
33
- return new ImportDeclaration({
34
- specifiers: [getRenderImportSpecifier()],
35
- source: new Literal('boxwood')
36
- })
37
- }
38
-
39
- function isFunctionExportDeclaration (node) {
40
- return AbstractSyntaxTree.match(node, 'ExportDefaultDeclaration[declaration.type="FunctionDeclaration"]')
41
- }
42
-
43
- class Bundler {
44
- constructor (options) {
45
- this.options = options
46
- }
47
-
48
- async bundle (input) {
49
- const tree = this.parse(input)
50
-
51
- const bundler = new ESBundler()
52
- return await bundler.bundle(tree.source, {
53
- platform: 'node',
54
- format: 'iife',
55
- paths: [
56
- join(__dirname, '../../vdom/server'),
57
- ...this.options.paths
58
- ]
59
- })
60
- }
61
-
62
- parse (input) {
63
- const tree = new AbstractSyntaxTree(input)
64
- let imported = false
65
- tree.replace(node => {
66
- if (isBoxwoodImportDeclaration(node)) {
67
- imported = true
68
- node.specifiers.push(getRenderImportSpecifier())
69
- }
70
- })
71
- if (!imported) {
72
- tree.prepend(getBoxwoodImportDeclaration())
73
- }
74
- tree.replace(node => {
75
- if (isFunctionExportDeclaration(node)) {
76
- return new ExpressionStatement({ expression: getRenderCallExpression(node) })
77
- }
78
- return node
79
- })
80
- return tree
81
- }
82
- }
83
-
84
- module.exports = Bundler
@@ -1,27 +0,0 @@
1
- const AbstractSyntaxTree = require('abstract-syntax-tree')
2
- const Bundler = require('../Bundler')
3
- const { OBJECT_VARIABLE } = require('../../../utilities/enum')
4
- const { getOptions, validateOptions } = require('../../../utilities/options')
5
-
6
- class Compiler {
7
- constructor (options) {
8
- this.options = getOptions(options)
9
- }
10
-
11
- async compile (input) {
12
- const { options } = this
13
- const errors = validateOptions(options)
14
- if (errors.length > 0) { return { errors } }
15
- const bundler = new Bundler(options)
16
- const bundle = await bundler.bundle(input)
17
- const tree = new AbstractSyntaxTree(bundle)
18
- const expression = tree.first('CallExpression > ArrowFunctionExpression')
19
- const { body } = expression.body
20
- const lastNode = body.pop()
21
- body.push({ type: 'ReturnStatement', argument: lastNode.expression })
22
- const template = new Function(`return function render(${OBJECT_VARIABLE}) {\nreturn ${tree.source}}`)() // eslint-disable-line
23
- return { template, errors: [] }
24
- }
25
- }
26
-
27
- module.exports = Compiler
@@ -1,5 +0,0 @@
1
- function isEqual (a, b) {
2
- return a === b
3
- }
4
-
5
- module.exports = isEqual
@@ -1,49 +0,0 @@
1
- const Lexer = require('html-lexer')
2
-
3
- const tokenize = (source) => {
4
- const tokens = []
5
- const delegate = {
6
- write: (token) => tokens.push(token),
7
- end: () => null
8
- }
9
- const lexer = new Lexer(delegate)
10
- lexer.write(source)
11
- lexer.end()
12
- return reduce(normalize(tokens))
13
- }
14
-
15
- const normalize = (tokens) => {
16
- for (let i = 0, ilen = tokens.length; i < ilen; i += 1) {
17
- const current = tokens[i]
18
- if (current[0] === 'endTagPrefix') {
19
- const previous = tokens[i - 1]
20
- const next = tokens[i + 1]
21
- if (previous && next && previous[0] === 'rawtext' && next[0] === 'rawtext') {
22
- current[0] = 'rawtext'
23
- }
24
- }
25
- }
26
- return tokens
27
- }
28
-
29
- const reduce = (tokens) => {
30
- const newTokens = []
31
- for (let i = 0, ilen = tokens.length; i < ilen; i += 1) {
32
- const current = tokens[i]
33
- if (current[0] === 'rawtext') {
34
- let text = current[1]
35
- let next = tokens[i + 1]
36
- while (next && next[0] === 'rawtext') {
37
- i++
38
- text += next[1]
39
- next = tokens[i + 1]
40
- }
41
- newTokens.push(['rawtext', text])
42
- } else {
43
- newTokens.push(tokens[i])
44
- }
45
- }
46
- return newTokens
47
- }
48
-
49
- module.exports = tokenize
@@ -1,49 +0,0 @@
1
- 'use strict'
2
-
3
- const START_TAG = '{'
4
- const END_TAG = '}'
5
-
6
- const TEXT = 'text'
7
- const EXPRESSION = 'expression'
8
-
9
- module.exports = function tokenize (input) {
10
- const tokens = []
11
- const length = input.length
12
- let index = 0
13
- let character = input[0]
14
- function advance () {
15
- index += 1
16
- character = input[index]
17
- return character
18
- }
19
- function current (tag) {
20
- return character === tag
21
- }
22
- function push (type, value) {
23
- if (value) tokens.push({ type, value })
24
- }
25
- let value = ''
26
- let type = current(START_TAG) ? EXPRESSION : TEXT
27
- let depth = 0
28
- while (index < length) {
29
- if (current(START_TAG)) { depth += 1 } else if (current(END_TAG)) { depth -= 1 }
30
-
31
- if (current(START_TAG) && depth === 1) {
32
- push(type, value)
33
- advance()
34
- value = ''
35
- type = EXPRESSION
36
- } else if (current(END_TAG) && depth === 0) {
37
- push(type, value)
38
- advance()
39
- value = ''
40
- type = TEXT
41
- } else {
42
- value += character
43
- advance()
44
- }
45
- }
46
- push(type, value)
47
-
48
- return tokens
49
- }
@@ -1,36 +0,0 @@
1
- const tokenize = require('../../lexers/html')
2
-
3
- const OPENING_ANGLE_BRACKET = '<'
4
- const CLOSING_ANGLE_BRACKET = '>'
5
-
6
- function isOpeningBracket (character) {
7
- return character === OPENING_ANGLE_BRACKET
8
- }
9
-
10
- function isClosingBracket (character) {
11
- return character === CLOSING_ANGLE_BRACKET
12
- }
13
-
14
- function verifyBrackets (source) {
15
- const tokens = tokenize(source).filter(token => token[0] !== 'rawtext')
16
- const text = tokens.map(token => token[1]).join('')
17
-
18
- const errors = []
19
- let bracket = null
20
- for (const character of text) {
21
- if (isOpeningBracket(character)) {
22
- if (isOpeningBracket(bracket)) {
23
- errors.push({ type: 'CLOSING_ANGLE_BRACKET_MISSING', message: 'closing angle bracket is missing' })
24
- }
25
- bracket = OPENING_ANGLE_BRACKET
26
- } else if (isClosingBracket(character)) {
27
- if (!isOpeningBracket(bracket)) {
28
- errors.push({ type: 'OPENING_ANGLE_BRACKET_MISSING', message: 'opening angle bracket is missing' })
29
- }
30
- bracket = CLOSING_ANGLE_BRACKET
31
- }
32
- }
33
- return errors
34
- }
35
-
36
- module.exports = { verifyBrackets }
@@ -1,43 +0,0 @@
1
- 'use strict'
2
-
3
- const walk = require('himalaya-walk')
4
- const { unique } = require('pure-utilities/array')
5
- const { isImportTag } = require('../../utilities/string')
6
- const { getComponentNames } = require('../../utilities/attributes')
7
-
8
- function isStyleImport (node) {
9
- const from = node.attributes.find(attr => attr.key === 'from')
10
- if (from && from.value.endsWith('.css')) {
11
- return true
12
- }
13
- return false
14
- }
15
-
16
- function analyze (tree) {
17
- const components = []
18
- walk(tree, node => {
19
- if (isImportTag(node.tagName) && !isStyleImport(node)) {
20
- const names = getComponentNames(node.attributes)
21
- names.forEach(name => components.push(name))
22
- }
23
- })
24
- return { components: unique(components) }
25
- }
26
-
27
- function verifyComponents (tree) {
28
- const warnings = []
29
- const { components } = analyze(tree)
30
- walk(tree, node => {
31
- const index = components.indexOf(node.tagName)
32
- if (index !== -1) {
33
- components.splice(index, 1)
34
- }
35
- })
36
- // TODO: unify warnings.
37
- components.forEach(component => {
38
- warnings.push({ type: 'UNUSED_COMPONENT', message: `${component} component is unused` })
39
- })
40
- return warnings
41
- }
42
-
43
- module.exports = { verifyComponents, analyze }