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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 |
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x31
x7247
x7247
x8195
x8195
x8195
x4517
x4517
x8195
x689
x8
x8
x8
x689
x689
x8195
x8195
x2989
x35
x35
x35
x35
x2968
x2637
x2637
x2637
x1375
x115
x115
x115
x1317
x24
x24
x1173
x6
x6
x2989
x8195
x7241
x7247
x31
x31
x31
x744
x31 |
|
import { type Directive, type NonVoid, Phase } from "@mizu/internal/engine"
export type * from "@mizu/internal/engine"
export const PHASE_TESTING_DELTA = -0.5 as number
export const typings = {
modifiers: {
text: { type: Boolean },
comment: { type: Boolean },
eval: { type: Boolean },
throw: { type: Boolean },
event: { type: String },
},
} as const
export const _test = {
name: /^~test/,
prefix: "",
phase: Phase.TESTING,
typings,
multiple: true,
async execute(renderer, element, { attributes, ...options }) {
const returned = {} as NonVoid<Awaited<ReturnType<NonNullable<Directive["execute"]>>>>
for (const attribute of attributes) {
const parsed = renderer.parseAttribute(attribute, this.typings, { modifiers: true })
parsed.tag ??= Phase[Phase.TESTING]
if ((parsed.tag) && (this.phase !== (Phase[parsed.tag.toLocaleUpperCase() as keyof typeof Phase] + PHASE_TESTING_DELTA))) {
continue
}
if (renderer.isComment(element)) {
if ((parsed.modifiers.comment) && (!await renderer.evaluate(element, attribute.value || "'true'", options))) {
returned.element = renderer.uncomment(element)
element = returned.element
}
renderer.setAttribute(element, attribute.name, attribute.value)
continue
}
else if (renderer.isHtmlElement(element)) {
if ((parsed.modifiers.comment) && (await renderer.evaluate(element, attribute.value || "'true'", options))) {
returned.element = renderer.comment(element, { expression: attribute.value, directive: attribute.name })
element = returned.element
continue
}
if (parsed.modifiers.text) {
element.textContent = `${await renderer.evaluate(element, attribute.value, options)}`
continue
}
if (parsed.modifiers.eval) {
await renderer.evaluate(element, attribute.value, options)
continue
}
if (parsed.modifiers.event) {
element.addEventListener(parsed.modifiers.event, (event) => renderer.evaluate(element, attribute.value, { context: options.context, state: { ...options.state, $event: event }, args: [event] }))
}
if ((parsed.modifiers.throw) && (await renderer.evaluate(element, attribute.value || "'true'", options))) {
throw new EvalError(`Expected error from: ${element.outerHTML.replace(element.innerHTML, "")}`)
}
}
}
return returned
},
} as const satisfies Directive<{
Name: RegExp
Typings: typeof typings
}>
const _tests = Object.entries(Phase)
.filter(([, value]) => (Number.isFinite(value)) && (Number(value) > Phase.META))
.map(([key, value]) => ({ ..._test, name: new RegExp(`${_test.name.source}(?<${key.toLocaleLowerCase()}>)`), phase: (value as number) + PHASE_TESTING_DELTA })) as Array<typeof _test>
export default _tests
|