a post-component library for building user-interfaces on the web.
1import { html } from 'dhtml'
2import { assert_eq, test } from '../../../scripts/test/test.ts'
3
4type JsonML = string | readonly [tag: string, attrs?: Record<string, any>, ...children: JsonML[]]
5interface Formatter {
6 header(value: unknown): JsonML | null
7 hasBody(value: unknown): boolean
8 body?(value: unknown): JsonML | null
9}
10
11const { devtoolsFormatters = [] } = globalThis as { devtoolsFormatters?: Formatter[] }
12
13function stringify(markup: JsonML): string {
14 if (typeof markup === 'string') return markup
15 const [tag, attrs, ...children] = markup
16
17 if (tag === 'object') return format(attrs!.object)
18
19 let str = `<${tag}`
20 if (attrs) for (const [k, v] of Object.entries(attrs)) str += ` ${k}="${v}"`
21 str += '>'
22 for (const child of children) str += stringify(child)
23 str += `</${tag}>`
24 return str
25}
26
27function format(value: unknown): string {
28 for (const formatter of devtoolsFormatters) {
29 const header = formatter.header(value)
30 if (header === null) continue
31
32 let str = stringify(header)
33 if (formatter.hasBody(value)) {
34 str += '\n\n' + stringify(formatter.body!(value)!)
35 }
36 return str
37 }
38 return JSON.stringify(value)
39}
40
41if (__DEV__) {
42 test('devtools formatter', () => {
43 assert_eq(format(html`<p>Count is ${1}</p>`), '<span>html`<p>Count is 1</p>`</span>')
44 })
45}