jq79 0.3.25 → 0.3.27
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/dist/jq79.cjs +9 -9
- package/dist/jq79.cjs.map +1 -1
- package/dist/jq79.d.ts +1 -1
- package/dist/jq79.global.js +9 -9
- package/dist/jq79.global.js.map +1 -1
- package/dist/jq79.js +9 -9
- package/dist/jq79.js.map +1 -1
- package/package.json +1 -1
- package/src/jq79.ts +26 -18
package/src/jq79.ts
CHANGED
|
@@ -119,8 +119,13 @@ const findComponentKey = (scope: Record<string, any>, tag: string): string | nul
|
|
|
119
119
|
// become camelCase. Props stay live: a parent effect re-evaluates each
|
|
120
120
|
// expression and writes it into the child's store. The component variable is
|
|
121
121
|
// reactive too - while it's undefined (e.g. an `await import(...)` still in
|
|
122
|
-
// flight) nothing renders, and the child appears when it resolves
|
|
123
|
-
|
|
122
|
+
// flight) nothing renders, and the child appears when it resolves.
|
|
123
|
+
// `shadow` is the parent's style mode, carried down the whole render: a child
|
|
124
|
+
// of a shadow-rendered component renders inside that shadow root, so its
|
|
125
|
+
// <style> has to go in there with it - document.head can't reach into a shadow
|
|
126
|
+
// tree, and a style that never applies to its own component would still be
|
|
127
|
+
// restyling the page around it
|
|
128
|
+
const renderNestedComponent = (key: string, node: TemplateNode, scope: Record<string, any>, fx: EffectScope, shadow: boolean): Node => {
|
|
124
129
|
const anchor = document.createComment(key)
|
|
125
130
|
const wrapper = document.createDocumentFragment()
|
|
126
131
|
wrapper.appendChild(anchor)
|
|
@@ -166,8 +171,11 @@ const renderNestedComponent = (key: string, node: TemplateNode, scope: Record<st
|
|
|
166
171
|
const seed = untracked(() =>
|
|
167
172
|
Object.fromEntries(Object.entries(props).map(([name, expr]) => [name, evalExpr(expr, scope)]))
|
|
168
173
|
)
|
|
174
|
+
// mounting into a fragment attaches no shadow root of its own: a
|
|
175
|
+
// shadow-rendered child keeps its <style> elements inline, next to the DOM
|
|
176
|
+
// they style, and the parent's shadow root is what scopes both
|
|
169
177
|
const holder = document.createDocumentFragment()
|
|
170
|
-
instance.render(seed).mount(holder)
|
|
178
|
+
;(shadow ? instance.renderShadow(seed) : instance.render(seed)).mount(holder)
|
|
171
179
|
anchor.parentNode!.insertBefore(holder, anchor.nextSibling)
|
|
172
180
|
|
|
173
181
|
const syncFx = createEffectScope(scope)
|
|
@@ -228,7 +236,7 @@ const createWithScope = (expr: string, scope: Record<string, any>): Record<strin
|
|
|
228
236
|
// normally. :if/:elseif/:else/:each are handled by renderNodes, which decides
|
|
229
237
|
// *whether*/*how many times* a node is rendered before calling this. Tags
|
|
230
238
|
// matching a PascalCase scope variable render as nested components instead
|
|
231
|
-
const renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: EffectScope): Node => {
|
|
239
|
+
const renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: EffectScope, shadow: boolean): Node => {
|
|
232
240
|
// :with applies to the element's own bindings (@events, :attrs) and its
|
|
233
241
|
// whole subtree. On a :each element the item scope is already in place, so
|
|
234
242
|
// :with="item" works
|
|
@@ -236,7 +244,7 @@ const renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: Eff
|
|
|
236
244
|
const scope = withExpr !== undefined ? createWithScope(withExpr, outerScope) : outerScope
|
|
237
245
|
|
|
238
246
|
const componentKey = findComponentKey(scope, node.tag)
|
|
239
|
-
if (componentKey) return renderNestedComponent(componentKey, node, scope, fx)
|
|
247
|
+
if (componentKey) return renderNestedComponent(componentKey, node, scope, fx, shadow)
|
|
240
248
|
|
|
241
249
|
const el = document.createElement(node.tag)
|
|
242
250
|
|
|
@@ -252,7 +260,7 @@ const renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: Eff
|
|
|
252
260
|
const key = findComponentKey(scope, node.tag)
|
|
253
261
|
if (!key) return
|
|
254
262
|
upgraded = true
|
|
255
|
-
el.replaceWith(renderNestedComponent(key, node, scope, fx))
|
|
263
|
+
el.replaceWith(renderNestedComponent(key, node, scope, fx, shadow))
|
|
256
264
|
})
|
|
257
265
|
}
|
|
258
266
|
|
|
@@ -287,7 +295,7 @@ const renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: Eff
|
|
|
287
295
|
} else if (htmlExpr !== undefined) {
|
|
288
296
|
fx.effect(() => { el.innerHTML = sanitizeHTML(String(evalExpr(htmlExpr, scope) ?? "")) })
|
|
289
297
|
} else {
|
|
290
|
-
el.appendChild(renderNodes(node.children, scope, fx))
|
|
298
|
+
el.appendChild(renderNodes(node.children, scope, fx, shadow))
|
|
291
299
|
}
|
|
292
300
|
|
|
293
301
|
return el
|
|
@@ -297,7 +305,7 @@ const renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: Eff
|
|
|
297
305
|
// can be swapped in place without disturbing sibling positions. Only depends
|
|
298
306
|
// on whatever the branch expressions read (e.g. "score"), and skips
|
|
299
307
|
// rebuilding entirely when the active branch hasn't actually changed
|
|
300
|
-
const renderConditional = (branches: ConditionalBranch[], scope: Record<string, any>, fx: EffectScope): Node => {
|
|
308
|
+
const renderConditional = (branches: ConditionalBranch[], scope: Record<string, any>, fx: EffectScope, shadow: boolean): Node => {
|
|
301
309
|
const anchor = document.createComment("if")
|
|
302
310
|
const wrapper = document.createDocumentFragment()
|
|
303
311
|
wrapper.appendChild(anchor)
|
|
@@ -317,7 +325,7 @@ const renderConditional = (branches: ConditionalBranch[], scope: Record<string,
|
|
|
317
325
|
if (!next) return
|
|
318
326
|
|
|
319
327
|
branchFx = createEffectScope(scope)
|
|
320
|
-
current = renderNode(next.node, scope, branchFx)
|
|
328
|
+
current = renderNode(next.node, scope, branchFx, shadow)
|
|
321
329
|
anchor.parentNode!.insertBefore(current, anchor.nextSibling)
|
|
322
330
|
})
|
|
323
331
|
|
|
@@ -346,7 +354,7 @@ type EachEntry = { key: any; item: any; scope: Record<string, any>; node: Node;
|
|
|
346
354
|
// the first change - add :key for anything that gets reordered or filtered.
|
|
347
355
|
// Each item gets its own scope via Object.create(scope), so `item`/`$index`
|
|
348
356
|
// shadow same-named outer bindings without copying the parent scope's keys
|
|
349
|
-
const renderEach = (node: TemplateNode, scope: Record<string, any>, fx: EffectScope): Node => {
|
|
357
|
+
const renderEach = (node: TemplateNode, scope: Record<string, any>, fx: EffectScope, shadow: boolean): Node => {
|
|
350
358
|
const match = node.attrs[":each"].match(EACH_PATTERN)
|
|
351
359
|
if (!match) return document.createComment(`invalid :each expression "${node.attrs[":each"]}"`)
|
|
352
360
|
|
|
@@ -382,7 +390,7 @@ const renderEach = (node: TemplateNode, scope: Record<string, any>, fx: EffectSc
|
|
|
382
390
|
existing?.node.parentNode?.removeChild(existing.node)
|
|
383
391
|
|
|
384
392
|
const itemFx = createEffectScope(scope)
|
|
385
|
-
return { key, item, scope: itemScope, fx: itemFx, node: renderNode(itemNode, itemScope, itemFx) }
|
|
393
|
+
return { key, item, scope: itemScope, fx: itemFx, node: renderNode(itemNode, itemScope, itemFx, shadow) }
|
|
386
394
|
})
|
|
387
395
|
|
|
388
396
|
const nextKeys = new Set(nextEntries.map(entry => entry.key))
|
|
@@ -407,7 +415,7 @@ const renderEach = (node: TemplateNode, scope: Record<string, any>, fx: EffectSc
|
|
|
407
415
|
|
|
408
416
|
// renders a list of sibling template nodes (text + elements), grouping
|
|
409
417
|
// consecutive :if/:elseif/:else nodes into a single conditional block
|
|
410
|
-
const renderNodes = (nodes: (TemplateNode | string)[], scope: Record<string, any>, fx: EffectScope): DocumentFragment => {
|
|
418
|
+
const renderNodes = (nodes: (TemplateNode | string)[], scope: Record<string, any>, fx: EffectScope, shadow = false): DocumentFragment => {
|
|
411
419
|
const fragment = document.createDocumentFragment()
|
|
412
420
|
let i = 0
|
|
413
421
|
|
|
@@ -425,7 +433,7 @@ const renderNodes = (nodes: (TemplateNode | string)[], scope: Record<string, any
|
|
|
425
433
|
}
|
|
426
434
|
|
|
427
435
|
if (":each" in node.attrs) {
|
|
428
|
-
fragment.appendChild(renderEach(node, scope, fx))
|
|
436
|
+
fragment.appendChild(renderEach(node, scope, fx, shadow))
|
|
429
437
|
i++
|
|
430
438
|
continue
|
|
431
439
|
}
|
|
@@ -455,19 +463,19 @@ const renderNodes = (nodes: (TemplateNode | string)[], scope: Record<string, any
|
|
|
455
463
|
const elseNode = nextBranch(":else")
|
|
456
464
|
if (elseNode) branches.push({ node: elseNode })
|
|
457
465
|
|
|
458
|
-
fragment.appendChild(renderConditional(branches, scope, fx))
|
|
466
|
+
fragment.appendChild(renderConditional(branches, scope, fx, shadow))
|
|
459
467
|
continue
|
|
460
468
|
}
|
|
461
469
|
|
|
462
|
-
fragment.appendChild(renderNode(node, scope, fx))
|
|
470
|
+
fragment.appendChild(renderNode(node, scope, fx, shadow))
|
|
463
471
|
i++
|
|
464
472
|
}
|
|
465
473
|
|
|
466
474
|
return fragment
|
|
467
475
|
}
|
|
468
476
|
|
|
469
|
-
export const renderComponent = (component: Component79, data: ReactiveDeepData<Record<string, any
|
|
470
|
-
renderNodes(component.template, data, createEffectScope(data))
|
|
477
|
+
export const renderComponent = (component: Component79, data: ReactiveDeepData<Record<string, any>>, shadow = false): Node =>
|
|
478
|
+
renderNodes(component.template, data, createEffectScope(data), shadow)
|
|
471
479
|
|
|
472
480
|
type ComponentParts = {
|
|
473
481
|
template: TemplateNode[]
|
|
@@ -950,7 +958,7 @@ export class Component79 {
|
|
|
950
958
|
})
|
|
951
959
|
|
|
952
960
|
const content = document.createDocumentFragment()
|
|
953
|
-
content.append(this.startMarker, renderNodes(this.template, store, fx), this.endMarker)
|
|
961
|
+
content.append(this.startMarker, renderNodes(this.template, store, fx, shadow), this.endMarker)
|
|
954
962
|
this.content = content
|
|
955
963
|
|
|
956
964
|
if (shadow) {
|