|
1 | 1 | <script> |
2 | 2 | const LokiHtmlReplacer = { |
3 | 3 | replace(root, incomingHTML) { |
4 | | - if (!(root instanceof Element)) { |
5 | | - throw new TypeError('`root` must be an Element'); |
| 4 | + if (root.hasAttribute('x-ignore')) { |
| 5 | + return; |
6 | 6 | } |
7 | | - if (root.hasAttribute('x-ignore')) return; |
8 | | - |
9 | | - const incomingFrag = this._parseHTML(incomingHTML); |
10 | 7 |
|
| 8 | + const incomingFrag = this.parseHTML(incomingHTML); |
11 | 9 | const existingSkips = root.querySelectorAll('[x-ignore]'); |
| 10 | + |
12 | 11 | existingSkips.forEach(oldEl => { |
13 | 12 | const ancestor = oldEl.parentElement?.closest('[x-ignore]'); |
14 | | - if (ancestor && ancestor !== oldEl) return; |
15 | | - |
16 | | - const key = oldEl.getAttribute('x-ignore'); |
17 | | - let counterpart = null; |
| 13 | + if (ancestor && ancestor !== oldEl) { |
| 14 | + return; |
| 15 | + } |
18 | 16 |
|
19 | | - if (key && key.length > 0) { |
20 | | - counterpart = incomingFrag.querySelector(`[x-ignore="${this._cssEscape(key)}"]`); |
21 | | - } else { |
22 | | - const path = this._pathFromRoot(root, oldEl); |
23 | | - counterpart = this._nodeByPath(incomingFrag, path); |
24 | | - if (counterpart && !(counterpart instanceof Element && counterpart.hasAttribute('x-ignore'))) { |
25 | | - counterpart = null; |
26 | | - } |
| 17 | + const path = this.pathFromRoot(root, oldEl); |
| 18 | + let counterpart = this.nodeByPath(incomingFrag, path); |
| 19 | + if (counterpart && !(counterpart instanceof Element && counterpart.hasAttribute('x-ignore'))) { |
| 20 | + counterpart = null; |
27 | 21 | } |
28 | 22 |
|
29 | 23 | if (counterpart) { |
|
34 | 28 | root.replaceChildren(...incomingFrag.childNodes); |
35 | 29 | }, |
36 | 30 |
|
37 | | - _parseHTML(html) { |
| 31 | + parseHTML(html) { |
38 | 32 | const tpl = document.createElement('template'); |
39 | 33 | tpl.innerHTML = String(html ?? '').trim(); |
40 | 34 | return tpl.content; |
41 | 35 | }, |
42 | 36 |
|
43 | | - _cssEscape(ident) { |
44 | | - if (window.CSS && typeof window.CSS.escape === 'function') { |
45 | | - return window.CSS.escape(ident); |
46 | | - } |
47 | | - return String(ident) |
48 | | - .replace(/[\0-\x1F\x7F]/g, '\uFFFD') |
49 | | - .replace(/(^-?\d)|[^a-zA-Z0-9_\u00A0-\uFFFF-]/g, (ch, d) => |
50 | | - d ? `\\3${d} ` : `\\${ch}` |
51 | | - ); |
52 | | - }, |
53 | | - |
54 | | - _pathFromRoot(rootEl, el) { |
| 37 | + pathFromRoot(rootEl, el) { |
55 | 38 | const path = []; |
56 | 39 | let cur = el; |
57 | 40 | while (cur && cur !== rootEl) { |
|
69 | 52 | return path; |
70 | 53 | }, |
71 | 54 |
|
72 | | - _nodeByPath(rootLike, path) { |
| 55 | + nodeByPath(rootLike, path) { |
73 | 56 | let node = rootLike; |
74 | 57 | for (const idx of path) { |
75 | 58 | const children = (node instanceof DocumentFragment) |
|
0 commit comments