@microsoft/fast-element 1.10.5 → 2.0.0-beta.10
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/.eslintrc.json +1 -12
- package/CHANGELOG.json +629 -6
- package/CHANGELOG.md +152 -5
- package/dist/dts/components/attributes.d.ts +14 -1
- package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +32 -32
- package/dist/dts/components/fast-definitions.d.ts +51 -11
- package/dist/dts/components/fast-element.d.ts +18 -23
- package/dist/dts/context.d.ts +157 -0
- package/dist/{esm/observation/behavior.js → dts/debug.d.ts} +0 -0
- package/dist/dts/di/di.d.ts +899 -0
- package/dist/dts/index.d.ts +17 -16
- package/dist/dts/index.debug.d.ts +2 -0
- package/dist/dts/index.rollup.d.ts +2 -0
- package/dist/dts/index.rollup.debug.d.ts +3 -0
- package/dist/dts/interfaces.d.ts +176 -0
- package/dist/dts/metadata.d.ts +25 -0
- package/dist/dts/observation/arrays.d.ts +207 -0
- package/dist/dts/observation/notifier.d.ts +18 -18
- package/dist/dts/observation/observable.d.ts +117 -34
- package/dist/dts/observation/update-queue.d.ts +40 -0
- package/dist/dts/pending-task.d.ts +20 -0
- package/dist/dts/platform.d.ts +23 -66
- package/dist/dts/polyfills.d.ts +8 -0
- package/dist/dts/state/exports.d.ts +3 -0
- package/dist/dts/state/reactive.d.ts +8 -0
- package/dist/dts/state/state.d.ts +141 -0
- package/dist/dts/state/visitor.d.ts +6 -0
- package/dist/dts/state/watch.d.ts +10 -0
- package/dist/dts/styles/css-directive.d.ts +44 -6
- package/dist/dts/styles/css.d.ts +19 -3
- package/dist/dts/styles/element-styles.d.ts +49 -63
- package/dist/dts/styles/host.d.ts +68 -0
- package/dist/dts/templating/binding-signal.d.ts +21 -0
- package/dist/dts/templating/binding-two-way.d.ts +39 -0
- package/dist/dts/templating/binding.d.ts +101 -70
- package/dist/dts/templating/children.d.ts +18 -15
- package/dist/dts/templating/compiler.d.ts +46 -28
- package/dist/dts/templating/dom.d.ts +41 -0
- package/dist/dts/templating/html-directive.d.ts +239 -45
- package/dist/dts/templating/markup.d.ts +48 -0
- package/dist/dts/templating/node-observation.d.ts +45 -30
- package/dist/dts/templating/ref.d.ts +6 -20
- package/dist/dts/templating/render.d.ts +272 -0
- package/dist/dts/templating/repeat.d.ts +36 -33
- package/dist/dts/templating/slotted.d.ts +13 -14
- package/dist/dts/templating/template.d.ts +28 -22
- package/dist/dts/templating/view.d.ts +82 -24
- package/dist/dts/templating/when.d.ts +3 -3
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +4 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/{tsdoc-metadata.json → dts/tsdoc-metadata.json} +1 -1
- package/dist/dts/utilities.d.ts +22 -0
- package/dist/esm/components/attributes.js +38 -28
- package/dist/esm/components/{controller.js → element-controller.js} +150 -140
- package/dist/esm/components/fast-definitions.js +48 -46
- package/dist/esm/components/fast-element.js +31 -12
- package/dist/esm/context.js +163 -0
- package/dist/esm/debug.js +61 -0
- package/dist/esm/di/di.js +1435 -0
- package/dist/esm/index.debug.js +2 -0
- package/dist/esm/index.js +20 -14
- package/dist/esm/index.rollup.debug.js +3 -0
- package/dist/esm/index.rollup.js +2 -0
- package/dist/esm/interfaces.js +12 -1
- package/dist/esm/metadata.js +60 -0
- package/dist/esm/observation/arrays.js +570 -0
- package/dist/esm/observation/notifier.js +27 -35
- package/dist/esm/observation/observable.js +116 -149
- package/dist/esm/observation/update-queue.js +67 -0
- package/dist/esm/pending-task.js +16 -0
- package/dist/esm/platform.js +60 -42
- package/dist/esm/polyfills.js +85 -0
- package/dist/esm/state/exports.js +3 -0
- package/dist/esm/state/reactive.js +34 -0
- package/dist/esm/state/state.js +148 -0
- package/dist/esm/state/visitor.js +28 -0
- package/dist/esm/state/watch.js +36 -0
- package/dist/esm/styles/css-directive.js +29 -13
- package/dist/esm/styles/css.js +29 -42
- package/dist/esm/styles/element-styles.js +79 -104
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/templating/binding-signal.js +83 -0
- package/dist/esm/templating/binding-two-way.js +103 -0
- package/dist/esm/templating/binding.js +189 -159
- package/dist/esm/templating/children.js +33 -23
- package/dist/esm/templating/compiler.js +258 -152
- package/dist/esm/templating/dom.js +49 -0
- package/dist/esm/templating/html-directive.js +193 -36
- package/dist/esm/templating/markup.js +75 -0
- package/dist/esm/templating/node-observation.js +51 -45
- package/dist/esm/templating/ref.js +8 -25
- package/dist/esm/templating/render.js +391 -0
- package/dist/esm/templating/repeat.js +83 -79
- package/dist/esm/templating/slotted.js +23 -20
- package/dist/esm/templating/template.js +51 -93
- package/dist/esm/templating/view.js +125 -46
- package/dist/esm/templating/when.js +6 -4
- package/dist/esm/testing/exports.js +3 -0
- package/dist/esm/testing/fakes.js +76 -0
- package/dist/esm/testing/fixture.js +86 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/utilities.js +44 -0
- package/dist/fast-element.api.json +12153 -5373
- package/dist/fast-element.d.ts +1448 -696
- package/dist/fast-element.debug.js +4107 -0
- package/dist/fast-element.debug.min.js +1 -0
- package/dist/fast-element.js +3817 -4029
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +2814 -0
- package/docs/api-report.md +567 -254
- package/docs/fast-element-2-changes.md +15 -0
- package/karma.conf.cjs +6 -17
- package/package.json +76 -15
- package/dist/dts/dom.d.ts +0 -112
- package/dist/dts/observation/array-change-records.d.ts +0 -48
- package/dist/dts/observation/array-observer.d.ts +0 -9
- package/dist/dts/observation/behavior.d.ts +0 -19
- package/dist/esm/dom.js +0 -207
- package/dist/esm/observation/array-change-records.js +0 -326
- package/dist/esm/observation/array-observer.js +0 -177
|
@@ -1,186 +1,292 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
release() {
|
|
18
|
-
/* eslint-disable-next-line @typescript-eslint/no-this-alias */
|
|
19
|
-
sharedContext = this;
|
|
20
|
-
}
|
|
21
|
-
static borrow(directives) {
|
|
22
|
-
const shareable = sharedContext || new CompilationContext();
|
|
23
|
-
shareable.directives = directives;
|
|
24
|
-
shareable.reset();
|
|
25
|
-
sharedContext = null;
|
|
26
|
-
return shareable;
|
|
1
|
+
import { isFunction, isString } from "../interfaces.js";
|
|
2
|
+
import { FAST } from "../platform.js";
|
|
3
|
+
import { Parser } from "./markup.js";
|
|
4
|
+
import { HTMLBindingDirective, oneTime } from "./binding.js";
|
|
5
|
+
import { Aspect } from "./html-directive.js";
|
|
6
|
+
import { HTMLView } from "./view.js";
|
|
7
|
+
const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
|
|
8
|
+
const descriptorCache = {};
|
|
9
|
+
// used to prevent creating lots of objects just to track node and index while compiling
|
|
10
|
+
const next = {
|
|
11
|
+
index: 0,
|
|
12
|
+
node: null,
|
|
13
|
+
};
|
|
14
|
+
function tryWarn(name) {
|
|
15
|
+
if (!name.startsWith("fast-")) {
|
|
16
|
+
FAST.warn(1204 /* Message.hostBindingWithoutHost */, { name });
|
|
27
17
|
}
|
|
28
18
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
const warningHost = new Proxy(document.createElement("div"), {
|
|
20
|
+
get(target, property) {
|
|
21
|
+
tryWarn(property);
|
|
22
|
+
const value = Reflect.get(target, property);
|
|
23
|
+
return isFunction(value) ? value.bind(target) : value;
|
|
24
|
+
},
|
|
25
|
+
set(target, property, value) {
|
|
26
|
+
tryWarn(property);
|
|
27
|
+
return Reflect.set(target, property, value);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
class CompilationContext {
|
|
31
|
+
constructor(fragment, directives) {
|
|
32
|
+
this.fragment = fragment;
|
|
33
|
+
this.directives = directives;
|
|
34
|
+
this.proto = null;
|
|
35
|
+
this.nodeIds = new Set();
|
|
36
|
+
this.descriptors = {};
|
|
37
|
+
this.factories = [];
|
|
32
38
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
for (let i = 0; i < partCount; ++i) {
|
|
45
|
-
output += finalParts[i](scope, context);
|
|
46
|
-
}
|
|
47
|
-
return output;
|
|
48
|
-
};
|
|
49
|
-
const directive = new HTMLBindingDirective(binding);
|
|
50
|
-
directive.targetName = targetName;
|
|
51
|
-
return directive;
|
|
52
|
-
}
|
|
53
|
-
const interpolationEndLength = _interpolationEnd.length;
|
|
54
|
-
function parseContent(context, value) {
|
|
55
|
-
const valueParts = value.split(_interpolationStart);
|
|
56
|
-
if (valueParts.length === 1) {
|
|
57
|
-
return null;
|
|
39
|
+
addFactory(factory, parentId, nodeId, targetIndex) {
|
|
40
|
+
if (!this.nodeIds.has(nodeId)) {
|
|
41
|
+
this.nodeIds.add(nodeId);
|
|
42
|
+
this.addTargetDescriptor(parentId, nodeId, targetIndex);
|
|
43
|
+
}
|
|
44
|
+
factory.nodeId = nodeId;
|
|
45
|
+
this.factories.push(factory);
|
|
46
|
+
}
|
|
47
|
+
freeze() {
|
|
48
|
+
this.proto = Object.create(null, this.descriptors);
|
|
49
|
+
return this;
|
|
58
50
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
literal = current;
|
|
51
|
+
addTargetDescriptor(parentId, targetId, targetIndex) {
|
|
52
|
+
const descriptors = this.descriptors;
|
|
53
|
+
if (targetId === "r" || // root
|
|
54
|
+
targetId === "h" || // host
|
|
55
|
+
descriptors[targetId]) {
|
|
56
|
+
return;
|
|
66
57
|
}
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
if (!descriptors[parentId]) {
|
|
59
|
+
const index = parentId.lastIndexOf(".");
|
|
60
|
+
const grandparentId = parentId.substring(0, index);
|
|
61
|
+
const childIndex = parseInt(parentId.substring(index + 1));
|
|
62
|
+
this.addTargetDescriptor(grandparentId, parentId, childIndex);
|
|
63
|
+
}
|
|
64
|
+
let descriptor = descriptorCache[targetId];
|
|
65
|
+
if (!descriptor) {
|
|
66
|
+
const field = `_${targetId}`;
|
|
67
|
+
descriptorCache[targetId] = descriptor = {
|
|
68
|
+
get() {
|
|
69
|
+
var _a;
|
|
70
|
+
return ((_a = this[field]) !== null && _a !== void 0 ? _a : (this[field] = this[parentId].childNodes[targetIndex]));
|
|
71
|
+
},
|
|
72
|
+
};
|
|
71
73
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
descriptors[targetId] = descriptor;
|
|
75
|
+
}
|
|
76
|
+
createView(hostBindingTarget) {
|
|
77
|
+
const fragment = this.fragment.cloneNode(true);
|
|
78
|
+
const targets = Object.create(this.proto);
|
|
79
|
+
targets.r = fragment;
|
|
80
|
+
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget : warningHost;
|
|
81
|
+
for (const id of this.nodeIds) {
|
|
82
|
+
targets[id]; // trigger locator
|
|
74
83
|
}
|
|
84
|
+
return new HTMLView(fragment, this.factories, targets);
|
|
75
85
|
}
|
|
76
|
-
return bindingParts;
|
|
77
86
|
}
|
|
78
|
-
function compileAttributes(context, node, includeBasicValues = false) {
|
|
87
|
+
function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBasicValues = false) {
|
|
79
88
|
const attributes = node.attributes;
|
|
89
|
+
const directives = context.directives;
|
|
80
90
|
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
81
91
|
const attr = attributes[i];
|
|
82
92
|
const attrValue = attr.value;
|
|
83
|
-
const parseResult =
|
|
93
|
+
const parseResult = Parser.parse(attrValue, directives);
|
|
84
94
|
let result = null;
|
|
85
95
|
if (parseResult === null) {
|
|
86
96
|
if (includeBasicValues) {
|
|
87
|
-
result = new HTMLBindingDirective(() => attrValue);
|
|
88
|
-
result
|
|
97
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
98
|
+
Aspect.assign(result, attr.name);
|
|
89
99
|
}
|
|
90
100
|
}
|
|
91
101
|
else {
|
|
92
|
-
|
|
102
|
+
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
103
|
+
result = Compiler.aggregate(parseResult);
|
|
93
104
|
}
|
|
94
105
|
if (result !== null) {
|
|
95
106
|
node.removeAttributeNode(attr);
|
|
96
107
|
i--;
|
|
97
108
|
ii--;
|
|
98
|
-
context.addFactory(result);
|
|
109
|
+
context.addFactory(result, parentId, nodeId, nodeIndex);
|
|
99
110
|
}
|
|
100
111
|
}
|
|
101
112
|
}
|
|
102
|
-
function compileContent(context, node,
|
|
103
|
-
const parseResult =
|
|
104
|
-
if (parseResult
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
114
|
+
const parseResult = Parser.parse(node.textContent, context.directives);
|
|
115
|
+
if (parseResult === null) {
|
|
116
|
+
next.node = node.nextSibling;
|
|
117
|
+
next.index = nodeIndex + 1;
|
|
118
|
+
return next;
|
|
119
|
+
}
|
|
120
|
+
let currentNode;
|
|
121
|
+
let lastNode = (currentNode = node);
|
|
122
|
+
for (let i = 0, ii = parseResult.length; i < ii; ++i) {
|
|
123
|
+
const currentPart = parseResult[i];
|
|
124
|
+
if (i !== 0) {
|
|
125
|
+
nodeIndex++;
|
|
126
|
+
nodeId = targetIdFrom(parentId, nodeIndex);
|
|
127
|
+
currentNode = lastNode.parentNode.insertBefore(document.createTextNode(""), lastNode.nextSibling);
|
|
128
|
+
}
|
|
129
|
+
if (isString(currentPart)) {
|
|
130
|
+
currentNode.textContent = currentPart;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
currentNode.textContent = " ";
|
|
134
|
+
Aspect.assign(currentPart);
|
|
135
|
+
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
123
136
|
}
|
|
124
|
-
|
|
137
|
+
lastNode = currentNode;
|
|
138
|
+
}
|
|
139
|
+
next.index = nodeIndex + 1;
|
|
140
|
+
next.node = lastNode.nextSibling;
|
|
141
|
+
return next;
|
|
142
|
+
}
|
|
143
|
+
function compileChildren(context, parent, parentId) {
|
|
144
|
+
let nodeIndex = 0;
|
|
145
|
+
let childNode = parent.firstChild;
|
|
146
|
+
while (childNode) {
|
|
147
|
+
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
148
|
+
const result = compileNode(context, parentId, childNode, nodeIndex);
|
|
149
|
+
childNode = result.node;
|
|
150
|
+
nodeIndex = result.index;
|
|
125
151
|
}
|
|
126
152
|
}
|
|
153
|
+
function compileNode(context, parentId, node, nodeIndex) {
|
|
154
|
+
const nodeId = targetIdFrom(parentId, nodeIndex);
|
|
155
|
+
switch (node.nodeType) {
|
|
156
|
+
case 1: // element node
|
|
157
|
+
compileAttributes(context, parentId, node, nodeId, nodeIndex);
|
|
158
|
+
compileChildren(context, node, nodeId);
|
|
159
|
+
break;
|
|
160
|
+
case 3: // text node
|
|
161
|
+
return compileContent(context, node, parentId, nodeId, nodeIndex);
|
|
162
|
+
case 8: // comment
|
|
163
|
+
const parts = Parser.parse(node.data, context.directives);
|
|
164
|
+
if (parts !== null) {
|
|
165
|
+
context.addFactory(
|
|
166
|
+
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
167
|
+
Compiler.aggregate(parts), parentId, nodeId, nodeIndex);
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
next.index = nodeIndex + 1;
|
|
172
|
+
next.node = node.nextSibling;
|
|
173
|
+
return next;
|
|
174
|
+
}
|
|
175
|
+
function isMarker(node, directives) {
|
|
176
|
+
return (node &&
|
|
177
|
+
node.nodeType == 8 &&
|
|
178
|
+
Parser.parse(node.data, directives) !== null);
|
|
179
|
+
}
|
|
180
|
+
const templateTag = "TEMPLATE";
|
|
181
|
+
const policyOptions = { createHTML: html => html };
|
|
182
|
+
let htmlPolicy = globalThis.trustedTypes
|
|
183
|
+
? globalThis.trustedTypes.createPolicy("fast-html", policyOptions)
|
|
184
|
+
: policyOptions;
|
|
185
|
+
const fastHTMLPolicy = htmlPolicy;
|
|
127
186
|
/**
|
|
128
|
-
*
|
|
129
|
-
* result which include a cloneable DocumentFragment and factories capable
|
|
130
|
-
* of attaching runtime behavior to nodes within the fragment.
|
|
131
|
-
* @param template - The template to compile.
|
|
132
|
-
* @param directives - The directives referenced by the template.
|
|
133
|
-
* @remarks
|
|
134
|
-
* The template that is provided for compilation is altered in-place
|
|
135
|
-
* and cannot be compiled again. If the original template must be preserved,
|
|
136
|
-
* it is recommended that you clone the original and pass the clone to this API.
|
|
187
|
+
* Common APIs related to compilation.
|
|
137
188
|
* @public
|
|
138
189
|
*/
|
|
139
|
-
export
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
context.targetIndex++;
|
|
151
|
-
switch (node.nodeType) {
|
|
152
|
-
case 1: // element node
|
|
153
|
-
compileAttributes(context, node);
|
|
154
|
-
break;
|
|
155
|
-
case 3: // text node
|
|
156
|
-
compileContent(context, node, walker);
|
|
157
|
-
break;
|
|
158
|
-
case 8: // comment
|
|
159
|
-
if (DOM.isMarker(node)) {
|
|
160
|
-
context.addFactory(directives[DOM.extractDirectiveIndexFromMarker(node)]);
|
|
161
|
-
}
|
|
190
|
+
export const Compiler = {
|
|
191
|
+
/**
|
|
192
|
+
* Sets the HTML trusted types policy used by the compiler.
|
|
193
|
+
* @param policy - The policy to set for HTML.
|
|
194
|
+
* @remarks
|
|
195
|
+
* This API can only be called once, for security reasons. It should be
|
|
196
|
+
* called by the application developer at the start of their program.
|
|
197
|
+
*/
|
|
198
|
+
setHTMLPolicy(policy) {
|
|
199
|
+
if (htmlPolicy !== fastHTMLPolicy) {
|
|
200
|
+
throw FAST.error(1201 /* Message.onlySetHTMLPolicyOnce */);
|
|
162
201
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
202
|
+
htmlPolicy = policy;
|
|
203
|
+
},
|
|
204
|
+
/**
|
|
205
|
+
* Compiles a template and associated directives into a compilation
|
|
206
|
+
* result which can be used to create views.
|
|
207
|
+
* @param html - The html string or template element to compile.
|
|
208
|
+
* @param directives - The directives referenced by the template.
|
|
209
|
+
* @remarks
|
|
210
|
+
* The template that is provided for compilation is altered in-place
|
|
211
|
+
* and cannot be compiled again. If the original template must be preserved,
|
|
212
|
+
* it is recommended that you clone the original and pass the clone to this API.
|
|
213
|
+
* @public
|
|
214
|
+
*/
|
|
215
|
+
compile(html, directives) {
|
|
216
|
+
let template;
|
|
217
|
+
if (isString(html)) {
|
|
218
|
+
template = document.createElement(templateTag);
|
|
219
|
+
template.innerHTML = htmlPolicy.createHTML(html);
|
|
220
|
+
const fec = template.content.firstElementChild;
|
|
221
|
+
if (fec !== null && fec.tagName === templateTag) {
|
|
222
|
+
template = fec;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
template = html;
|
|
227
|
+
}
|
|
228
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1111864
|
|
229
|
+
const fragment = document.adoptNode(template.content);
|
|
230
|
+
const context = new CompilationContext(fragment, directives);
|
|
231
|
+
compileAttributes(context, "", template, /* host */ "h", 0, true);
|
|
232
|
+
if (
|
|
233
|
+
// If the first node in a fragment is a marker, that means it's an unstable first node,
|
|
234
|
+
// because something like a when, repeat, etc. could add nodes before the marker.
|
|
235
|
+
// To mitigate this, we insert a stable first node. However, if we insert a node,
|
|
236
|
+
// that will alter the result of the TreeWalker. So, we also need to offset the target index.
|
|
237
|
+
isMarker(fragment.firstChild, directives) ||
|
|
238
|
+
// Or if there is only one node and a directive, it means the template's content
|
|
239
|
+
// is *only* the directive. In that case, HTMLView.dispose() misses any nodes inserted by
|
|
240
|
+
// the directive. Inserting a new node ensures proper disposal of nodes added by the directive.
|
|
241
|
+
(fragment.childNodes.length === 1 && Object.keys(directives).length > 0)) {
|
|
242
|
+
fragment.insertBefore(document.createComment(""), fragment.firstChild);
|
|
243
|
+
}
|
|
244
|
+
compileChildren(context, fragment, /* root */ "r");
|
|
245
|
+
next.node = null; // prevent leaks
|
|
246
|
+
return context.freeze();
|
|
247
|
+
},
|
|
248
|
+
/**
|
|
249
|
+
* Sets the default compilation strategy that will be used by the ViewTemplate whenever
|
|
250
|
+
* it needs to compile a view preprocessed with the html template function.
|
|
251
|
+
* @param strategy - The compilation strategy to use when compiling templates.
|
|
252
|
+
*/
|
|
253
|
+
setDefaultStrategy(strategy) {
|
|
254
|
+
this.compile = strategy;
|
|
255
|
+
},
|
|
256
|
+
/**
|
|
257
|
+
* Aggregates an array of strings and directives into a single directive.
|
|
258
|
+
* @param parts - A heterogeneous array of static strings interspersed with
|
|
259
|
+
* directives.
|
|
260
|
+
* @returns A single inline directive that aggregates the behavior of all the parts.
|
|
261
|
+
*/
|
|
262
|
+
aggregate(parts) {
|
|
263
|
+
if (parts.length === 1) {
|
|
264
|
+
return parts[0];
|
|
265
|
+
}
|
|
266
|
+
let sourceAspect;
|
|
267
|
+
let binding;
|
|
268
|
+
let isVolatile = false;
|
|
269
|
+
const partCount = parts.length;
|
|
270
|
+
const finalParts = parts.map((x) => {
|
|
271
|
+
if (isString(x)) {
|
|
272
|
+
return () => x;
|
|
273
|
+
}
|
|
274
|
+
sourceAspect = x.sourceAspect || sourceAspect;
|
|
275
|
+
binding = x.dataBinding || binding;
|
|
276
|
+
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
277
|
+
return x.dataBinding.evaluate;
|
|
278
|
+
});
|
|
279
|
+
const expression = (scope, context) => {
|
|
280
|
+
let output = "";
|
|
281
|
+
for (let i = 0; i < partCount; ++i) {
|
|
282
|
+
output += finalParts[i](scope, context);
|
|
283
|
+
}
|
|
284
|
+
return output;
|
|
285
|
+
};
|
|
286
|
+
binding.evaluate = expression;
|
|
287
|
+
binding.isVolatile = isVolatile;
|
|
288
|
+
const directive = new HTMLBindingDirective(binding);
|
|
289
|
+
Aspect.assign(directive, sourceAspect);
|
|
290
|
+
return directive;
|
|
291
|
+
},
|
|
292
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Updates } from "../observation/update-queue.js";
|
|
2
|
+
/**
|
|
3
|
+
* Common DOM APIs.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export const DOM = Object.freeze({
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated
|
|
9
|
+
* Use Updates.enqueue().
|
|
10
|
+
*/
|
|
11
|
+
queueUpdate: Updates.enqueue,
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated
|
|
14
|
+
* Use Updates.next()
|
|
15
|
+
*/
|
|
16
|
+
nextUpdate: Updates.next,
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated
|
|
19
|
+
* Use Updates.process()
|
|
20
|
+
*/
|
|
21
|
+
processUpdates: Updates.process,
|
|
22
|
+
/**
|
|
23
|
+
* Sets an attribute value on an element.
|
|
24
|
+
* @param element - The element to set the attribute value on.
|
|
25
|
+
* @param attributeName - The attribute name to set.
|
|
26
|
+
* @param value - The value of the attribute to set.
|
|
27
|
+
* @remarks
|
|
28
|
+
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
29
|
+
* it is set to the provided value using the standard `setAttribute` API.
|
|
30
|
+
*/
|
|
31
|
+
setAttribute(element, attributeName, value) {
|
|
32
|
+
value === null || value === undefined
|
|
33
|
+
? element.removeAttribute(attributeName)
|
|
34
|
+
: element.setAttribute(attributeName, value);
|
|
35
|
+
},
|
|
36
|
+
/**
|
|
37
|
+
* Sets a boolean attribute value.
|
|
38
|
+
* @param element - The element to set the boolean attribute value on.
|
|
39
|
+
* @param attributeName - The attribute name to set.
|
|
40
|
+
* @param value - The value of the attribute to set.
|
|
41
|
+
* @remarks
|
|
42
|
+
* If the value is true, the attribute is added; otherwise it is removed.
|
|
43
|
+
*/
|
|
44
|
+
setBooleanAttribute(element, attributeName, value) {
|
|
45
|
+
value
|
|
46
|
+
? element.setAttribute(attributeName, "")
|
|
47
|
+
: element.removeAttribute(attributeName);
|
|
48
|
+
},
|
|
49
|
+
});
|