All files / once / mod.ts

100.00% Branches 16/16
100.00% Functions 3/3
100.00% Lines 40/40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
x11
 
 
 
x11
x11
x11
x11
x11
 
 
x11
x11
x11
x11
x11
x24
x11
x11
x120
x10
x10
x11
x11
x120
x120
x3
x3
x120
x120
x104
x104
x120
x11
x11
x33
x4
x4
x33
x33
x11
x16
x120
x11
 
 
 
 
 
x11
















































// Imports
import { type Cache, type Directive, Phase } from "@mizu/internal/engine"
export type * from "@mizu/internal/engine"

/** `*once` typings. */
export const typings = {
  modifiers: {
    flat: { type: Boolean },
  },
} as const

/** `*once` directive. */
export const _once = {
  name: "*once",
  phase: Phase.POSTPROCESSING,
  typings,
  init(renderer) {
    renderer.cache<Cache<typeof _once>>(this.name, new WeakSet())
  },
  setup(_, element, { cache }) {
    if (cache.has(element)) {
      return false
    }
  },
  async cleanup(renderer, element, { cache, context, state }) {
    let target = element
    if ((renderer.isComment(element)) && (renderer.cache("*").has(element))) {
      target = renderer.cache("*").get(element)!
    }
    const attribute = renderer.getAttributes(target, this.name, { first: true })
    if (!attribute) {
      return
    }
    if ((renderer.isHtmlElement(element)) && (renderer.parseAttribute(attribute, this.typings, { modifiers: true }).modifiers.flat)) {
      const template = element.tagName === "TEMPLATE"
      for (const child of renderer.replaceElementWithChildNodes(element, element)) {
        if (template && (renderer.isHtmlElement(child))) {
          await renderer.render(child, { context, state: { ...state } })
        }
        cache.add(child)
      }
    }
    cache.add(element)
  },
} as const satisfies Directive<{
  Cache: WeakSet<HTMLElement | Comment>
  Typings: typeof typings
}>

/** Default exports. */
export default _once