1 | import { DOMTreeConstruction, ConcreteBounds, NewElementBuilder } from '@glimmer/runtime';
|
2 | import createHTMLDocument from '@simple-dom/document';
|
3 |
|
4 | class NodeDOMTreeConstruction extends DOMTreeConstruction {
|
5 |
|
6 | constructor(doc) {
|
7 | super(doc || createHTMLDocument());
|
8 | }
|
9 |
|
10 |
|
11 | setupUselessElement() {}
|
12 | insertHTMLBefore(parent, reference, html) {
|
13 | let raw = this.document.createRawHTMLSection(html);
|
14 | parent.insertBefore(raw, reference);
|
15 | return new ConcreteBounds(parent, raw, raw);
|
16 | }
|
17 |
|
18 |
|
19 | createElement(tag) {
|
20 | return this.document.createElement(tag);
|
21 | }
|
22 |
|
23 |
|
24 | setAttribute(element, name, value) {
|
25 | element.setAttribute(name, value);
|
26 | }
|
27 | }
|
28 |
|
29 | const TEXT_NODE = 3;
|
30 | const NEEDS_EXTRA_CLOSE = new WeakMap();
|
31 | function currentNode(cursor) {
|
32 | let {
|
33 | element,
|
34 | nextSibling
|
35 | } = cursor;
|
36 | if (nextSibling === null) {
|
37 | return element.lastChild;
|
38 | } else {
|
39 | return nextSibling.previousSibling;
|
40 | }
|
41 | }
|
42 | class SerializeBuilder extends NewElementBuilder {
|
43 | serializeBlockDepth = 0;
|
44 | __openBlock() {
|
45 | let {
|
46 | tagName
|
47 | } = this.element;
|
48 | if (tagName !== 'TITLE' && tagName !== 'SCRIPT' && tagName !== 'STYLE') {
|
49 | let depth = this.serializeBlockDepth++;
|
50 | this.__appendComment(`%+b:${depth}%`);
|
51 | }
|
52 | super.__openBlock();
|
53 | }
|
54 | __closeBlock() {
|
55 | let {
|
56 | tagName
|
57 | } = this.element;
|
58 | super.__closeBlock();
|
59 | if (tagName !== 'TITLE' && tagName !== 'SCRIPT' && tagName !== 'STYLE') {
|
60 | let depth = --this.serializeBlockDepth;
|
61 | this.__appendComment(`%-b:${depth}%`);
|
62 | }
|
63 | }
|
64 | __appendHTML(html) {
|
65 | let {
|
66 | tagName
|
67 | } = this.element;
|
68 | if (tagName === 'TITLE' || tagName === 'SCRIPT' || tagName === 'STYLE') {
|
69 | return super.__appendHTML(html);
|
70 | }
|
71 |
|
72 |
|
73 | let first = this.__appendComment('%glmr%');
|
74 | if (tagName === 'TABLE') {
|
75 | let openIndex = html.indexOf('<');
|
76 | if (openIndex > -1) {
|
77 | let tr = html.slice(openIndex + 1, openIndex + 3);
|
78 | if (tr === 'tr') {
|
79 | html = `<tbody>${html}</tbody>`;
|
80 | }
|
81 | }
|
82 | }
|
83 | if (html === '') {
|
84 | this.__appendComment('% %');
|
85 | } else {
|
86 | super.__appendHTML(html);
|
87 | }
|
88 | let last = this.__appendComment('%glmr%');
|
89 | return new ConcreteBounds(this.element, first, last);
|
90 | }
|
91 | __appendText(string) {
|
92 | let {
|
93 | tagName
|
94 | } = this.element;
|
95 | let current = currentNode(this);
|
96 | if (tagName === 'TITLE' || tagName === 'SCRIPT' || tagName === 'STYLE') {
|
97 | return super.__appendText(string);
|
98 | } else if (string === '') {
|
99 | return this.__appendComment('% %');
|
100 | } else if (current && current.nodeType === TEXT_NODE) {
|
101 | this.__appendComment('%|%');
|
102 | }
|
103 | return super.__appendText(string);
|
104 | }
|
105 | closeElement() {
|
106 | if (NEEDS_EXTRA_CLOSE.has(this.element)) {
|
107 | NEEDS_EXTRA_CLOSE.delete(this.element);
|
108 | super.closeElement();
|
109 | }
|
110 | return super.closeElement();
|
111 | }
|
112 | openElement(tag) {
|
113 | if (tag === 'tr') {
|
114 | if (this.element.tagName !== 'TBODY' && this.element.tagName !== 'THEAD' && this.element.tagName !== 'TFOOT') {
|
115 | this.openElement('tbody');
|
116 |
|
117 |
|
118 |
|
119 |
|
120 | NEEDS_EXTRA_CLOSE.set(this.constructing, true);
|
121 | this.flushElement(null);
|
122 | }
|
123 | }
|
124 | return super.openElement(tag);
|
125 | }
|
126 | pushRemoteElement(element, cursorId, insertBefore = null) {
|
127 | let {
|
128 | dom
|
129 | } = this;
|
130 | let script = dom.createElement('script');
|
131 | script.setAttribute('glmr', cursorId);
|
132 | dom.insertBefore(element, script, insertBefore);
|
133 | return super.pushRemoteElement(element, cursorId, insertBefore);
|
134 | }
|
135 | }
|
136 | function serializeBuilder(env, cursor) {
|
137 | return SerializeBuilder.forInitialRender(env, cursor);
|
138 | }
|
139 |
|
140 | export { NodeDOMTreeConstruction, serializeBuilder };
|
141 |
|