@katabatic/compiler 1.1.0 → 1.1.1
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/package.json +1 -1
- package/src/css-matcher.js +52 -48
- package/src/module-matcher.js +23 -1
- package/src/transform/index.js +2 -0
- package/src/transform/visitors/Program.js +2 -3
- package/src/transform/visitors/Style.js +11 -2
- package/src/transform/visitors/Template.js +3 -3
- package/src/transform/visitors/TypeSelector.js +6 -0
package/package.json
CHANGED
package/src/css-matcher.js
CHANGED
|
@@ -36,65 +36,69 @@ function matchSelectors(selectors, template) {
|
|
|
36
36
|
if (selectors.length === 0) return false
|
|
37
37
|
|
|
38
38
|
let result = false
|
|
39
|
-
walk(template, undefined, {
|
|
40
|
-
Element: (node, ctx) => {
|
|
41
|
-
ctx.next()
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
function Visitor(node, ctx) {
|
|
41
|
+
ctx.next()
|
|
42
|
+
|
|
43
|
+
let scopedIdAttribute
|
|
44
|
+
let scopedClassAttribute
|
|
45
|
+
let scopedElement
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
let classAttribute
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
54
|
-
scopedElement = node
|
|
55
|
-
scopedClassAttribute = classAttribute
|
|
56
|
-
break
|
|
57
|
-
}
|
|
58
|
-
return
|
|
59
|
-
case 'PseudoClassSelector':
|
|
49
|
+
for (const selector of selectors) {
|
|
50
|
+
switch (selector.type) {
|
|
51
|
+
case 'TypeSelector':
|
|
52
|
+
if (selector.name === node.name) {
|
|
60
53
|
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
61
54
|
scopedElement = node
|
|
62
55
|
scopedClassAttribute = classAttribute
|
|
63
56
|
break
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
57
|
+
}
|
|
58
|
+
return
|
|
59
|
+
case 'PseudoClassSelector':
|
|
60
|
+
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
61
|
+
scopedElement = node
|
|
62
|
+
scopedClassAttribute = classAttribute
|
|
63
|
+
break
|
|
64
|
+
case 'IdSelector':
|
|
65
|
+
const idAttribute = node.attributes.find((a) => a.name === 'id')
|
|
66
|
+
if (idAttribute?.value[0].data === selector.name) {
|
|
67
|
+
scopedIdAttribute = idAttribute
|
|
68
|
+
break
|
|
69
|
+
}
|
|
70
|
+
return
|
|
71
|
+
case 'ClassSelector':
|
|
72
|
+
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
73
|
+
const classes = classAttribute?.value[0].data.split(/\s+/)
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
scopedClassAttribute.metadata ??= {}
|
|
89
|
-
scopedClassAttribute.metadata.isScoped = true
|
|
90
|
-
}
|
|
91
|
-
if (scopedElement) {
|
|
92
|
-
scopedElement.metadata ??= {}
|
|
93
|
-
scopedElement.metadata.isScoped = true
|
|
75
|
+
if (classes?.includes(selector.name)) {
|
|
76
|
+
scopedClassAttribute = classAttribute
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
return
|
|
94
80
|
}
|
|
81
|
+
}
|
|
95
82
|
|
|
96
|
-
|
|
83
|
+
if (scopedIdAttribute) {
|
|
84
|
+
scopedIdAttribute.metadata ??= {}
|
|
85
|
+
scopedIdAttribute.metadata.isScoped = true
|
|
86
|
+
}
|
|
87
|
+
if (scopedClassAttribute) {
|
|
88
|
+
scopedClassAttribute.metadata ??= {}
|
|
89
|
+
scopedClassAttribute.metadata.isScoped = true
|
|
90
|
+
}
|
|
91
|
+
if (scopedElement) {
|
|
92
|
+
scopedElement.metadata ??= {}
|
|
93
|
+
scopedElement.metadata.isScoped = true
|
|
97
94
|
}
|
|
95
|
+
|
|
96
|
+
result = true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
walk(template, undefined, {
|
|
100
|
+
Element: Visitor,
|
|
101
|
+
CustomElement: Visitor
|
|
98
102
|
})
|
|
99
103
|
return result
|
|
100
104
|
}
|
package/src/module-matcher.js
CHANGED
|
@@ -11,7 +11,29 @@ export function matchModule(name, index, template) {
|
|
|
11
11
|
|
|
12
12
|
result = true
|
|
13
13
|
}
|
|
14
|
-
}
|
|
14
|
+
},
|
|
15
|
+
TypeSelector: (node, ctx) => {
|
|
16
|
+
if (node.name === name) {
|
|
17
|
+
node.metadata ??= {}
|
|
18
|
+
node.metadata.isModule = true
|
|
19
|
+
node.metadata.index = index
|
|
20
|
+
|
|
21
|
+
result = true
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
...CssTree
|
|
15
25
|
})
|
|
16
26
|
return result
|
|
17
27
|
}
|
|
28
|
+
|
|
29
|
+
export const CssTree = {
|
|
30
|
+
StyleSheet: CssTreeNodeFix,
|
|
31
|
+
SelectorList: CssTreeNodeFix,
|
|
32
|
+
Selector: CssTreeNodeFix,
|
|
33
|
+
PseudoClassSelector: CssTreeNodeFix
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function CssTreeNodeFix(node, ctx) {
|
|
37
|
+
const children = node.children?.map((c) => ctx.visit(c)) ?? null
|
|
38
|
+
return { ...node, children }
|
|
39
|
+
}
|
package/src/transform/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import { CustomElement } from './visitors/CustomElement.js'
|
|
|
19
19
|
import { AssignmentExpression } from './visitors/AssignmentExpression.js'
|
|
20
20
|
import { PropertyDefinition } from './visitors/PropertyDefinition.js'
|
|
21
21
|
import { PrivateIdentifier } from './visitors/PrivateIdentifier.js'
|
|
22
|
+
import { TypeSelector } from './visitors/TypeSelector.js'
|
|
22
23
|
|
|
23
24
|
const templateVisitors = {
|
|
24
25
|
Template,
|
|
@@ -34,6 +35,7 @@ const templateVisitors = {
|
|
|
34
35
|
IfBlock,
|
|
35
36
|
EachBlock,
|
|
36
37
|
Selector,
|
|
38
|
+
TypeSelector,
|
|
37
39
|
...CssTree
|
|
38
40
|
}
|
|
39
41
|
|
|
@@ -18,9 +18,8 @@ export function Program(node, ctx) {
|
|
|
18
18
|
stmts1.push(stmt)
|
|
19
19
|
|
|
20
20
|
// style
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
stmt = b.declaration('STYLE', b.literal(style))
|
|
21
|
+
const style = ctx.state.template.style
|
|
22
|
+
stmt = b.declaration('STYLE', b.template(style))
|
|
24
23
|
stmts1.push(stmt)
|
|
25
24
|
|
|
26
25
|
// $name
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { generate } from 'css-tree'
|
|
2
|
-
import
|
|
2
|
+
import * as b from '../../builders.js'
|
|
3
|
+
import { appendExpression, appendText } from '../../utils/template.js'
|
|
3
4
|
|
|
4
5
|
export function Style(node, ctx) {
|
|
5
6
|
node = ctx.next() ?? node
|
|
6
7
|
|
|
7
8
|
const css = generate(node.content)
|
|
9
|
+
const style = css.length > 0 ? `<style>${css}</style>` : ''
|
|
10
|
+
|
|
11
|
+
// handle modules
|
|
12
|
+
const tokens = style.split(/(\$Module_\d+)/)
|
|
13
|
+
for (const token of tokens) {
|
|
14
|
+
token.startsWith('$Module_')
|
|
15
|
+
? appendExpression(ctx.state.style, b.$name(token))
|
|
16
|
+
: appendText(ctx.state.style, token)
|
|
17
|
+
}
|
|
8
18
|
|
|
9
|
-
ctx.state.css.push(css)
|
|
10
19
|
appendText(ctx.state.template, '<!-- -->')
|
|
11
20
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as b from '../../builders.js'
|
|
2
2
|
|
|
3
3
|
export function Template(node, ctx) {
|
|
4
|
-
const
|
|
4
|
+
const style = { text: [''], expressions: [] }
|
|
5
5
|
const template = { text: [''], expressions: [] }
|
|
6
6
|
const init = { elem: [], text: [], binding: [] }
|
|
7
7
|
const effects = []
|
|
@@ -11,7 +11,7 @@ export function Template(node, ctx) {
|
|
|
11
11
|
|
|
12
12
|
ctx.visit(node.fragment, {
|
|
13
13
|
...ctx.state,
|
|
14
|
-
|
|
14
|
+
style,
|
|
15
15
|
template,
|
|
16
16
|
init,
|
|
17
17
|
effects,
|
|
@@ -40,5 +40,5 @@ export function Template(node, ctx) {
|
|
|
40
40
|
const bodyStmt = [...stmts1, ...stmts2, stmt3]
|
|
41
41
|
const block = b.$block(bodyStmt)
|
|
42
42
|
|
|
43
|
-
return { type: 'TemplateMod', metadata: node.metadata,
|
|
43
|
+
return { type: 'TemplateMod', metadata: node.metadata, style, template, block }
|
|
44
44
|
}
|