@vertexvis/html-templates 0.12.0-canary.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 - Present Vertex Software, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,6 @@
1
+ # Vertex JS HTML Templating Library
2
+
3
+ ![npm](https://img.shields.io/npm/v/@vertexvis/html-templates)
4
+ ![npm (scoped with tag)](https://img.shields.io/npm/v/@vertexvis/html-templates/canary)
5
+
6
+ This project contains Vertex HTML templating libraries.
@@ -0,0 +1,35 @@
1
+ export interface Binding {
2
+ bind<T>(data: T): void;
3
+ }
4
+ export declare class CollectionBinding implements Binding {
5
+ private bindings;
6
+ constructor(bindings: Binding[]);
7
+ bind<T>(data: T): void;
8
+ }
9
+ export declare abstract class NodeBinding<N extends Node> implements Binding {
10
+ protected node: N;
11
+ protected expr: string;
12
+ protected constructor(node: N, expr: string);
13
+ abstract bind<T>(data: T): void;
14
+ }
15
+ export declare class TextNodeBinding extends NodeBinding<Node> {
16
+ constructor(node: Node, expr: string);
17
+ bind<T>(data: T): void;
18
+ }
19
+ export declare class AttributeBinding extends NodeBinding<Element> {
20
+ private attr;
21
+ constructor(node: Element, expr: string, attr: string);
22
+ bind<T>(data: T): void;
23
+ }
24
+ export declare class PropertyBinding extends NodeBinding<Element> {
25
+ private prop;
26
+ constructor(node: Element, expr: string, prop: string);
27
+ bind<T>(data: T): void;
28
+ }
29
+ export declare class EventHandlerBinding extends NodeBinding<Element> {
30
+ private eventName;
31
+ private disposable?;
32
+ constructor(node: Element, expr: string, eventName: string);
33
+ bind<T>(data: T): void;
34
+ }
35
+ export declare function generateBindings(node: Node): Binding[];
@@ -0,0 +1,321 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var tslib = require('tslib');
6
+
7
+ /**
8
+ * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
9
+ */
10
+ /**
11
+ * Lower case as a function.
12
+ */
13
+ function lowerCase(str) {
14
+ return str.toLowerCase();
15
+ }
16
+
17
+ // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
18
+ var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
19
+ // Remove all non-word characters.
20
+ var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
21
+ /**
22
+ * Normalize the string into something other libraries can manipulate easier.
23
+ */
24
+ function noCase(input, options) {
25
+ if (options === void 0) { options = {}; }
26
+ var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
27
+ var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
28
+ var start = 0;
29
+ var end = result.length;
30
+ // Trim the delimiter from around the output string.
31
+ while (result.charAt(start) === "\0")
32
+ start++;
33
+ while (result.charAt(end - 1) === "\0")
34
+ end--;
35
+ // Transform each token independently.
36
+ return result.slice(start, end).split("\0").map(transform).join(delimiter);
37
+ }
38
+ /**
39
+ * Replace `re` in the input string with the replacement value.
40
+ */
41
+ function replace(input, re, value) {
42
+ if (re instanceof RegExp)
43
+ return input.replace(re, value);
44
+ return re.reduce(function (input, re) { return input.replace(re, value); }, input);
45
+ }
46
+
47
+ function pascalCaseTransform(input, index) {
48
+ var firstChar = input.charAt(0);
49
+ var lowerChars = input.substr(1).toLowerCase();
50
+ if (index > 0 && firstChar >= "0" && firstChar <= "9") {
51
+ return "_" + firstChar + lowerChars;
52
+ }
53
+ return "" + firstChar.toUpperCase() + lowerChars;
54
+ }
55
+ function pascalCase(input, options) {
56
+ if (options === void 0) { options = {}; }
57
+ return noCase(input, tslib.__assign({ delimiter: "", transform: pascalCaseTransform }, options));
58
+ }
59
+
60
+ function camelCaseTransform(input, index) {
61
+ if (index === 0)
62
+ return input.toLowerCase();
63
+ return pascalCaseTransform(input, index);
64
+ }
65
+ function camelCase(input, options) {
66
+ if (options === void 0) { options = {}; }
67
+ return pascalCase(input, tslib.__assign({ transform: camelCaseTransform }, options));
68
+ }
69
+
70
+ const bindingRegEx = /{{(.+)}}/;
71
+ class CollectionBinding {
72
+ constructor(bindings) {
73
+ this.bindings = bindings;
74
+ }
75
+ bind(data) {
76
+ this.bindings.forEach((binding) => binding.bind(data));
77
+ }
78
+ }
79
+ class NodeBinding {
80
+ constructor(node, expr) {
81
+ this.node = node;
82
+ this.expr = expr;
83
+ }
84
+ }
85
+ class TextNodeBinding extends NodeBinding {
86
+ constructor(node, expr) {
87
+ super(node, expr);
88
+ }
89
+ bind(data) {
90
+ const newContent = replaceBindingString(data, this.expr);
91
+ if (newContent !== this.node.textContent) {
92
+ this.node.textContent = newContent;
93
+ }
94
+ }
95
+ }
96
+ class AttributeBinding extends NodeBinding {
97
+ constructor(node, expr, attr) {
98
+ super(node, expr);
99
+ this.attr = attr;
100
+ }
101
+ bind(data) {
102
+ const newValue = replaceBindingString(data, this.expr);
103
+ const oldValue = this.node.getAttribute(this.attr);
104
+ if (oldValue !== newValue) {
105
+ this.node.setAttribute(this.attr, newValue);
106
+ }
107
+ }
108
+ }
109
+ class PropertyBinding extends NodeBinding {
110
+ constructor(node, expr, prop) {
111
+ super(node, expr);
112
+ this.prop = prop;
113
+ }
114
+ bind(data) {
115
+ const newValue = replaceBinding(data, this.expr);
116
+ /* eslint-disable @typescript-eslint/no-explicit-any */
117
+ const oldValue = this.node[this.prop];
118
+ if (oldValue !== newValue) {
119
+ this.node[this.prop] = newValue;
120
+ }
121
+ /* eslint-enable @typescript-eslint/no-explicit-any */
122
+ }
123
+ }
124
+ class EventHandlerBinding extends NodeBinding {
125
+ constructor(node, expr, eventName) {
126
+ super(node, expr);
127
+ this.eventName = eventName;
128
+ }
129
+ bind(data) {
130
+ var _a;
131
+ const path = extractBindingPath(this.expr);
132
+ if (path != null) {
133
+ (_a = this.disposable) === null || _a === void 0 ? void 0 : _a.dispose();
134
+ const listener = getBindableValue(data, path, true);
135
+ this.node.addEventListener(this.eventName, listener);
136
+ this.disposable = {
137
+ dispose: () => {
138
+ this.node.removeEventListener(this.eventName, listener);
139
+ },
140
+ };
141
+ }
142
+ }
143
+ }
144
+ function generateBindings(node) {
145
+ const bindings = [];
146
+ if (node.nodeType === Node.ELEMENT_NODE) {
147
+ const el = node;
148
+ const bindableAttributes = getBindableAttributes(el);
149
+ bindableAttributes.forEach((attr) => {
150
+ if (attr.name.startsWith('event:')) {
151
+ const eventName = camelCase(attr.name.replace('event:', ''));
152
+ bindings.push(new EventHandlerBinding(el, attr.value, eventName));
153
+ }
154
+ else if (attr.name.startsWith('attr:')) {
155
+ bindings.push(new AttributeBinding(el, attr.value, attr.name.replace('attr:', '')));
156
+ }
157
+ else if (attr.name.startsWith('prop:')) {
158
+ const propName = camelCase(attr.name.replace('prop:', ''));
159
+ bindings.push(new PropertyBinding(el, attr.value, propName));
160
+ }
161
+ });
162
+ }
163
+ else if (node.nodeType === Node.TEXT_NODE &&
164
+ node.textContent != null &&
165
+ bindingRegEx.test(node.textContent)) {
166
+ bindings.push(new TextNodeBinding(node, node.textContent));
167
+ }
168
+ for (let i = 0; i < node.childNodes.length; i++) {
169
+ bindings.push(...generateBindings(node.childNodes[i]));
170
+ }
171
+ return bindings;
172
+ }
173
+ function getBindableAttributes(element) {
174
+ return Array.from(element.attributes).filter((attr) => bindingRegEx.test(attr.value));
175
+ }
176
+ function extractBindingPath(expr) {
177
+ const result = bindingRegEx.exec(expr);
178
+ return result != null ? result[1] : undefined;
179
+ }
180
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
181
+ function replaceBindingString(data, expr) {
182
+ const path = extractBindingPath(expr);
183
+ if (path != null) {
184
+ const value = getBindableValue(data, path, true);
185
+ return expr.replace(`{{${path}}}`, value === null || value === void 0 ? void 0 : value.toString());
186
+ }
187
+ else {
188
+ return expr;
189
+ }
190
+ }
191
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
192
+ function replaceBinding(data, expr) {
193
+ const path = extractBindingPath(expr);
194
+ if (path != null) {
195
+ const value = getBindableValue(data, path, true);
196
+ return value;
197
+ }
198
+ else {
199
+ return expr;
200
+ }
201
+ }
202
+ function getBindableValue(
203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
204
+ data, path, isHead = false
205
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
+ ) {
207
+ const [head, ...tail] = path.split('.');
208
+ if (isHead && tail.length === 0) {
209
+ return data;
210
+ }
211
+ else if (isHead && tail.length > 0) {
212
+ return getBindableValue(data, tail.join('.'), false);
213
+ }
214
+ else {
215
+ const value = data[head];
216
+ if (tail.length > 0) {
217
+ return getBindableValue(value, tail.join('.'), false);
218
+ }
219
+ else {
220
+ return value;
221
+ }
222
+ }
223
+ }
224
+
225
+ class ElementPool {
226
+ constructor(container, elementFactory) {
227
+ this.container = container;
228
+ this.elementFactory = elementFactory;
229
+ this.instanceMap = new Map();
230
+ this.elements = [];
231
+ }
232
+ swapHeadToTail(count) {
233
+ const sliced = this.elements.splice(0, count);
234
+ this.elements.splice(this.elements.length, 0, ...sliced);
235
+ return this.elements.concat();
236
+ }
237
+ swapTailToHead(count) {
238
+ const sliced = this.elements.splice(-count, count);
239
+ this.elements.splice(0, 0, ...sliced);
240
+ return this.elements.concat();
241
+ }
242
+ updateElements(count) {
243
+ const diff = count - this.elements.length;
244
+ if (diff > 0) {
245
+ for (let i = 0; i < diff; i++) {
246
+ this.createElement();
247
+ }
248
+ }
249
+ else {
250
+ for (let i = 0; i < -diff; i++) {
251
+ this.deleteElement();
252
+ }
253
+ }
254
+ return this.elements.concat();
255
+ }
256
+ updateData(f) {
257
+ this.elements.forEach((el, i) => {
258
+ const instance = this.instanceMap.get(el);
259
+ const data = f(i);
260
+ instance === null || instance === void 0 ? void 0 : instance.bindings.bind(data);
261
+ });
262
+ }
263
+ updateElementFactory(elementFactory) {
264
+ this.elementFactory = elementFactory;
265
+ this.updateElements(0);
266
+ }
267
+ iterateElements(f) {
268
+ this.elements.forEach((el, i) => {
269
+ const instance = this.instanceMap.get(el);
270
+ if (instance == null) {
271
+ throw new Error('Binding not found for element.');
272
+ }
273
+ f(el, instance.bindings, i);
274
+ });
275
+ }
276
+ createElement() {
277
+ const instance = this.elementFactory();
278
+ this.elements.push(instance.element);
279
+ this.instanceMap.set(instance.element, instance);
280
+ this.container.append(instance.element);
281
+ return instance;
282
+ }
283
+ deleteElement() {
284
+ const element = this.elements.pop();
285
+ if (element != null) {
286
+ this.instanceMap.delete(element);
287
+ element.remove();
288
+ }
289
+ }
290
+ }
291
+
292
+ function append(container, element, data) {
293
+ const bindings = new CollectionBinding(generateBindings(element));
294
+ bindings.bind(data);
295
+ container.appendChild(element);
296
+ const created = container.lastElementChild;
297
+ if (created != null) {
298
+ return { element: created, bindings };
299
+ }
300
+ else {
301
+ throw new Error('Failed to append element');
302
+ }
303
+ }
304
+ function generateInstanceFromTemplate(template) {
305
+ const fragment = template.content.cloneNode(true);
306
+ const element = fragment.firstElementChild;
307
+ const bindings = new CollectionBinding(generateBindings(fragment));
308
+ return { element, bindings };
309
+ }
310
+
311
+ exports.AttributeBinding = AttributeBinding;
312
+ exports.CollectionBinding = CollectionBinding;
313
+ exports.ElementPool = ElementPool;
314
+ exports.EventHandlerBinding = EventHandlerBinding;
315
+ exports.NodeBinding = NodeBinding;
316
+ exports.PropertyBinding = PropertyBinding;
317
+ exports.TextNodeBinding = TextNodeBinding;
318
+ exports.append = append;
319
+ exports.generateBindings = generateBindings;
320
+ exports.generateInstanceFromTemplate = generateInstanceFromTemplate;
321
+ //# sourceMappingURL=bundle.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.cjs.js","sources":["../../../node_modules/lower-case/dist.es2015/index.js","../../../node_modules/no-case/dist.es2015/index.js","../../../node_modules/pascal-case/dist.es2015/index.js","../../../node_modules/camel-case/dist.es2015/index.js","../src/binding.ts","../src/element-pool.ts","../src/templates.ts"],"sourcesContent":["/**\n * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt\n */\nvar SUPPORTED_LOCALE = {\n tr: {\n regexp: /\\u0130|\\u0049|\\u0049\\u0307/g,\n map: {\n İ: \"\\u0069\",\n I: \"\\u0131\",\n İ: \"\\u0069\",\n },\n },\n az: {\n regexp: /\\u0130/g,\n map: {\n İ: \"\\u0069\",\n I: \"\\u0131\",\n İ: \"\\u0069\",\n },\n },\n lt: {\n regexp: /\\u0049|\\u004A|\\u012E|\\u00CC|\\u00CD|\\u0128/g,\n map: {\n I: \"\\u0069\\u0307\",\n J: \"\\u006A\\u0307\",\n Į: \"\\u012F\\u0307\",\n Ì: \"\\u0069\\u0307\\u0300\",\n Í: \"\\u0069\\u0307\\u0301\",\n Ĩ: \"\\u0069\\u0307\\u0303\",\n },\n },\n};\n/**\n * Localized lower case.\n */\nexport function localeLowerCase(str, locale) {\n var lang = SUPPORTED_LOCALE[locale.toLowerCase()];\n if (lang)\n return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; }));\n return lowerCase(str);\n}\n/**\n * Lower case as a function.\n */\nexport function lowerCase(str) {\n return str.toLowerCase();\n}\n//# sourceMappingURL=index.js.map","import { lowerCase } from \"lower-case\";\n// Support camel case (\"camelCase\" -> \"camel Case\" and \"CAMELCase\" -> \"CAMEL Case\").\nvar DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];\n// Remove all non-word characters.\nvar DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;\n/**\n * Normalize the string into something other libraries can manipulate easier.\n */\nexport function noCase(input, options) {\n if (options === void 0) { options = {}; }\n var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? \" \" : _d;\n var result = replace(replace(input, splitRegexp, \"$1\\0$2\"), stripRegexp, \"\\0\");\n var start = 0;\n var end = result.length;\n // Trim the delimiter from around the output string.\n while (result.charAt(start) === \"\\0\")\n start++;\n while (result.charAt(end - 1) === \"\\0\")\n end--;\n // Transform each token independently.\n return result.slice(start, end).split(\"\\0\").map(transform).join(delimiter);\n}\n/**\n * Replace `re` in the input string with the replacement value.\n */\nfunction replace(input, re, value) {\n if (re instanceof RegExp)\n return input.replace(re, value);\n return re.reduce(function (input, re) { return input.replace(re, value); }, input);\n}\n//# sourceMappingURL=index.js.map","import { __assign } from \"tslib\";\nimport { noCase } from \"no-case\";\nexport function pascalCaseTransform(input, index) {\n var firstChar = input.charAt(0);\n var lowerChars = input.substr(1).toLowerCase();\n if (index > 0 && firstChar >= \"0\" && firstChar <= \"9\") {\n return \"_\" + firstChar + lowerChars;\n }\n return \"\" + firstChar.toUpperCase() + lowerChars;\n}\nexport function pascalCaseTransformMerge(input) {\n return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();\n}\nexport function pascalCase(input, options) {\n if (options === void 0) { options = {}; }\n return noCase(input, __assign({ delimiter: \"\", transform: pascalCaseTransform }, options));\n}\n//# sourceMappingURL=index.js.map","import { __assign } from \"tslib\";\nimport { pascalCase, pascalCaseTransform, pascalCaseTransformMerge, } from \"pascal-case\";\nexport function camelCaseTransform(input, index) {\n if (index === 0)\n return input.toLowerCase();\n return pascalCaseTransform(input, index);\n}\nexport function camelCaseTransformMerge(input, index) {\n if (index === 0)\n return input.toLowerCase();\n return pascalCaseTransformMerge(input);\n}\nexport function camelCase(input, options) {\n if (options === void 0) { options = {}; }\n return pascalCase(input, __assign({ transform: camelCaseTransform }, options));\n}\n//# sourceMappingURL=index.js.map","import { Disposable } from '@vertexvis/utils';\nimport { camelCase } from 'camel-case';\n\nconst bindingRegEx = /{{(.+)}}/;\n\nexport interface Binding {\n bind<T>(data: T): void;\n}\n\nexport class CollectionBinding implements Binding {\n public constructor(private bindings: Binding[]) {}\n\n public bind<T>(data: T): void {\n this.bindings.forEach((binding) => binding.bind(data));\n }\n}\n\nexport abstract class NodeBinding<N extends Node> implements Binding {\n protected constructor(protected node: N, protected expr: string) {}\n\n public abstract bind<T>(data: T): void;\n}\n\nexport class TextNodeBinding extends NodeBinding<Node> {\n public constructor(node: Node, expr: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const newContent = replaceBindingString(data, this.expr);\n if (newContent !== this.node.textContent) {\n this.node.textContent = newContent;\n }\n }\n}\n\nexport class AttributeBinding extends NodeBinding<Element> {\n public constructor(node: Element, expr: string, private attr: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const newValue = replaceBindingString(data, this.expr);\n const oldValue = this.node.getAttribute(this.attr);\n if (oldValue !== newValue) {\n this.node.setAttribute(this.attr, newValue);\n }\n }\n}\n\nexport class PropertyBinding extends NodeBinding<Element> {\n public constructor(node: Element, expr: string, private prop: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const newValue = replaceBinding(data, this.expr);\n /* eslint-disable @typescript-eslint/no-explicit-any */\n const oldValue = (this.node as any)[this.prop];\n if (oldValue !== newValue) {\n (this.node as any)[this.prop] = newValue;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n }\n}\n\nexport class EventHandlerBinding extends NodeBinding<Element> {\n private disposable?: Disposable;\n\n public constructor(node: Element, expr: string, private eventName: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const path = extractBindingPath(this.expr);\n if (path != null) {\n this.disposable?.dispose();\n\n const listener = getBindableValue(data, path, true);\n this.node.addEventListener(this.eventName, listener);\n\n this.disposable = {\n dispose: () => {\n this.node.removeEventListener(this.eventName, listener);\n },\n };\n }\n }\n}\n\nexport function generateBindings(node: Node): Binding[] {\n const bindings: Binding[] = [];\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n const bindableAttributes = getBindableAttributes(el);\n\n bindableAttributes.forEach((attr) => {\n if (attr.name.startsWith('event:')) {\n const eventName = camelCase(attr.name.replace('event:', ''));\n bindings.push(new EventHandlerBinding(el, attr.value, eventName));\n } else if (attr.name.startsWith('attr:')) {\n bindings.push(\n new AttributeBinding(el, attr.value, attr.name.replace('attr:', ''))\n );\n } else if (attr.name.startsWith('prop:')) {\n const propName = camelCase(attr.name.replace('prop:', ''));\n bindings.push(new PropertyBinding(el, attr.value, propName));\n }\n });\n } else if (\n node.nodeType === Node.TEXT_NODE &&\n node.textContent != null &&\n bindingRegEx.test(node.textContent)\n ) {\n bindings.push(new TextNodeBinding(node, node.textContent));\n }\n\n for (let i = 0; i < node.childNodes.length; i++) {\n bindings.push(...generateBindings(node.childNodes[i]));\n }\n\n return bindings;\n}\n\nfunction getBindableAttributes(element: Element): Attr[] {\n return Array.from(element.attributes).filter((attr) =>\n bindingRegEx.test(attr.value)\n );\n}\n\nfunction extractBindingPath(expr: string): string | undefined {\n const result = bindingRegEx.exec(expr);\n return result != null ? result[1] : undefined;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction replaceBindingString(data: Record<string, any>, expr: string): string {\n const path = extractBindingPath(expr);\n if (path != null) {\n const value = getBindableValue(data, path, true);\n return expr.replace(`{{${path}}}`, value?.toString());\n } else {\n return expr;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction replaceBinding(data: Record<string, any>, expr: string): any {\n const path = extractBindingPath(expr);\n if (path != null) {\n const value = getBindableValue(data, path, true);\n return value;\n } else {\n return expr;\n }\n}\n\nfunction getBindableValue(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data: Record<string, any>,\n path: string,\n isHead = false\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): any {\n const [head, ...tail] = path.split('.');\n if (isHead && tail.length === 0) {\n return data;\n } else if (isHead && tail.length > 0) {\n return getBindableValue(data, tail.join('.'), false);\n } else {\n const value = data[head];\n if (tail.length > 0) {\n return getBindableValue(value, tail.join('.'), false);\n } else {\n return value;\n }\n }\n}\n","import { Binding } from './binding';\nimport { InstancedTemplate } from './templates';\n\nexport type ElementFactory = () => InstancedTemplate<HTMLElement>;\n\nexport class ElementPool {\n private readonly elements: HTMLElement[];\n private instanceMap = new Map<HTMLElement, InstancedTemplate<HTMLElement>>();\n\n public constructor(\n private container: Element,\n private elementFactory: ElementFactory\n ) {\n this.elements = [];\n }\n\n public swapHeadToTail(count: number): HTMLElement[] {\n const sliced = this.elements.splice(0, count);\n this.elements.splice(this.elements.length, 0, ...sliced);\n return this.elements.concat();\n }\n\n public swapTailToHead(count: number): HTMLElement[] {\n const sliced = this.elements.splice(-count, count);\n this.elements.splice(0, 0, ...sliced);\n return this.elements.concat();\n }\n\n public updateElements(count: number): HTMLElement[] {\n const diff = count - this.elements.length;\n\n if (diff > 0) {\n for (let i = 0; i < diff; i++) {\n this.createElement();\n }\n } else {\n for (let i = 0; i < -diff; i++) {\n this.deleteElement();\n }\n }\n\n return this.elements.concat();\n }\n\n public updateData<D>(f: (index: number) => D): void {\n this.elements.forEach((el, i) => {\n const instance = this.instanceMap.get(el);\n const data = f(i);\n instance?.bindings.bind(data);\n });\n }\n\n public updateElementFactory(elementFactory: ElementFactory): void {\n this.elementFactory = elementFactory;\n this.updateElements(0);\n }\n\n public iterateElements(\n f: (element: HTMLElement, binding: Binding, index: number) => void\n ): void {\n this.elements.forEach((el, i) => {\n const instance = this.instanceMap.get(el);\n if (instance == null) {\n throw new Error('Binding not found for element.');\n }\n f(el, instance.bindings, i);\n });\n }\n\n private createElement(): InstancedTemplate<HTMLElement> {\n const instance = this.elementFactory();\n this.elements.push(instance.element);\n this.instanceMap.set(instance.element, instance);\n this.container.append(instance.element);\n return instance;\n }\n\n private deleteElement(): void {\n const element = this.elements.pop();\n if (element != null) {\n this.instanceMap.delete(element);\n element.remove();\n }\n }\n}\n","import { CollectionBinding, generateBindings } from './binding';\n\nexport interface InstancedTemplate<E extends Element> {\n element: E;\n bindings: CollectionBinding;\n}\n\nexport function append<E extends Element, D>(\n container: Element,\n element: E,\n data: D\n): InstancedTemplate<E> {\n const bindings = new CollectionBinding(generateBindings(element));\n bindings.bind(data);\n container.appendChild(element);\n const created = container.lastElementChild as E;\n if (created != null) {\n return { element: created, bindings };\n } else {\n throw new Error('Failed to append element');\n }\n}\n\nexport function generateInstanceFromTemplate(\n template: HTMLTemplateElement\n): InstancedTemplate<HTMLElement> {\n const fragment = template.content.cloneNode(true) as HTMLElement;\n const element = fragment.firstElementChild as HTMLElement;\n const bindings = new CollectionBinding(generateBindings(fragment));\n return { element, bindings };\n}\n"],"names":["__assign"],"mappings":"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"}
@@ -0,0 +1,308 @@
1
+ import { __assign } from 'tslib';
2
+
3
+ /**
4
+ * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
5
+ */
6
+ /**
7
+ * Lower case as a function.
8
+ */
9
+ function lowerCase(str) {
10
+ return str.toLowerCase();
11
+ }
12
+
13
+ // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
14
+ var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
15
+ // Remove all non-word characters.
16
+ var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
17
+ /**
18
+ * Normalize the string into something other libraries can manipulate easier.
19
+ */
20
+ function noCase(input, options) {
21
+ if (options === void 0) { options = {}; }
22
+ var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
23
+ var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
24
+ var start = 0;
25
+ var end = result.length;
26
+ // Trim the delimiter from around the output string.
27
+ while (result.charAt(start) === "\0")
28
+ start++;
29
+ while (result.charAt(end - 1) === "\0")
30
+ end--;
31
+ // Transform each token independently.
32
+ return result.slice(start, end).split("\0").map(transform).join(delimiter);
33
+ }
34
+ /**
35
+ * Replace `re` in the input string with the replacement value.
36
+ */
37
+ function replace(input, re, value) {
38
+ if (re instanceof RegExp)
39
+ return input.replace(re, value);
40
+ return re.reduce(function (input, re) { return input.replace(re, value); }, input);
41
+ }
42
+
43
+ function pascalCaseTransform(input, index) {
44
+ var firstChar = input.charAt(0);
45
+ var lowerChars = input.substr(1).toLowerCase();
46
+ if (index > 0 && firstChar >= "0" && firstChar <= "9") {
47
+ return "_" + firstChar + lowerChars;
48
+ }
49
+ return "" + firstChar.toUpperCase() + lowerChars;
50
+ }
51
+ function pascalCase(input, options) {
52
+ if (options === void 0) { options = {}; }
53
+ return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
54
+ }
55
+
56
+ function camelCaseTransform(input, index) {
57
+ if (index === 0)
58
+ return input.toLowerCase();
59
+ return pascalCaseTransform(input, index);
60
+ }
61
+ function camelCase(input, options) {
62
+ if (options === void 0) { options = {}; }
63
+ return pascalCase(input, __assign({ transform: camelCaseTransform }, options));
64
+ }
65
+
66
+ const bindingRegEx = /{{(.+)}}/;
67
+ class CollectionBinding {
68
+ constructor(bindings) {
69
+ this.bindings = bindings;
70
+ }
71
+ bind(data) {
72
+ this.bindings.forEach((binding) => binding.bind(data));
73
+ }
74
+ }
75
+ class NodeBinding {
76
+ constructor(node, expr) {
77
+ this.node = node;
78
+ this.expr = expr;
79
+ }
80
+ }
81
+ class TextNodeBinding extends NodeBinding {
82
+ constructor(node, expr) {
83
+ super(node, expr);
84
+ }
85
+ bind(data) {
86
+ const newContent = replaceBindingString(data, this.expr);
87
+ if (newContent !== this.node.textContent) {
88
+ this.node.textContent = newContent;
89
+ }
90
+ }
91
+ }
92
+ class AttributeBinding extends NodeBinding {
93
+ constructor(node, expr, attr) {
94
+ super(node, expr);
95
+ this.attr = attr;
96
+ }
97
+ bind(data) {
98
+ const newValue = replaceBindingString(data, this.expr);
99
+ const oldValue = this.node.getAttribute(this.attr);
100
+ if (oldValue !== newValue) {
101
+ this.node.setAttribute(this.attr, newValue);
102
+ }
103
+ }
104
+ }
105
+ class PropertyBinding extends NodeBinding {
106
+ constructor(node, expr, prop) {
107
+ super(node, expr);
108
+ this.prop = prop;
109
+ }
110
+ bind(data) {
111
+ const newValue = replaceBinding(data, this.expr);
112
+ /* eslint-disable @typescript-eslint/no-explicit-any */
113
+ const oldValue = this.node[this.prop];
114
+ if (oldValue !== newValue) {
115
+ this.node[this.prop] = newValue;
116
+ }
117
+ /* eslint-enable @typescript-eslint/no-explicit-any */
118
+ }
119
+ }
120
+ class EventHandlerBinding extends NodeBinding {
121
+ constructor(node, expr, eventName) {
122
+ super(node, expr);
123
+ this.eventName = eventName;
124
+ }
125
+ bind(data) {
126
+ var _a;
127
+ const path = extractBindingPath(this.expr);
128
+ if (path != null) {
129
+ (_a = this.disposable) === null || _a === void 0 ? void 0 : _a.dispose();
130
+ const listener = getBindableValue(data, path, true);
131
+ this.node.addEventListener(this.eventName, listener);
132
+ this.disposable = {
133
+ dispose: () => {
134
+ this.node.removeEventListener(this.eventName, listener);
135
+ },
136
+ };
137
+ }
138
+ }
139
+ }
140
+ function generateBindings(node) {
141
+ const bindings = [];
142
+ if (node.nodeType === Node.ELEMENT_NODE) {
143
+ const el = node;
144
+ const bindableAttributes = getBindableAttributes(el);
145
+ bindableAttributes.forEach((attr) => {
146
+ if (attr.name.startsWith('event:')) {
147
+ const eventName = camelCase(attr.name.replace('event:', ''));
148
+ bindings.push(new EventHandlerBinding(el, attr.value, eventName));
149
+ }
150
+ else if (attr.name.startsWith('attr:')) {
151
+ bindings.push(new AttributeBinding(el, attr.value, attr.name.replace('attr:', '')));
152
+ }
153
+ else if (attr.name.startsWith('prop:')) {
154
+ const propName = camelCase(attr.name.replace('prop:', ''));
155
+ bindings.push(new PropertyBinding(el, attr.value, propName));
156
+ }
157
+ });
158
+ }
159
+ else if (node.nodeType === Node.TEXT_NODE &&
160
+ node.textContent != null &&
161
+ bindingRegEx.test(node.textContent)) {
162
+ bindings.push(new TextNodeBinding(node, node.textContent));
163
+ }
164
+ for (let i = 0; i < node.childNodes.length; i++) {
165
+ bindings.push(...generateBindings(node.childNodes[i]));
166
+ }
167
+ return bindings;
168
+ }
169
+ function getBindableAttributes(element) {
170
+ return Array.from(element.attributes).filter((attr) => bindingRegEx.test(attr.value));
171
+ }
172
+ function extractBindingPath(expr) {
173
+ const result = bindingRegEx.exec(expr);
174
+ return result != null ? result[1] : undefined;
175
+ }
176
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
+ function replaceBindingString(data, expr) {
178
+ const path = extractBindingPath(expr);
179
+ if (path != null) {
180
+ const value = getBindableValue(data, path, true);
181
+ return expr.replace(`{{${path}}}`, value === null || value === void 0 ? void 0 : value.toString());
182
+ }
183
+ else {
184
+ return expr;
185
+ }
186
+ }
187
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
188
+ function replaceBinding(data, expr) {
189
+ const path = extractBindingPath(expr);
190
+ if (path != null) {
191
+ const value = getBindableValue(data, path, true);
192
+ return value;
193
+ }
194
+ else {
195
+ return expr;
196
+ }
197
+ }
198
+ function getBindableValue(
199
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
200
+ data, path, isHead = false
201
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
202
+ ) {
203
+ const [head, ...tail] = path.split('.');
204
+ if (isHead && tail.length === 0) {
205
+ return data;
206
+ }
207
+ else if (isHead && tail.length > 0) {
208
+ return getBindableValue(data, tail.join('.'), false);
209
+ }
210
+ else {
211
+ const value = data[head];
212
+ if (tail.length > 0) {
213
+ return getBindableValue(value, tail.join('.'), false);
214
+ }
215
+ else {
216
+ return value;
217
+ }
218
+ }
219
+ }
220
+
221
+ class ElementPool {
222
+ constructor(container, elementFactory) {
223
+ this.container = container;
224
+ this.elementFactory = elementFactory;
225
+ this.instanceMap = new Map();
226
+ this.elements = [];
227
+ }
228
+ swapHeadToTail(count) {
229
+ const sliced = this.elements.splice(0, count);
230
+ this.elements.splice(this.elements.length, 0, ...sliced);
231
+ return this.elements.concat();
232
+ }
233
+ swapTailToHead(count) {
234
+ const sliced = this.elements.splice(-count, count);
235
+ this.elements.splice(0, 0, ...sliced);
236
+ return this.elements.concat();
237
+ }
238
+ updateElements(count) {
239
+ const diff = count - this.elements.length;
240
+ if (diff > 0) {
241
+ for (let i = 0; i < diff; i++) {
242
+ this.createElement();
243
+ }
244
+ }
245
+ else {
246
+ for (let i = 0; i < -diff; i++) {
247
+ this.deleteElement();
248
+ }
249
+ }
250
+ return this.elements.concat();
251
+ }
252
+ updateData(f) {
253
+ this.elements.forEach((el, i) => {
254
+ const instance = this.instanceMap.get(el);
255
+ const data = f(i);
256
+ instance === null || instance === void 0 ? void 0 : instance.bindings.bind(data);
257
+ });
258
+ }
259
+ updateElementFactory(elementFactory) {
260
+ this.elementFactory = elementFactory;
261
+ this.updateElements(0);
262
+ }
263
+ iterateElements(f) {
264
+ this.elements.forEach((el, i) => {
265
+ const instance = this.instanceMap.get(el);
266
+ if (instance == null) {
267
+ throw new Error('Binding not found for element.');
268
+ }
269
+ f(el, instance.bindings, i);
270
+ });
271
+ }
272
+ createElement() {
273
+ const instance = this.elementFactory();
274
+ this.elements.push(instance.element);
275
+ this.instanceMap.set(instance.element, instance);
276
+ this.container.append(instance.element);
277
+ return instance;
278
+ }
279
+ deleteElement() {
280
+ const element = this.elements.pop();
281
+ if (element != null) {
282
+ this.instanceMap.delete(element);
283
+ element.remove();
284
+ }
285
+ }
286
+ }
287
+
288
+ function append(container, element, data) {
289
+ const bindings = new CollectionBinding(generateBindings(element));
290
+ bindings.bind(data);
291
+ container.appendChild(element);
292
+ const created = container.lastElementChild;
293
+ if (created != null) {
294
+ return { element: created, bindings };
295
+ }
296
+ else {
297
+ throw new Error('Failed to append element');
298
+ }
299
+ }
300
+ function generateInstanceFromTemplate(template) {
301
+ const fragment = template.content.cloneNode(true);
302
+ const element = fragment.firstElementChild;
303
+ const bindings = new CollectionBinding(generateBindings(fragment));
304
+ return { element, bindings };
305
+ }
306
+
307
+ export { AttributeBinding, CollectionBinding, ElementPool, EventHandlerBinding, NodeBinding, PropertyBinding, TextNodeBinding, append, generateBindings, generateInstanceFromTemplate };
308
+ //# sourceMappingURL=bundle.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.esm.js","sources":["../../../node_modules/lower-case/dist.es2015/index.js","../../../node_modules/no-case/dist.es2015/index.js","../../../node_modules/pascal-case/dist.es2015/index.js","../../../node_modules/camel-case/dist.es2015/index.js","../src/binding.ts","../src/element-pool.ts","../src/templates.ts"],"sourcesContent":["/**\n * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt\n */\nvar SUPPORTED_LOCALE = {\n tr: {\n regexp: /\\u0130|\\u0049|\\u0049\\u0307/g,\n map: {\n İ: \"\\u0069\",\n I: \"\\u0131\",\n İ: \"\\u0069\",\n },\n },\n az: {\n regexp: /\\u0130/g,\n map: {\n İ: \"\\u0069\",\n I: \"\\u0131\",\n İ: \"\\u0069\",\n },\n },\n lt: {\n regexp: /\\u0049|\\u004A|\\u012E|\\u00CC|\\u00CD|\\u0128/g,\n map: {\n I: \"\\u0069\\u0307\",\n J: \"\\u006A\\u0307\",\n Į: \"\\u012F\\u0307\",\n Ì: \"\\u0069\\u0307\\u0300\",\n Í: \"\\u0069\\u0307\\u0301\",\n Ĩ: \"\\u0069\\u0307\\u0303\",\n },\n },\n};\n/**\n * Localized lower case.\n */\nexport function localeLowerCase(str, locale) {\n var lang = SUPPORTED_LOCALE[locale.toLowerCase()];\n if (lang)\n return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; }));\n return lowerCase(str);\n}\n/**\n * Lower case as a function.\n */\nexport function lowerCase(str) {\n return str.toLowerCase();\n}\n//# sourceMappingURL=index.js.map","import { lowerCase } from \"lower-case\";\n// Support camel case (\"camelCase\" -> \"camel Case\" and \"CAMELCase\" -> \"CAMEL Case\").\nvar DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];\n// Remove all non-word characters.\nvar DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;\n/**\n * Normalize the string into something other libraries can manipulate easier.\n */\nexport function noCase(input, options) {\n if (options === void 0) { options = {}; }\n var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? \" \" : _d;\n var result = replace(replace(input, splitRegexp, \"$1\\0$2\"), stripRegexp, \"\\0\");\n var start = 0;\n var end = result.length;\n // Trim the delimiter from around the output string.\n while (result.charAt(start) === \"\\0\")\n start++;\n while (result.charAt(end - 1) === \"\\0\")\n end--;\n // Transform each token independently.\n return result.slice(start, end).split(\"\\0\").map(transform).join(delimiter);\n}\n/**\n * Replace `re` in the input string with the replacement value.\n */\nfunction replace(input, re, value) {\n if (re instanceof RegExp)\n return input.replace(re, value);\n return re.reduce(function (input, re) { return input.replace(re, value); }, input);\n}\n//# sourceMappingURL=index.js.map","import { __assign } from \"tslib\";\nimport { noCase } from \"no-case\";\nexport function pascalCaseTransform(input, index) {\n var firstChar = input.charAt(0);\n var lowerChars = input.substr(1).toLowerCase();\n if (index > 0 && firstChar >= \"0\" && firstChar <= \"9\") {\n return \"_\" + firstChar + lowerChars;\n }\n return \"\" + firstChar.toUpperCase() + lowerChars;\n}\nexport function pascalCaseTransformMerge(input) {\n return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();\n}\nexport function pascalCase(input, options) {\n if (options === void 0) { options = {}; }\n return noCase(input, __assign({ delimiter: \"\", transform: pascalCaseTransform }, options));\n}\n//# sourceMappingURL=index.js.map","import { __assign } from \"tslib\";\nimport { pascalCase, pascalCaseTransform, pascalCaseTransformMerge, } from \"pascal-case\";\nexport function camelCaseTransform(input, index) {\n if (index === 0)\n return input.toLowerCase();\n return pascalCaseTransform(input, index);\n}\nexport function camelCaseTransformMerge(input, index) {\n if (index === 0)\n return input.toLowerCase();\n return pascalCaseTransformMerge(input);\n}\nexport function camelCase(input, options) {\n if (options === void 0) { options = {}; }\n return pascalCase(input, __assign({ transform: camelCaseTransform }, options));\n}\n//# sourceMappingURL=index.js.map","import { Disposable } from '@vertexvis/utils';\nimport { camelCase } from 'camel-case';\n\nconst bindingRegEx = /{{(.+)}}/;\n\nexport interface Binding {\n bind<T>(data: T): void;\n}\n\nexport class CollectionBinding implements Binding {\n public constructor(private bindings: Binding[]) {}\n\n public bind<T>(data: T): void {\n this.bindings.forEach((binding) => binding.bind(data));\n }\n}\n\nexport abstract class NodeBinding<N extends Node> implements Binding {\n protected constructor(protected node: N, protected expr: string) {}\n\n public abstract bind<T>(data: T): void;\n}\n\nexport class TextNodeBinding extends NodeBinding<Node> {\n public constructor(node: Node, expr: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const newContent = replaceBindingString(data, this.expr);\n if (newContent !== this.node.textContent) {\n this.node.textContent = newContent;\n }\n }\n}\n\nexport class AttributeBinding extends NodeBinding<Element> {\n public constructor(node: Element, expr: string, private attr: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const newValue = replaceBindingString(data, this.expr);\n const oldValue = this.node.getAttribute(this.attr);\n if (oldValue !== newValue) {\n this.node.setAttribute(this.attr, newValue);\n }\n }\n}\n\nexport class PropertyBinding extends NodeBinding<Element> {\n public constructor(node: Element, expr: string, private prop: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const newValue = replaceBinding(data, this.expr);\n /* eslint-disable @typescript-eslint/no-explicit-any */\n const oldValue = (this.node as any)[this.prop];\n if (oldValue !== newValue) {\n (this.node as any)[this.prop] = newValue;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n }\n}\n\nexport class EventHandlerBinding extends NodeBinding<Element> {\n private disposable?: Disposable;\n\n public constructor(node: Element, expr: string, private eventName: string) {\n super(node, expr);\n }\n\n public bind<T>(data: T): void {\n const path = extractBindingPath(this.expr);\n if (path != null) {\n this.disposable?.dispose();\n\n const listener = getBindableValue(data, path, true);\n this.node.addEventListener(this.eventName, listener);\n\n this.disposable = {\n dispose: () => {\n this.node.removeEventListener(this.eventName, listener);\n },\n };\n }\n }\n}\n\nexport function generateBindings(node: Node): Binding[] {\n const bindings: Binding[] = [];\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n const bindableAttributes = getBindableAttributes(el);\n\n bindableAttributes.forEach((attr) => {\n if (attr.name.startsWith('event:')) {\n const eventName = camelCase(attr.name.replace('event:', ''));\n bindings.push(new EventHandlerBinding(el, attr.value, eventName));\n } else if (attr.name.startsWith('attr:')) {\n bindings.push(\n new AttributeBinding(el, attr.value, attr.name.replace('attr:', ''))\n );\n } else if (attr.name.startsWith('prop:')) {\n const propName = camelCase(attr.name.replace('prop:', ''));\n bindings.push(new PropertyBinding(el, attr.value, propName));\n }\n });\n } else if (\n node.nodeType === Node.TEXT_NODE &&\n node.textContent != null &&\n bindingRegEx.test(node.textContent)\n ) {\n bindings.push(new TextNodeBinding(node, node.textContent));\n }\n\n for (let i = 0; i < node.childNodes.length; i++) {\n bindings.push(...generateBindings(node.childNodes[i]));\n }\n\n return bindings;\n}\n\nfunction getBindableAttributes(element: Element): Attr[] {\n return Array.from(element.attributes).filter((attr) =>\n bindingRegEx.test(attr.value)\n );\n}\n\nfunction extractBindingPath(expr: string): string | undefined {\n const result = bindingRegEx.exec(expr);\n return result != null ? result[1] : undefined;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction replaceBindingString(data: Record<string, any>, expr: string): string {\n const path = extractBindingPath(expr);\n if (path != null) {\n const value = getBindableValue(data, path, true);\n return expr.replace(`{{${path}}}`, value?.toString());\n } else {\n return expr;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction replaceBinding(data: Record<string, any>, expr: string): any {\n const path = extractBindingPath(expr);\n if (path != null) {\n const value = getBindableValue(data, path, true);\n return value;\n } else {\n return expr;\n }\n}\n\nfunction getBindableValue(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data: Record<string, any>,\n path: string,\n isHead = false\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): any {\n const [head, ...tail] = path.split('.');\n if (isHead && tail.length === 0) {\n return data;\n } else if (isHead && tail.length > 0) {\n return getBindableValue(data, tail.join('.'), false);\n } else {\n const value = data[head];\n if (tail.length > 0) {\n return getBindableValue(value, tail.join('.'), false);\n } else {\n return value;\n }\n }\n}\n","import { Binding } from './binding';\nimport { InstancedTemplate } from './templates';\n\nexport type ElementFactory = () => InstancedTemplate<HTMLElement>;\n\nexport class ElementPool {\n private readonly elements: HTMLElement[];\n private instanceMap = new Map<HTMLElement, InstancedTemplate<HTMLElement>>();\n\n public constructor(\n private container: Element,\n private elementFactory: ElementFactory\n ) {\n this.elements = [];\n }\n\n public swapHeadToTail(count: number): HTMLElement[] {\n const sliced = this.elements.splice(0, count);\n this.elements.splice(this.elements.length, 0, ...sliced);\n return this.elements.concat();\n }\n\n public swapTailToHead(count: number): HTMLElement[] {\n const sliced = this.elements.splice(-count, count);\n this.elements.splice(0, 0, ...sliced);\n return this.elements.concat();\n }\n\n public updateElements(count: number): HTMLElement[] {\n const diff = count - this.elements.length;\n\n if (diff > 0) {\n for (let i = 0; i < diff; i++) {\n this.createElement();\n }\n } else {\n for (let i = 0; i < -diff; i++) {\n this.deleteElement();\n }\n }\n\n return this.elements.concat();\n }\n\n public updateData<D>(f: (index: number) => D): void {\n this.elements.forEach((el, i) => {\n const instance = this.instanceMap.get(el);\n const data = f(i);\n instance?.bindings.bind(data);\n });\n }\n\n public updateElementFactory(elementFactory: ElementFactory): void {\n this.elementFactory = elementFactory;\n this.updateElements(0);\n }\n\n public iterateElements(\n f: (element: HTMLElement, binding: Binding, index: number) => void\n ): void {\n this.elements.forEach((el, i) => {\n const instance = this.instanceMap.get(el);\n if (instance == null) {\n throw new Error('Binding not found for element.');\n }\n f(el, instance.bindings, i);\n });\n }\n\n private createElement(): InstancedTemplate<HTMLElement> {\n const instance = this.elementFactory();\n this.elements.push(instance.element);\n this.instanceMap.set(instance.element, instance);\n this.container.append(instance.element);\n return instance;\n }\n\n private deleteElement(): void {\n const element = this.elements.pop();\n if (element != null) {\n this.instanceMap.delete(element);\n element.remove();\n }\n }\n}\n","import { CollectionBinding, generateBindings } from './binding';\n\nexport interface InstancedTemplate<E extends Element> {\n element: E;\n bindings: CollectionBinding;\n}\n\nexport function append<E extends Element, D>(\n container: Element,\n element: E,\n data: D\n): InstancedTemplate<E> {\n const bindings = new CollectionBinding(generateBindings(element));\n bindings.bind(data);\n container.appendChild(element);\n const created = container.lastElementChild as E;\n if (created != null) {\n return { element: created, bindings };\n } else {\n throw new Error('Failed to append element');\n }\n}\n\nexport function generateInstanceFromTemplate(\n template: HTMLTemplateElement\n): InstancedTemplate<HTMLElement> {\n const fragment = template.content.cloneNode(true) as HTMLElement;\n const element = fragment.firstElementChild as HTMLElement;\n const bindings = new CollectionBinding(generateBindings(fragment));\n return { element, bindings };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { Binding } from './binding';
2
+ import { InstancedTemplate } from './templates';
3
+ export declare type ElementFactory = () => InstancedTemplate<HTMLElement>;
4
+ export declare class ElementPool {
5
+ private container;
6
+ private elementFactory;
7
+ private readonly elements;
8
+ private instanceMap;
9
+ constructor(container: Element, elementFactory: ElementFactory);
10
+ swapHeadToTail(count: number): HTMLElement[];
11
+ swapTailToHead(count: number): HTMLElement[];
12
+ updateElements(count: number): HTMLElement[];
13
+ updateData<D>(f: (index: number) => D): void;
14
+ updateElementFactory(elementFactory: ElementFactory): void;
15
+ iterateElements(f: (element: HTMLElement, binding: Binding, index: number) => void): void;
16
+ private createElement;
17
+ private deleteElement;
18
+ }
@@ -0,0 +1,3 @@
1
+ export * from './binding';
2
+ export * from './element-pool';
3
+ export * from './templates';
@@ -0,0 +1,7 @@
1
+ import { CollectionBinding } from './binding';
2
+ export interface InstancedTemplate<E extends Element> {
3
+ element: E;
4
+ bindings: CollectionBinding;
5
+ }
6
+ export declare function append<E extends Element, D>(container: Element, element: E, data: D): InstancedTemplate<E>;
7
+ export declare function generateInstanceFromTemplate(template: HTMLTemplateElement): InstancedTemplate<HTMLElement>;
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@vertexvis/html-templates",
3
+ "version": "0.12.0-canary.24",
4
+ "description": "HTML templating library for Viewer SDK.",
5
+ "license": "MIT",
6
+ "author": "Vertex Developers <support@vertexvis.com> (https://developer.vertexvis.com)",
7
+ "homepage": "https://github.com/Vertexvis/vertex-web-sdk#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Vertexvis/vertex-web-sdk.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/Vertexvis/vertex-web-sdk/issues"
14
+ },
15
+ "main": "./dist/bundle.cjs.js",
16
+ "module": "./dist/bundle.esm.js",
17
+ "typings": "./dist/index.d.ts",
18
+ "browser": "./dist/browser.esm.js",
19
+ "publishConfig": {
20
+ "registry": "https://registry.npmjs.org",
21
+ "access": "public"
22
+ },
23
+ "sideEffects": false,
24
+ "files": [
25
+ "dist/*",
26
+ "!dist/**/__tests__"
27
+ ],
28
+ "scripts": {
29
+ "clean": "rm -fr ./dist && mkdir ./dist",
30
+ "prebuild": "yarn clean",
31
+ "build": "rollup --config ./rollup.config.js",
32
+ "format": "yarn lint --fix",
33
+ "lint": "eslint --ext .ts,.tsx,.js,.jsx --ignore-path ../../.gitignore .",
34
+ "start": "jest --watch",
35
+ "test": "jest",
36
+ "test:coverage": "yarn test --coverage"
37
+ },
38
+ "dependencies": {
39
+ "@vertexvis/utils": "^0.12.0-canary.24"
40
+ },
41
+ "devDependencies": {
42
+ "@types/jest": "^26.0.20",
43
+ "@types/lodash.isequal": "^4.5.5",
44
+ "@types/uuid": "^8.3.0",
45
+ "@vertexvis/eslint-config-vertexvis-typescript": "^0.4.1",
46
+ "@vertexvis/jest-config-vertexvis": "^0.5.3",
47
+ "@vertexwebsdk/build": "^0.12.0-canary.24",
48
+ "eslint": "^7.20.0",
49
+ "jest": "^26.6.3",
50
+ "rollup": "^2.58.0",
51
+ "ts-jest": "^26.5.2",
52
+ "tslib": "^2.1.0",
53
+ "typescript": "^4.4.4"
54
+ },
55
+ "peerDependencies": {
56
+ "tslib": ">=2.1.0"
57
+ },
58
+ "gitHead": "5e3514d77b124400fe7d051ca5da0b2e77743fe8"
59
+ }