@katabatic/compiler 1.1.0 → 1.1.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/package.json +1 -1
- package/src/builders.js +0 -66
- 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/Attribute.js +6 -13
- 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/builders.js
CHANGED
|
@@ -648,72 +648,6 @@ export function $instrument(value) {
|
|
|
648
648
|
}
|
|
649
649
|
}
|
|
650
650
|
|
|
651
|
-
export function $getBindingProp(object, value, body) {
|
|
652
|
-
return {
|
|
653
|
-
type: 'CallExpression',
|
|
654
|
-
callee: {
|
|
655
|
-
type: 'MemberExpression',
|
|
656
|
-
object: { type: 'ThisExpression' },
|
|
657
|
-
property: {
|
|
658
|
-
type: 'MemberExpression',
|
|
659
|
-
object: {
|
|
660
|
-
type: 'Identifier',
|
|
661
|
-
name: '$'
|
|
662
|
-
},
|
|
663
|
-
property: {
|
|
664
|
-
type: 'Identifier',
|
|
665
|
-
name: 'getBindingProp'
|
|
666
|
-
},
|
|
667
|
-
computed: false,
|
|
668
|
-
optional: false
|
|
669
|
-
},
|
|
670
|
-
computed: false,
|
|
671
|
-
optional: false
|
|
672
|
-
},
|
|
673
|
-
arguments: [
|
|
674
|
-
object,
|
|
675
|
-
{ type: 'Literal', value },
|
|
676
|
-
{
|
|
677
|
-
type: 'ArrowFunctionExpression',
|
|
678
|
-
id: null,
|
|
679
|
-
expression: false,
|
|
680
|
-
generator: false,
|
|
681
|
-
async: false,
|
|
682
|
-
params: [{ type: 'Identifier', name: 'v' }],
|
|
683
|
-
body
|
|
684
|
-
}
|
|
685
|
-
],
|
|
686
|
-
optional: false
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
export function $setBindingProp(object, value, arg) {
|
|
691
|
-
return {
|
|
692
|
-
type: 'CallExpression',
|
|
693
|
-
callee: {
|
|
694
|
-
type: 'MemberExpression',
|
|
695
|
-
object: { type: 'ThisExpression' },
|
|
696
|
-
property: {
|
|
697
|
-
type: 'MemberExpression',
|
|
698
|
-
object: {
|
|
699
|
-
type: 'Identifier',
|
|
700
|
-
name: '$'
|
|
701
|
-
},
|
|
702
|
-
property: {
|
|
703
|
-
type: 'Identifier',
|
|
704
|
-
name: 'setBindingProp'
|
|
705
|
-
},
|
|
706
|
-
computed: false,
|
|
707
|
-
optional: false
|
|
708
|
-
},
|
|
709
|
-
computed: false,
|
|
710
|
-
optional: false
|
|
711
|
-
},
|
|
712
|
-
arguments: [object, { type: 'Literal', value }, arg],
|
|
713
|
-
optional: false
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
|
|
717
651
|
export function createElement(value) {
|
|
718
652
|
return {
|
|
719
653
|
type: 'CallExpression',
|
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
|
|
|
@@ -52,21 +52,14 @@ export function Attribute(node, ctx) {
|
|
|
52
52
|
])
|
|
53
53
|
ctx.state.effects.push(stmt)
|
|
54
54
|
} else if (bindingId) {
|
|
55
|
-
const
|
|
56
|
-
b.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
55
|
+
const stmt1 = b.$effect([
|
|
56
|
+
b.assignment(b.member(bindingId, node.name), template.expressions[0])
|
|
57
|
+
])
|
|
58
|
+
const stmt2 = b.$effect([
|
|
59
|
+
b.assignment(template.expressions[0], b.member(bindingId, node.name))
|
|
61
60
|
])
|
|
62
|
-
ctx.state.effects.push(stmt)
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
bindingId,
|
|
66
|
-
node.name,
|
|
67
|
-
b.assignment(template.expressions[0], b.id('v'))
|
|
68
|
-
)
|
|
69
|
-
ctx.state.changed.push(stmt2)
|
|
62
|
+
ctx.state.effects.push(stmt1, stmt2)
|
|
70
63
|
} else {
|
|
71
64
|
const stmt = b.$effect([
|
|
72
65
|
b.setAttribute(elementId, b.literal(node.name), template.expressions[0])
|
|
@@ -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
|
}
|