UNPKG

2.4 kBJavaScriptView Raw
1import { isWhitespace, walk } from "./helpers.js"
2
3export function parseEach(node) {
4 let each = node.getAttribute("each")
5 let m = each?.match(/(.+)\s+in\s+(.+)/)
6 if (!m) {
7 if (!each) return m
8 return {
9 path: each.trim(),
10 key: node.getAttribute("key"),
11 }
12 }
13 let [_, left, right] = m
14 let parts = left.match(/\(([^\)]+)\)/)
15 let [a, b] = (parts ? parts[1].split(",") : [left]).map((v) => v.trim())
16
17 return {
18 path: right.trim(),
19 identifier: b ? b : a,
20 index: b ? a : b,
21 key: node.getAttribute("key"),
22 }
23}
24
25const getBlockSize = (template) => {
26 let i = 0
27 walk(template.content?.firstChild || template.firstChild, () => i++, false)
28 return i
29}
30
31const nextNonWhitespaceSibling = (node) => {
32 return isWhitespace(node.nextSibling)
33 ? nextNonWhitespaceSibling(node.nextSibling)
34 : node.nextSibling
35}
36
37const getBlockFragments = (template, numBlocks) => {
38 let blockSize = getBlockSize(template)
39
40 let r = []
41 if (numBlocks) {
42 while (numBlocks--) {
43 let f = document.createDocumentFragment()
44 let n = blockSize
45 while (n--) {
46 f.appendChild(nextNonWhitespaceSibling(template))
47 }
48 r.push(f)
49 }
50 }
51 return r
52}
53
54export const getBlocks = (template) => {
55 let numBlocks = template.getAttribute("length")
56 let blockSize = getBlockSize(template)
57 let r = []
58 let node = template
59 if (numBlocks) {
60 while (numBlocks--) {
61 let f = []
62 let n = blockSize
63 while (n--) {
64 node = nextNonWhitespaceSibling(node)
65 f.push(node)
66 }
67 r.push(f)
68 }
69 }
70 return r
71}
72
73export const compareKeyedLists = (key, a = [], b = []) => {
74 let delta = b.map(([k, item]) =>
75 !key ? (k in a ? k : -1) : a.findIndex(([_, v]) => v[key] === item[key])
76 )
77 if (a.length !== b.length || !delta.every((a, b) => a === b)) return delta
78}
79
80function lastChild(v) {
81 return (v.nodeType === v.DOCUMENT_FRAGMENT_NODE && v.lastChild) || v
82}
83
84export const updateList = (template, delta, entries, createListItem) => {
85 let n = template.getAttribute("length") || 0
86 let blocks = getBlockFragments(template, n)
87 let t = template
88
89 delta.forEach((i, newIndex) => {
90 let frag =
91 i === -1
92 ? createListItem(entries[newIndex][1], entries[newIndex][0])
93 : blocks[i]
94 let x = lastChild(frag)
95 t.after(frag)
96 t = x
97 })
98
99 template.setAttribute("length", delta.length)
100}