All files / if / else / mod.ts

100.00% Branches 13/13
100.00% Lines 27/27
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
 
x8
x8
 
 
 
x8
x8
x8
x8
x8
x30
x30
 
x82
x83
x83
 
 
x82
x564
x840
x105
x95
x95
 
 
x259
x720
x90
x113
x113
x33
x30
x8
 
 
x32



































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

/** `*else` directive. */
export const _else = {
  name: "*else",
  phase: Phase.TOGGLE,
  default: "true",
  execute(renderer, element, { attributes: [attribute] }) {
    let previous = element.previousSibling as HTMLElement
    while (previous) {
      // Break on non-empty text nodes
      if ((previous.nodeType === renderer.window.Node.TEXT_NODE) && (previous.textContent?.trim())) {
        break
      }

      // Force directive to `false` when a previous operand is truthy
      if ((renderer.isHtmlElement(previous))) {
        if (renderer.getAttributes(previous, [_if.name, _else.name] as string[], { first: true })) {
          return _if.execute(renderer, element, { ...arguments[2], _directive: { directive: this.name, expression: attribute.value, value: "false" } })
        }
        break
      }

      // Execute directive with given expression when first operand is found and is falsy (meaning all previous operand were falsy too)
      if ((renderer.isComment(previous)) && (renderer.getAttributes(renderer.cache("*").get(previous), _if.name, { first: true }))) {
        return _if.execute(renderer, element, { ...arguments[2], _directive: { directive: this.name, expression: attribute.value, value: attribute.value || this.default } })
      }
      previous = (previous as HTMLElement).previousSibling as HTMLElement
    }
    renderer.warn(`[${this.name}] must be immediately preceded by another [${_if.name}] or [${_else.name}], ignoring`, element)
  },
} as Directive

/** Default exports. */
export default [_if, _else]