@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@katabatic/compiler",
3
3
  "license": "MIT",
4
- "version": "1.1.0",
4
+ "version": "1.1.1",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -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
- let scopedIdAttribute
44
- let scopedClassAttribute
45
- let scopedElement
40
+ function Visitor(node, ctx) {
41
+ ctx.next()
42
+
43
+ let scopedIdAttribute
44
+ let scopedClassAttribute
45
+ let scopedElement
46
46
 
47
- let classAttribute
47
+ let classAttribute
48
48
 
49
- for (const selector of selectors) {
50
- switch (selector.type) {
51
- case 'TypeSelector':
52
- if (selector.name === node.name) {
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
- 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+/)
74
-
75
- if (classes?.includes(selector.name)) {
76
- scopedClassAttribute = classAttribute
77
- break
78
- }
79
- return
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
- 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
75
+ if (classes?.includes(selector.name)) {
76
+ scopedClassAttribute = classAttribute
77
+ break
78
+ }
79
+ return
94
80
  }
81
+ }
95
82
 
96
- result = true
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
  }
@@ -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
+ }
@@ -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 css = ctx.state.template.css
22
- const style = css.length >= 0 ? `<style>${ctx.state.template.css.join('')}</style>` : ''
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 { appendText } from '../../utils/template.js'
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 css = []
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
- css,
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, css, template, block }
43
+ return { type: 'TemplateMod', metadata: node.metadata, style, template, block }
44
44
  }
@@ -0,0 +1,6 @@
1
+ export function TypeSelector(node) {
2
+ if (node.metadata?.isModule) {
3
+ const name = `$Module_${node.metadata.index + 1}`
4
+ return { ...node, name }
5
+ }
6
+ }