@sprlab/wccompiler 0.9.7 → 0.9.9

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 (2) hide show
  1. package/integrations/vue.js +37 -10
  2. package/package.json +1 -1
@@ -64,28 +64,54 @@ export function wccVuePlugin(options = {}) {
64
64
  let result = code
65
65
 
66
66
  // Transform v-model:propName="expr" on custom elements (tags with hyphens)
67
+ // Also handles modifiers: v-model:propName.trim.number="expr"
67
68
  // → :propName="expr" @propName-changed="expr = $event.detail"
69
+ // with modifiers applied to the event handler value:
70
+ // .trim → $event.detail.trim() (for string values)
71
+ // .number → Number($event.detail)
72
+ // .lazy → uses @propName-changed (same event, no difference for CE)
68
73
  // Run in a loop to handle multiple v-model on the same element
69
74
  let prev = ''
70
75
  while (prev !== result) {
71
76
  prev = result
72
77
  result = result.replace(
73
- /(<[\w]+-[\w-]*(?:\s[^>]*?)?)\bv-model:(\w+)="([^"]+)"/,
74
- (match, prefix, prop, expr) => {
75
- return `${prefix}:${prop}="${expr}" @${prop}-changed="${expr} = $event.detail"`
78
+ /(<[\w]+-[\w-]*(?:\s[^>]*?)?)\bv-model:(\w+)((?:\.\w+)*)="([^"]+)"/,
79
+ (match, prefix, prop, modifiersStr, expr) => {
80
+ const modifiers = modifiersStr ? modifiersStr.slice(1).split('.') : []
81
+ let value = '$event.detail'
82
+ // Apply modifiers in order
83
+ for (const mod of modifiers) {
84
+ if (mod === 'trim') {
85
+ value = `(typeof ${value} === 'string' ? (${value}).trim() : ${value})`
86
+ } else if (mod === 'number') {
87
+ value = `Number(${value})`
88
+ }
89
+ // .lazy is a no-op for custom elements (they already use change events)
90
+ }
91
+ return `${prefix}:${prop}="${expr}" @${prop}-changed="${expr} = ${value}"`
76
92
  }
77
93
  )
78
94
  }
79
95
 
80
96
  // Transform v-model="expr" (without argument) on custom elements
97
+ // Also handles modifiers: v-model.trim.lazy="expr"
81
98
  // → :model-value="expr" @model-value-changed="expr = $event.detail"
82
99
  prev = ''
83
100
  while (prev !== result) {
84
101
  prev = result
85
102
  result = result.replace(
86
- /(<[\w]+-[\w-]*(?:\s[^>]*?)?)\bv-model="([^"]+)"/,
87
- (match, prefix, expr) => {
88
- return `${prefix}:model-value="${expr}" @model-value-changed="${expr} = $event.detail"`
103
+ /(<[\w]+-[\w-]*(?:\s[^>]*?)?)\bv-model((?:\.\w+)*)="([^"]+)"/,
104
+ (match, prefix, modifiersStr, expr) => {
105
+ const modifiers = modifiersStr ? modifiersStr.slice(1).split('.') : []
106
+ let value = '$event.detail'
107
+ for (const mod of modifiers) {
108
+ if (mod === 'trim') {
109
+ value = `(typeof ${value} === 'string' ? (${value}).trim() : ${value})`
110
+ } else if (mod === 'number') {
111
+ value = `Number(${value})`
112
+ }
113
+ }
114
+ return `${prefix}:model-value="${expr}" @model-value-changed="${expr} = ${value}"`
89
115
  }
90
116
  )
91
117
  }
@@ -114,7 +140,8 @@ export function wccVuePlugin(options = {}) {
114
140
  }
115
141
 
116
142
  // Handle scoped slots: <template #name="{ prop1, prop2 }">...</template>
117
- // → <div slot="name" slot-props="prop1, prop2">content with {%prop%}</div>
143
+ // → <div slot="name" slot-props="prop1, prop2" hidden>content with {%prop%}</div>
144
+ // The 'hidden' attribute prevents {%prop%} tokens from flashing before the WCC runtime processes them.
118
145
  // Only inside custom elements (tag names with hyphens)
119
146
  prev = ''
120
147
  while (prev !== result) {
@@ -123,13 +150,13 @@ export function wccVuePlugin(options = {}) {
123
150
  /(<[\w]+-[\w-]*[^>]*>)([\s\S]*?)<template\s+#(\w+)="\{\s*([^}]*)\s*\}">([\s\S]*?)<\/template>/,
124
151
  (match, openTag, before, slotName, propsExpr, content) => {
125
152
  const { transformed, props } = transformScopedContent(content, propsExpr)
126
- return `${openTag}${before}<div slot="${slotName}" slot-props="${props.join(', ')}">${transformed}</div>`
153
+ return `${openTag}${before}<div slot="${slotName}" slot-props="${props.join(', ')}" hidden>${transformed}</div>`
127
154
  }
128
155
  )
129
156
  }
130
157
 
131
158
  // Handle scoped slots: <template v-slot:name="{ prop1, prop2 }">...</template>
132
- // → <div slot="name" slot-props="prop1, prop2">content with {%prop%}</div>
159
+ // → <div slot="name" slot-props="prop1, prop2" hidden>content with {%prop%}</div>
133
160
  // Only inside custom elements (tag names with hyphens)
134
161
  prev = ''
135
162
  while (prev !== result) {
@@ -138,7 +165,7 @@ export function wccVuePlugin(options = {}) {
138
165
  /(<[\w]+-[\w-]*[^>]*>)([\s\S]*?)<template\s+v-slot:(\w+)="\{\s*([^}]*)\s*\}">([\s\S]*?)<\/template>/,
139
166
  (match, openTag, before, slotName, propsExpr, content) => {
140
167
  const { transformed, props } = transformScopedContent(content, propsExpr)
141
- return `${openTag}${before}<div slot="${slotName}" slot-props="${props.join(', ')}">${transformed}</div>`
168
+ return `${openTag}${before}<div slot="${slotName}" slot-props="${props.join(', ')}" hidden>${transformed}</div>`
142
169
  }
143
170
  )
144
171
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprlab/wccompiler",
3
- "version": "0.9.7",
3
+ "version": "0.9.9",
4
4
  "description": "Zero-runtime compiler that transforms .wcc single-file components into native web components with signals-based reactivity",
5
5
  "type": "module",
6
6
  "exports": {