tangled
alpha
login
or
join now
tombl.dev
/
dhtml
1
fork
atom
a post-component library for building user-interfaces on the web.
1
fork
atom
overview
issues
pulls
pipelines
make HTML a class
tombl.dev
7 months ago
3f633f83
c917d5a2
verified
This commit was signed with the committer's
known signature
.
tombl.dev
SSH Key Fingerprint:
SHA256:d8AHgL5V+3WdvGdDb3SVBfb0RIRJfkKcqhQ5aG1mVNk=
+35
-20
5 changed files
expand all
collapse all
unified
split
src
client
parts.ts
root.ts
index.ts
server.ts
shared.ts
+2
-1
src/client/parts.ts
reviewed
···
5
5
is_keyed,
6
6
is_renderable,
7
7
single_part_template,
8
8
+
unwrap_html,
8
9
type Displayable,
9
10
type Key,
10
11
type Renderable,
···
172
173
}
173
174
174
175
if (is_html(value)) {
175
175
-
const { _dynamics: dynamics, _statics: statics } = value
176
176
+
const { _statics: statics, _dynamics: dynamics } = unwrap_html(value)
176
177
const template = compile_template(statics)
177
178
178
179
assert(
+4
-2
src/client/root.ts
reviewed
···
5
5
is_keyed,
6
6
is_renderable,
7
7
single_part_template,
8
8
+
unwrap_html,
8
9
type Displayable,
9
10
type Key,
10
11
type Renderable,
···
111
112
}
112
113
113
114
if (is_html(value)) {
114
114
-
template = compile_template(value._statics)
115
115
+
const { _statics: statics, _dynamics: dynamics } = unwrap_html(value)
116
116
+
template = compile_template(statics)
115
117
116
118
const node_by_part: Array<Node | Span> = []
117
119
···
180
182
_start: child.previousSibling,
181
183
_end: end,
182
184
},
183
183
-
value._dynamics[dynamic_index],
185
185
+
dynamics[dynamic_index],
184
186
),
185
187
]
186
188
case PART_DIRECTIVE:
+4
-4
src/index.ts
reviewed
···
1
1
export { html, keyed, type Displayable, type HTML, type Renderable } from './shared.ts'
2
2
3
3
-
import { is_html } from './shared.ts'
3
3
+
import { is_html, unwrap_html } from './shared.ts'
4
4
5
5
if (__DEV__) {
6
6
type JsonML = string | readonly [tag: string, attrs?: Record<string, any>, ...children: JsonML[]]
···
13
13
;((globalThis as { devtoolsFormatters?: Formatter[] }).devtoolsFormatters ??= []).push({
14
14
header(value) {
15
15
if (!is_html(value)) return null
16
16
+
const { _statics: statics, _dynamics: dynamics } = unwrap_html(value)
16
17
17
18
const children: JsonML[] = []
18
18
-
for (let i = 0; i < value._dynamics.length; i++)
19
19
-
children.push(value._statics[i], ['object', { object: value._dynamics[i] }])
20
20
-
children.push(value._statics[value._statics.length - 1])
19
19
+
for (let i = 0; i < dynamics.length; i++) children.push(statics[i], ['object', { object: dynamics[i] }])
20
20
+
children.push(statics[statics.length - 1])
21
21
22
22
return ['span', {}, 'html`', ...children, '`']
23
23
},
+11
-2
src/server.ts
reviewed
···
1
1
-
import { assert, is_html, is_iterable, is_renderable, lexer, single_part_template, type Displayable } from './shared.ts'
1
1
+
import {
2
2
+
assert,
3
3
+
is_html,
4
4
+
is_iterable,
5
5
+
is_renderable,
6
6
+
lexer,
7
7
+
single_part_template,
8
8
+
unwrap_html,
9
9
+
type Displayable,
10
10
+
} from './shared.ts'
2
11
3
12
interface PartRenderer {
4
13
replace_start: number
···
153
162
if (is_iterable(value)) {
154
163
for (const item of value) yield* render_child(item)
155
164
} else if (is_html(value)) {
156
156
-
const { _statics: statics, _dynamics: dynamics } = value
165
165
+
const { _statics: statics, _dynamics: dynamics } = unwrap_html(value)
157
166
const template = compile_template(statics)
158
167
159
168
assert(
+14
-11
src/shared.ts
reviewed
···
31
31
}
32
32
}
33
33
34
34
-
export interface HTML {
35
35
-
[html_tag]: true
36
36
-
/* @internal */ _statics: TemplateStringsArray
37
37
-
/* @internal */ _dynamics: unknown[]
34
34
+
export let unwrap_html: (value: HTML) => { _statics: TemplateStringsArray; _dynamics: unknown[] }
35
35
+
36
36
+
export class HTML {
37
37
+
#statics: TemplateStringsArray
38
38
+
#dynamics: unknown[]
39
39
+
constructor(statics: TemplateStringsArray, dynamics: unknown[]) {
40
40
+
this.#statics = statics
41
41
+
this.#dynamics = dynamics
42
42
+
}
43
43
+
static {
44
44
+
unwrap_html = value => ({ _statics: value.#statics, _dynamics: value.#dynamics })
45
45
+
}
38
46
}
39
47
40
40
-
const html_tag: unique symbol = Symbol()
41
48
export function html(statics: TemplateStringsArray, ...dynamics: unknown[]): HTML {
42
42
-
return {
43
43
-
[html_tag]: true,
44
44
-
_dynamics: dynamics,
45
45
-
_statics: statics,
46
46
-
}
49
49
+
return new HTML(statics, dynamics)
47
50
}
48
51
49
52
export function is_html(value: unknown): value is HTML {
50
50
-
return typeof value === 'object' && value !== null && html_tag in value
53
53
+
return value instanceof HTML
51
54
}
52
55
53
56
export function single_part_template(part: Displayable): HTML {