@barefootjs/client 0.26.4 → 0.28.0
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/reactive.d.ts.map +1 -1
- package/dist/runtime/claim-slots.d.ts +222 -0
- package/dist/runtime/claim-slots.d.ts.map +1 -0
- package/dist/runtime/component.d.ts +40 -18
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/dynamic-text.d.ts +24 -1
- package/dist/runtime/dynamic-text.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +4 -5
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +467 -259
- package/dist/runtime/loop-markers.d.ts +26 -0
- package/dist/runtime/loop-markers.d.ts.map +1 -0
- package/dist/runtime/map-array-lazy.d.ts +164 -0
- package/dist/runtime/map-array-lazy.d.ts.map +1 -0
- package/dist/runtime/map-array.d.ts +35 -0
- package/dist/runtime/map-array.d.ts.map +1 -1
- package/dist/runtime/qsa-item.d.ts +7 -0
- package/dist/runtime/qsa-item.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/standalone.js +455 -248
- package/package.json +2 -2
- package/src/reactive.ts +2 -1
- package/src/runtime/claim-slots.ts +647 -0
- package/src/runtime/component.ts +153 -70
- package/src/runtime/dynamic-text.ts +24 -1
- package/src/runtime/index.ts +20 -7
- package/src/runtime/insert.ts +1 -1
- package/src/runtime/loop-markers.ts +100 -0
- package/src/runtime/map-array-lazy.ts +470 -0
- package/src/runtime/map-array.ts +68 -11
- package/src/runtime/qsa-item.ts +9 -3
- package/src/runtime/registry.ts +5 -3
- package/dist/runtime/client-marker.d.ts +0 -21
- package/dist/runtime/client-marker.d.ts.map +0 -1
- package/dist/runtime/list.d.ts +0 -21
- package/dist/runtime/list.d.ts.map +0 -1
- package/dist/runtime/patch-slot-range.d.ts +0 -47
- package/dist/runtime/patch-slot-range.d.ts.map +0 -1
- package/dist/runtime/reconcile-elements.d.ts +0 -44
- package/dist/runtime/reconcile-elements.d.ts.map +0 -1
- package/src/runtime/client-marker.ts +0 -46
- package/src/runtime/list.ts +0 -47
- package/src/runtime/patch-slot-range.ts +0 -105
- package/src/runtime/reconcile-elements.ts +0 -391
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BarefootJS - Client Marker
|
|
3
|
-
*
|
|
4
|
-
* Update text content for @client directive expressions
|
|
5
|
-
* that are evaluated only on the client side.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Update text content for a client marker.
|
|
9
|
-
*
|
|
10
|
-
* Expects comment marker format: <!--bf-client:sX-->
|
|
11
|
-
* Both GoTemplateAdapter and HonoAdapter output this format for @client directives.
|
|
12
|
-
*
|
|
13
|
-
* A zero-width space (\u200B) is used as a prefix to mark text nodes managed by @client.
|
|
14
|
-
* This allows distinguishing managed text nodes from other content.
|
|
15
|
-
*
|
|
16
|
-
* @param scope - The component scope element to search within
|
|
17
|
-
* @param id - The slot ID (e.g., 's5')
|
|
18
|
-
* @param value - The value to display (will be converted to string)
|
|
19
|
-
*/
|
|
20
|
-
export declare function updateClientMarker(scope: Element | null, id: string, value: unknown): void;
|
|
21
|
-
//# sourceMappingURL=client-marker.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client-marker.d.ts","sourceRoot":"","sources":["../../src/runtime/client-marker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAyB1F"}
|
package/dist/runtime/list.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BarefootJS - List Reconciliation
|
|
3
|
-
*
|
|
4
|
-
* Key-based DOM reconciliation for efficient list updates.
|
|
5
|
-
* Delegates to reconcileElements for element-based rendering.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Render function type for list items.
|
|
9
|
-
* Returns an HTMLElement for each item.
|
|
10
|
-
*/
|
|
11
|
-
export type RenderItemFn<T> = (item: T, index: number) => HTMLElement;
|
|
12
|
-
/**
|
|
13
|
-
* Reconcile a list container with new items using key-based matching.
|
|
14
|
-
*
|
|
15
|
-
* @param container - The parent element containing list items
|
|
16
|
-
* @param items - Array of items to render
|
|
17
|
-
* @param getKey - Function to extract a unique key from each item (or null to use index)
|
|
18
|
-
* @param renderItem - Function to render an item as HTMLElement
|
|
19
|
-
*/
|
|
20
|
-
export declare function reconcileList<T>(container: HTMLElement | null, items: T[], getKey: ((item: T, index: number) => string) | null, renderItem: RenderItemFn<T>): void;
|
|
21
|
-
//# sourceMappingURL=list.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/runtime/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW,CAAA;AAErE;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,GAC1B,IAAI,CAkBN"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-place patch for a `.map()` preamble-patched loop region — the
|
|
3
|
-
* `<!--bf:sN-->...<!--/-->` marker pair around a loop-body expression child
|
|
4
|
-
* whose free identifiers read a preamble-declared local (`{cells}` in
|
|
5
|
-
* `arr.map(t => { const cells = []; ...; return <tr>{cells}<td>{t.name}</td></tr> })`,
|
|
6
|
-
* #2389). `mapArray` reuses the same row element on a same-key item update
|
|
7
|
-
* via per-item `setItem`, re-running only the row's wired text/attr-slot
|
|
8
|
-
* effects — a preamble-derived region has neither, so without this it
|
|
9
|
-
* freezes at its mount-time content forever. The compiled per-item
|
|
10
|
-
* `createEffect` (see `emitPreambleRegionEffects` in `@barefootjs/jsx`)
|
|
11
|
-
* calls this whenever the re-computed region HTML differs from the
|
|
12
|
-
* last-patched value.
|
|
13
|
-
*
|
|
14
|
-
* Sibling of `patchLeaf` (same "wholesale replace, preserve identity"
|
|
15
|
-
* contract), but scoped to a marker-delimited RANGE inside an element
|
|
16
|
-
* rather than the element itself — a region has no element of its own to
|
|
17
|
-
* hold an identity, only the comment pair.
|
|
18
|
-
*
|
|
19
|
-
* The start comment is located here, per call, rather than by a separate
|
|
20
|
-
* mount-time lookup: the region effect's first run only records the
|
|
21
|
-
* mount-time value, so a row that never changes pays ZERO lookup cost —
|
|
22
|
-
* the scan runs only on an actual content change, over a single (small)
|
|
23
|
-
* row element.
|
|
24
|
-
*
|
|
25
|
-
* Ownership: slot ids are per-component, so a marker under a nested `bf-s`
|
|
26
|
-
* scope (a child component's own `bf:sN`) is never a candidate. Today
|
|
27
|
-
* that's defense in depth — regions are only emitted for the plain
|
|
28
|
-
* loop-plan shape, and `decideLoopRendering` routes any row containing
|
|
29
|
-
* nested components or inner loops to the composite/component shapes,
|
|
30
|
-
* which don't consume `preambleRegions` — but the guard keeps that safety
|
|
31
|
-
* local instead of coupled to routing.
|
|
32
|
-
*
|
|
33
|
-
* A missing start or end marker means the DOM diverged from the compiled
|
|
34
|
-
* template — warn and do nothing (sound-or-loud: never guess a boundary).
|
|
35
|
-
*
|
|
36
|
-
* Range contract: the matching end is the nearest following sibling
|
|
37
|
-
* `<!--/-->` comment at the SAME nesting depth — any `bf:`-prefixed
|
|
38
|
-
* comment along the way opens a FURTHER nested region (a leaf rendered
|
|
39
|
-
* inside this one could carry its own ordinary text-slot markers) and
|
|
40
|
-
* increments a depth counter so that region's own `/` doesn't prematurely
|
|
41
|
-
* close the outer range. Every node strictly between the two markers is
|
|
42
|
-
* removed, then `html` is parsed via a `<template>` and inserted before
|
|
43
|
-
* the end marker. The two markers themselves are never removed — they
|
|
44
|
-
* stay as the region's permanent boundary for the next patch.
|
|
45
|
-
*/
|
|
46
|
-
export declare function patchSlotRange(scope: Element, id: string, html: string): void;
|
|
47
|
-
//# sourceMappingURL=patch-slot-range.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"patch-slot-range.d.ts","sourceRoot":"","sources":["../../src/runtime/patch-slot-range.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAyD7E"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BarefootJS - Element-based List Reconciliation
|
|
3
|
-
*
|
|
4
|
-
* Key-based DOM reconciliation for component-based list rendering.
|
|
5
|
-
* Used when renderItem returns HTMLElement (via createComponent).
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Get loop children from a container, respecting bf-loop boundary markers.
|
|
9
|
-
* When markers are present, returns only elements between them.
|
|
10
|
-
* When absent, returns all children (backward compatible).
|
|
11
|
-
* Exported for use by compiler-generated hydration code.
|
|
12
|
-
*/
|
|
13
|
-
export declare function getLoopChildren(container: HTMLElement, markerId?: string): HTMLElement[];
|
|
14
|
-
/**
|
|
15
|
-
* Like {@link getLoopChildren}, but returns every node between the loop
|
|
16
|
-
* boundary markers — Comments (per-item `<!--bf-loop-i-->` markers) and
|
|
17
|
-
* text included. The branch-clearing path needs to remove the per-item
|
|
18
|
-
* marker comments alongside elements; otherwise stale markers would
|
|
19
|
-
* accumulate when a branch swap forces mapArray to start over (#1212).
|
|
20
|
-
*/
|
|
21
|
-
export declare function getLoopNodes(container: HTMLElement, markerId?: string): Node[];
|
|
22
|
-
/**
|
|
23
|
-
* Ensure loop boundary markers exist in a container for SSR-rendered content.
|
|
24
|
-
* SSR HTML doesn't include markers, so we insert them during hydration.
|
|
25
|
-
* Uses itemCount to identify the last N children as loop items (rest are siblings).
|
|
26
|
-
*/
|
|
27
|
-
export declare function ensureLoopMarkers(container: HTMLElement, itemCount: number, markerId?: string): void;
|
|
28
|
-
/**
|
|
29
|
-
* Reconcile a list container using HTMLElement mode (for createComponent).
|
|
30
|
-
* Reuses existing elements by key, creates new elements as needed.
|
|
31
|
-
*
|
|
32
|
-
* @param container - The parent element containing list items
|
|
33
|
-
* @param items - Array of items to render
|
|
34
|
-
* @param getKey - Function to extract a unique key from each item (or null to use index)
|
|
35
|
-
* @param renderItem - Function that returns an HTMLElement for each item
|
|
36
|
-
* @param firstElement - Pre-created element for first item (avoids duplicate creation when caller already rendered item 0)
|
|
37
|
-
*/
|
|
38
|
-
export declare function reconcileElements<T>(container: HTMLElement | null, items: T[], getKey: ((item: T, index: number) => string) | null, renderItem: (item: T, index: number) => HTMLElement, firstElement?: HTMLElement, markerId?: string): void;
|
|
39
|
-
/**
|
|
40
|
-
* Sync reactive DOM state from a source element to a target element.
|
|
41
|
-
* Copies class names, replaces conditional elements, and syncs text content.
|
|
42
|
-
*/
|
|
43
|
-
export declare function syncElementState(target: HTMLElement, source: HTMLElement): void;
|
|
44
|
-
//# sourceMappingURL=reconcile-elements.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-elements.d.ts","sourceRoot":"","sources":["../../src/runtime/reconcile-elements.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAoEH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAMxF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAY9E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAgBpG;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW,EACnD,YAAY,CAAC,EAAE,WAAW,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CA2JN;AAkCD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAiD/E"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BarefootJS - Client Marker
|
|
3
|
-
*
|
|
4
|
-
* Update text content for @client directive expressions
|
|
5
|
-
* that are evaluated only on the client side.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Update text content for a client marker.
|
|
10
|
-
*
|
|
11
|
-
* Expects comment marker format: <!--bf-client:sX-->
|
|
12
|
-
* Both GoTemplateAdapter and HonoAdapter output this format for @client directives.
|
|
13
|
-
*
|
|
14
|
-
* A zero-width space (\u200B) is used as a prefix to mark text nodes managed by @client.
|
|
15
|
-
* This allows distinguishing managed text nodes from other content.
|
|
16
|
-
*
|
|
17
|
-
* @param scope - The component scope element to search within
|
|
18
|
-
* @param id - The slot ID (e.g., 's5')
|
|
19
|
-
* @param value - The value to display (will be converted to string)
|
|
20
|
-
*/
|
|
21
|
-
export function updateClientMarker(scope: Element | null, id: string, value: unknown): void {
|
|
22
|
-
if (!scope) return
|
|
23
|
-
|
|
24
|
-
const marker = `bf-client:${id}`
|
|
25
|
-
const walker = document.createTreeWalker(scope, NodeFilter.SHOW_COMMENT)
|
|
26
|
-
|
|
27
|
-
while (walker.nextNode()) {
|
|
28
|
-
if (walker.currentNode.nodeValue === marker) {
|
|
29
|
-
const comment = walker.currentNode
|
|
30
|
-
let textNode = comment.nextSibling
|
|
31
|
-
|
|
32
|
-
// Check if next sibling is our managed text node (prefixed with zero-width space)
|
|
33
|
-
if (textNode?.nodeType !== Node.TEXT_NODE ||
|
|
34
|
-
!textNode.nodeValue?.startsWith('\u200B')) {
|
|
35
|
-
// Create new text node with zero-width space marker
|
|
36
|
-
textNode = document.createTextNode('\u200B' + String(value ?? ''))
|
|
37
|
-
// Insert after the comment node
|
|
38
|
-
comment.parentNode?.insertBefore(textNode, comment.nextSibling)
|
|
39
|
-
} else {
|
|
40
|
-
// Update existing managed text node
|
|
41
|
-
textNode.nodeValue = '\u200B' + String(value ?? '')
|
|
42
|
-
}
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
package/src/runtime/list.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BarefootJS - List Reconciliation
|
|
3
|
-
*
|
|
4
|
-
* Key-based DOM reconciliation for efficient list updates.
|
|
5
|
-
* Delegates to reconcileElements for element-based rendering.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { reconcileElements } from './reconcile-elements.ts'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Render function type for list items.
|
|
12
|
-
* Returns an HTMLElement for each item.
|
|
13
|
-
*/
|
|
14
|
-
export type RenderItemFn<T> = (item: T, index: number) => HTMLElement
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Reconcile a list container with new items using key-based matching.
|
|
18
|
-
*
|
|
19
|
-
* @param container - The parent element containing list items
|
|
20
|
-
* @param items - Array of items to render
|
|
21
|
-
* @param getKey - Function to extract a unique key from each item (or null to use index)
|
|
22
|
-
* @param renderItem - Function to render an item as HTMLElement
|
|
23
|
-
*/
|
|
24
|
-
export function reconcileList<T>(
|
|
25
|
-
container: HTMLElement | null,
|
|
26
|
-
items: T[],
|
|
27
|
-
getKey: ((item: T, index: number) => string) | null,
|
|
28
|
-
renderItem: RenderItemFn<T>
|
|
29
|
-
): void {
|
|
30
|
-
if (!container || !items) return
|
|
31
|
-
|
|
32
|
-
if (items.length === 0) {
|
|
33
|
-
container.innerHTML = ''
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Pre-create first element to avoid duplicate creation inside reconcileElements
|
|
38
|
-
const firstElement = renderItem(items[0], 0)
|
|
39
|
-
|
|
40
|
-
reconcileElements(
|
|
41
|
-
container,
|
|
42
|
-
items,
|
|
43
|
-
getKey,
|
|
44
|
-
renderItem,
|
|
45
|
-
firstElement
|
|
46
|
-
)
|
|
47
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { BF_SCOPE } from '@barefootjs/shared'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* In-place patch for a `.map()` preamble-patched loop region — the
|
|
5
|
-
* `<!--bf:sN-->...<!--/-->` marker pair around a loop-body expression child
|
|
6
|
-
* whose free identifiers read a preamble-declared local (`{cells}` in
|
|
7
|
-
* `arr.map(t => { const cells = []; ...; return <tr>{cells}<td>{t.name}</td></tr> })`,
|
|
8
|
-
* #2389). `mapArray` reuses the same row element on a same-key item update
|
|
9
|
-
* via per-item `setItem`, re-running only the row's wired text/attr-slot
|
|
10
|
-
* effects — a preamble-derived region has neither, so without this it
|
|
11
|
-
* freezes at its mount-time content forever. The compiled per-item
|
|
12
|
-
* `createEffect` (see `emitPreambleRegionEffects` in `@barefootjs/jsx`)
|
|
13
|
-
* calls this whenever the re-computed region HTML differs from the
|
|
14
|
-
* last-patched value.
|
|
15
|
-
*
|
|
16
|
-
* Sibling of `patchLeaf` (same "wholesale replace, preserve identity"
|
|
17
|
-
* contract), but scoped to a marker-delimited RANGE inside an element
|
|
18
|
-
* rather than the element itself — a region has no element of its own to
|
|
19
|
-
* hold an identity, only the comment pair.
|
|
20
|
-
*
|
|
21
|
-
* The start comment is located here, per call, rather than by a separate
|
|
22
|
-
* mount-time lookup: the region effect's first run only records the
|
|
23
|
-
* mount-time value, so a row that never changes pays ZERO lookup cost —
|
|
24
|
-
* the scan runs only on an actual content change, over a single (small)
|
|
25
|
-
* row element.
|
|
26
|
-
*
|
|
27
|
-
* Ownership: slot ids are per-component, so a marker under a nested `bf-s`
|
|
28
|
-
* scope (a child component's own `bf:sN`) is never a candidate. Today
|
|
29
|
-
* that's defense in depth — regions are only emitted for the plain
|
|
30
|
-
* loop-plan shape, and `decideLoopRendering` routes any row containing
|
|
31
|
-
* nested components or inner loops to the composite/component shapes,
|
|
32
|
-
* which don't consume `preambleRegions` — but the guard keeps that safety
|
|
33
|
-
* local instead of coupled to routing.
|
|
34
|
-
*
|
|
35
|
-
* A missing start or end marker means the DOM diverged from the compiled
|
|
36
|
-
* template — warn and do nothing (sound-or-loud: never guess a boundary).
|
|
37
|
-
*
|
|
38
|
-
* Range contract: the matching end is the nearest following sibling
|
|
39
|
-
* `<!--/-->` comment at the SAME nesting depth — any `bf:`-prefixed
|
|
40
|
-
* comment along the way opens a FURTHER nested region (a leaf rendered
|
|
41
|
-
* inside this one could carry its own ordinary text-slot markers) and
|
|
42
|
-
* increments a depth counter so that region's own `/` doesn't prematurely
|
|
43
|
-
* close the outer range. Every node strictly between the two markers is
|
|
44
|
-
* removed, then `html` is parsed via a `<template>` and inserted before
|
|
45
|
-
* the end marker. The two markers themselves are never removed — they
|
|
46
|
-
* stay as the region's permanent boundary for the next patch.
|
|
47
|
-
*/
|
|
48
|
-
export function patchSlotRange(scope: Element, id: string, html: string): void {
|
|
49
|
-
const marker = `bf:${id}`
|
|
50
|
-
let start: Comment | null = null
|
|
51
|
-
const walker = document.createTreeWalker(scope, NodeFilter.SHOW_COMMENT)
|
|
52
|
-
while (walker.nextNode()) {
|
|
53
|
-
const comment = walker.currentNode as Comment
|
|
54
|
-
if (comment.nodeValue !== marker) continue
|
|
55
|
-
let owned = true
|
|
56
|
-
for (let el = comment.parentElement; el && el !== scope; el = el.parentElement) {
|
|
57
|
-
if (el.hasAttribute(BF_SCOPE)) {
|
|
58
|
-
owned = false
|
|
59
|
-
break
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (owned) {
|
|
63
|
-
start = comment
|
|
64
|
-
break
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const parent = start?.parentNode
|
|
68
|
-
if (!start || !parent) {
|
|
69
|
-
console.warn(`[barefootjs] preamble region marker bf:${id} not found in row; skipping patch`)
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let depth = 0
|
|
74
|
-
let end: Comment | null = null
|
|
75
|
-
const toRemove: Node[] = []
|
|
76
|
-
let node: Node | null = start.nextSibling
|
|
77
|
-
while (node) {
|
|
78
|
-
if (node.nodeType === Node.COMMENT_NODE) {
|
|
79
|
-
const value = (node as Comment).nodeValue ?? ''
|
|
80
|
-
if (value.startsWith('bf:')) {
|
|
81
|
-
depth++
|
|
82
|
-
} else if (value === '/') {
|
|
83
|
-
if (depth === 0) {
|
|
84
|
-
end = node as Comment
|
|
85
|
-
break
|
|
86
|
-
}
|
|
87
|
-
depth--
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
toRemove.push(node)
|
|
91
|
-
node = node.nextSibling
|
|
92
|
-
}
|
|
93
|
-
if (!end) {
|
|
94
|
-
// Malformed/unexpected DOM shape — never risk deleting past the
|
|
95
|
-
// region's intended boundary.
|
|
96
|
-
console.warn(`[barefootjs] preamble region bf:${id} has no end marker; skipping patch`)
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
for (const n of toRemove) parent.removeChild(n)
|
|
101
|
-
|
|
102
|
-
const tpl = document.createElement('template')
|
|
103
|
-
tpl.innerHTML = html
|
|
104
|
-
parent.insertBefore(tpl.content, end)
|
|
105
|
-
}
|