@webtides/element-js 1.0.0-alpha.4 → 1.0.0-alpha.5
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/docs/README.md +174 -0
- package/docs/concepts/classes.md +167 -0
- package/docs/concepts/hierarchy.md +61 -0
- package/docs/concepts/lifecycle.md +45 -0
- package/docs/concepts/reactivity.md +14 -0
- package/docs/features/computed-properties.md +28 -0
- package/docs/features/dependency-injection-context-protocol.md +132 -0
- package/docs/features/events.md +155 -0
- package/docs/features/global-styles.md +131 -0
- package/docs/features/methods.md +34 -0
- package/docs/features/properties.md +56 -0
- package/docs/features/refs.md +47 -0
- package/docs/features/renderless.md +70 -0
- package/docs/features/store.md +143 -0
- package/docs/features/styles.md +169 -0
- package/docs/features/templates.md +308 -0
- package/docs/features/watch.md +54 -0
- package/docs/getting-started/upgrade-to-v1.md +243 -0
- package/docs/guide/guide.md +112 -0
- package/package.json +15 -19
- package/src/BaseElement.js +6 -6
- package/src/dom-parts/AttributePart.js +1 -0
- package/src/dom-parts/ChildNodePart.js +2 -0
- package/src/dom-parts/NodePart.js +1 -0
- package/src/dom-parts/TemplateResult.js +2 -0
- package/src/dom-parts/directives.js +5 -3
- package/dist/index.js +0 -1554
- package/dist/index.js.map +0 -7
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Upgrade Guide
|
|
2
|
+
|
|
3
|
+
Upgrading from `element-js` v0.x to v1.0
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`element-js` v1.0 is the first major version since it was released in June 2020. The biggest change is a new and custom DOM Parts renderer that allows us to get rid of `lit-html` making it a dependency free library finally.
|
|
8
|
+
|
|
9
|
+
We only have a couple of breaking changes and a few removed deprecations. The deprecations have been logged to the console for a while now and we hope that most of them should not be there anymore. And the breaking changes should be mostly changed import paths. So it should only be a matter of copy and paste.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Install element-js v1.0
|
|
14
|
+
|
|
15
|
+
Update `element-js` using npm:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npm install element-js@latest
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Support for IE 11 has been dropped
|
|
22
|
+
|
|
23
|
+
Prior to v1.0, we tried our best to make sure features we included in `element-js` worked in IE 11 whenever possible. If you need to support IE 11, we recommend continuing to use `element-js` v0.x until you no longer need to support IE.
|
|
24
|
+
|
|
25
|
+
## Added `afterUpdate` lifecycle hook upon connecting the elements
|
|
26
|
+
|
|
27
|
+
`element-js` will now also trigger the `afterUpdate` hook right after the `connected` hook. This is to reduce the cases where you had to do the same things in `connected` and `afterUpdate`. You can now remove those duplicate calls from the `connected` hook.
|
|
28
|
+
|
|
29
|
+
## Change import paths for main exports
|
|
30
|
+
|
|
31
|
+
> This only applies if you used the vanilla renderer. For the default `lit-html` renderer you do not need to change the import paths.
|
|
32
|
+
|
|
33
|
+
Change everything that was imported from:
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
import { TemplateElement, html } from '@webtides/element-js/src/renderer/vanilla';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
to:
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
import { TemplateElement, html } from '@webtides/element-js';
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This must be done for the following classes and functions:
|
|
46
|
+
|
|
47
|
+
- BaseElement
|
|
48
|
+
- StyledElement
|
|
49
|
+
- TemplateElement
|
|
50
|
+
- Store
|
|
51
|
+
- html
|
|
52
|
+
- toString
|
|
53
|
+
- defineElement
|
|
54
|
+
- i18n
|
|
55
|
+
|
|
56
|
+
## Change import paths for directives
|
|
57
|
+
|
|
58
|
+
If you used any directives you must change their import paths as well.
|
|
59
|
+
|
|
60
|
+
For the vanilla renderer we previously had them here:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
import { unsafeHTML } from '@webtides/element-js/src/renderer/vanilla/util/directives.js';
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
And for the `lit-html` renderer you had to import the directives from `lit`:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
In both cases you must now change the imports to our new directives:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
import { unsafeHTML } from '@webtides/element-js/src/dom-parts/directives';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Removed childListUpdate option from constructor options
|
|
79
|
+
|
|
80
|
+
We removed the deprecated `BaseElement` constructor option `childListUpdate`. Please use the "mutationObserverOptions" dictionary instead.
|
|
81
|
+
|
|
82
|
+
Change:
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
class MyElement extends BaseElement {
|
|
86
|
+
constructor() {
|
|
87
|
+
super({ childListUpdate: true });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
to:
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
class MyElement extends BaseElement {
|
|
96
|
+
constructor() {
|
|
97
|
+
super({ mutationObserverOptions: { childList: true } });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For more information on how to configure `mutationObserverOptions` see the docs.
|
|
103
|
+
|
|
104
|
+
## Removed the `hooks` map
|
|
105
|
+
|
|
106
|
+
We removed the `hooks` map in the `BaseElement`. Using the hooks() map for lifecycle hooks is not possible anymore! Please overwrite the existing lifecycle hook functions. See the docs for more info.
|
|
107
|
+
|
|
108
|
+
Change:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
class MyElement extends BaseElement {
|
|
112
|
+
hooks() {
|
|
113
|
+
return {
|
|
114
|
+
connected: () => {},
|
|
115
|
+
beforeUpdate: () => {},
|
|
116
|
+
afterUpdate: () => {}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
to:
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
class MyElement extends BaseElement {
|
|
126
|
+
connected() {}
|
|
127
|
+
beforeUpdate() {}
|
|
128
|
+
afterUpdate() {}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Removed the `computed` map
|
|
133
|
+
|
|
134
|
+
We removed the `computed` map in the `BaseElement`. Using the computed() map for computed properties is is not possible anymore! Please use regular JS getters and return the computed value. See the docs for more info.
|
|
135
|
+
|
|
136
|
+
Change:
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
class MyElement extends BaseElement {
|
|
140
|
+
firstName = 'John';
|
|
141
|
+
lastName = 'Doe';
|
|
142
|
+
|
|
143
|
+
computed() {
|
|
144
|
+
return {
|
|
145
|
+
name: () => `${this.firstName} ${this.lastName}`
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
to:
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
class MyElement extends BaseElement {
|
|
155
|
+
firstName = 'John';
|
|
156
|
+
lastName = 'Doe';
|
|
157
|
+
|
|
158
|
+
get name() {
|
|
159
|
+
return `${this.firstName} ${this.lastName}`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Removed the `i18n` helper function
|
|
165
|
+
|
|
166
|
+
We removed the `i18n` helper function. It was a very simple and naive implementation for translating strings in templates. We would recommend to use a more sophisticated i18n solution.
|
|
167
|
+
|
|
168
|
+
If you still need the same functionality, you can simply add the following function to your code and change the imports accordingly:
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
/**
|
|
172
|
+
* Retrieves a translated key from a dictionary on the window object
|
|
173
|
+
* Example: ${i18n('CustomElement.buttonLabel', 'Label')}
|
|
174
|
+
* @param {string} key - to be translated
|
|
175
|
+
* @param {string} fallback - to be used if key is not defined
|
|
176
|
+
* @return {string} - String of the translated key or fallback or original key
|
|
177
|
+
*/
|
|
178
|
+
export function i18n(key, fallback) {
|
|
179
|
+
try {
|
|
180
|
+
const translations = window.elementjs.i18n();
|
|
181
|
+
if (translations[key] === undefined) {
|
|
182
|
+
throw 'Translation Missing';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return translations[key];
|
|
186
|
+
} catch (err) {
|
|
187
|
+
if (fallback) return fallback;
|
|
188
|
+
else return key;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Changed default options for the `dispatch` helper function
|
|
194
|
+
|
|
195
|
+
We changed the default options when using the `dispatch` helper function. `bubbles`, `cancelable` and `composed` will now be `true` by default.
|
|
196
|
+
|
|
197
|
+
Also, we changed the parameter signature. Instead of expecting the tree boolean values as parameters after the data value, we now expect an `options` object that is in line with the `CustomEventInit` options for the `CustomEvent` class. This is not a breaking change, and we will still evaluate the old parameter list for now. It will finally be removed in v2.0.
|
|
198
|
+
|
|
199
|
+
We would recommend that you start using the new syntax. Change this:
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
this.dispatch('custom-event', 'foo', true, true, true);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
to (if you wanted every parameter to be `true` before):
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
this.dispatch('custom-event', 'foo');
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
or this (if you had different option values):
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
this.dispatch('custom-event', 'foo', {
|
|
215
|
+
bubbles: true,
|
|
216
|
+
cancelable: false,
|
|
217
|
+
composed: true
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Changed adoptGlobalStyles
|
|
222
|
+
|
|
223
|
+
We changed adopting global styles to include ALL global styles now. Previously only one inline <style> with the ID of '#globalStyles' would be adopted. For more information see the docs. We think that this is the behaviour that one would actually want.
|
|
224
|
+
|
|
225
|
+
If you still need it to be the way it was before, please change the `adoptGlobalStyles` option value from:
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
export class ShadowElement extends TemplateElement {
|
|
229
|
+
constructor() {
|
|
230
|
+
super({ adoptGlobalStyles: true });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
to:
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
export class ShadowElement extends TemplateElement {
|
|
239
|
+
constructor() {
|
|
240
|
+
super({ adoptGlobalStyles: '#globalStyles' });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
|
|
2
|
+
## Guides/Tooling
|
|
3
|
+
|
|
4
|
+
### Frontend Stack
|
|
5
|
+
|
|
6
|
+
### Bundling/Publishing
|
|
7
|
+
|
|
8
|
+
### Design System
|
|
9
|
+
|
|
10
|
+
### Style Guide / Best Practices
|
|
11
|
+
|
|
12
|
+
This is an element style guide created and enforced for the purpose of standardizing elements and file structures.
|
|
13
|
+
|
|
14
|
+
#### File structure
|
|
15
|
+
|
|
16
|
+
- One element per file.
|
|
17
|
+
- One element per directory. Though it may make sense to group similar elements into the same directory, we've found it'
|
|
18
|
+
s easier to consume and document elements when each one has its own directory.
|
|
19
|
+
- Implementation (.js) and styles (.css) of an element should live in the same directory.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
├── card-element
|
|
25
|
+
│ ├── card-element.css
|
|
26
|
+
│ ├── card-element.js
|
|
27
|
+
│ └── test
|
|
28
|
+
│ ├── card-element.e2e.js
|
|
29
|
+
│ └── card-element.spec.js
|
|
30
|
+
├── card-content
|
|
31
|
+
│ ├── card-content.css
|
|
32
|
+
│ └── card-content.js
|
|
33
|
+
├── card-title
|
|
34
|
+
│ ├── card-title.css
|
|
35
|
+
│ └── card-title.js
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Naming
|
|
39
|
+
|
|
40
|
+
##### Name
|
|
41
|
+
|
|
42
|
+
Elements are not actions, they are conceptually "things". It is better to use nouns, instead of verbs, such us: "
|
|
43
|
+
animation" instead of "animating". "input", "tab", "nav", "menu" are some examples.
|
|
44
|
+
|
|
45
|
+
##### -element postfix
|
|
46
|
+
|
|
47
|
+
The naming has a major role when you are creating a collection of elements intended to be used across different
|
|
48
|
+
projects. Web Components are not scoped because they are globally declared within the page, which means a "unique" name
|
|
49
|
+
is needed to prevent collisions.
|
|
50
|
+
Additionally, web components are required to contain a "-" dash within the tag name. When using the first section to
|
|
51
|
+
namespace your components - everything will look the same, and it will be hard to distinguish elements.
|
|
52
|
+
|
|
53
|
+
DO NOT do this:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
company-card
|
|
57
|
+
company-card-header
|
|
58
|
+
company-card-title
|
|
59
|
+
company-card-content
|
|
60
|
+
company-card-footer
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Instead, use -element for elements with a single noun.
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
card-element
|
|
67
|
+
card-header
|
|
68
|
+
card-title
|
|
69
|
+
card-content
|
|
70
|
+
card-footer
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
##### Modifiers
|
|
74
|
+
|
|
75
|
+
When several elements are related and/or coupled, it is a good idea to share the name, and then add different modifiers,
|
|
76
|
+
for example:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
menu-element
|
|
80
|
+
menu-controller
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
card-element
|
|
85
|
+
card-header
|
|
86
|
+
card-content
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
##### Element (JS class)
|
|
90
|
+
|
|
91
|
+
The name of the ES6 class of the element should reflect the file name, and the html tag name.
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
export class ButtonElement extends BaseElement {
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
customElements.define('button-element', ButtonElement);
|
|
98
|
+
|
|
99
|
+
export class MenuElement extends BaseElement {
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
customElements.define('menu-element', MenuElement);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Code organization
|
|
106
|
+
|
|
107
|
+
##### Newspaper Metaphor from The Robert C. Martin's _Clean Code_
|
|
108
|
+
|
|
109
|
+
> The source file should be organized like a newspaper article, with the highest level summary at the top, and more and
|
|
110
|
+
> more details further down. Functions called from the top function come directly below it, and so on down to the lowest
|
|
111
|
+
> level, and most detailed functions at the bottom. This is a good way to organize the source code, even though IDE:s make
|
|
112
|
+
> the location of functions less important, since it is so easy to navigate in and out of them.
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webtides/element-js",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.5",
|
|
4
4
|
"module": "index.js",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"/
|
|
8
|
+
"/docs",
|
|
9
9
|
"/src",
|
|
10
10
|
"index.js"
|
|
11
11
|
],
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"browser": "./
|
|
14
|
+
"browser": "./index.js",
|
|
15
15
|
"import": "./index.js",
|
|
16
16
|
"default": "./index.js"
|
|
17
17
|
},
|
|
@@ -35,21 +35,18 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@babel/eslint-parser": "^7.
|
|
39
|
-
"@open-wc/testing": "^
|
|
40
|
-
"@web/dev-server": "^0.1
|
|
41
|
-
"@web/test-runner": "^0.14.
|
|
38
|
+
"@babel/eslint-parser": "^7.23.3",
|
|
39
|
+
"@open-wc/testing": "^4.0.0",
|
|
40
|
+
"@web/dev-server": "^0.4.1",
|
|
41
|
+
"@web/test-runner": "^0.14.1",
|
|
42
42
|
"babel-eslint": "^10.1.0",
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"eslint": "
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"husky": "^8.0.1",
|
|
51
|
-
"lint-staged": "^13.0.3",
|
|
52
|
-
"prettier": "^2.7.1"
|
|
43
|
+
"eslint": "8.55.0",
|
|
44
|
+
"eslint-config-prettier": "^9.1.0",
|
|
45
|
+
"eslint-plugin-import": "^2.29.0",
|
|
46
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
47
|
+
"husky": "^8.0.3",
|
|
48
|
+
"lint-staged": "^15.1.0",
|
|
49
|
+
"prettier": "^3.1.0"
|
|
53
50
|
},
|
|
54
51
|
"lint-staged": {
|
|
55
52
|
"*.{js,json}": [
|
|
@@ -59,7 +56,6 @@
|
|
|
59
56
|
},
|
|
60
57
|
"scripts": {
|
|
61
58
|
"lint": "eslint index.js 'src/**/*.js'",
|
|
62
|
-
"prepare": "esbuild index.js --outfile=dist/index.js --bundle --format=esm --sourcemap --target=chrome79,firefox68,safari12,edge79",
|
|
63
59
|
"test": "web-test-runner test/**/*.test.{html,js} --node-resolve",
|
|
64
60
|
"test:coverage": "web-test-runner test/**/*.test.{html,js} --node-resolve --coverage",
|
|
65
61
|
"test:watch": "web-test-runner test/**/*.test.{html,js} --node-resolve --watch",
|
package/src/BaseElement.js
CHANGED
|
@@ -380,7 +380,7 @@ class BaseElement extends HTMLElement {
|
|
|
380
380
|
property in this._options['propertyOptions'] &&
|
|
381
381
|
this._options['propertyOptions'][property]['notify'] === true
|
|
382
382
|
) {
|
|
383
|
-
this.dispatch(`${camelToDash(property)}-changed`, newValue
|
|
383
|
+
this.dispatch(`${camelToDash(property)}-changed`, newValue);
|
|
384
384
|
}
|
|
385
385
|
}
|
|
386
386
|
|
|
@@ -453,7 +453,7 @@ class BaseElement extends HTMLElement {
|
|
|
453
453
|
* @param {any | function} valueOrCallback
|
|
454
454
|
*/
|
|
455
455
|
requestContext(propertyName, valueOrCallback) {
|
|
456
|
-
this.dispatch('request-context', { [propertyName]: valueOrCallback }
|
|
456
|
+
this.dispatch('request-context', { [propertyName]: valueOrCallback });
|
|
457
457
|
}
|
|
458
458
|
|
|
459
459
|
/**
|
|
@@ -619,10 +619,10 @@ class BaseElement extends HTMLElement {
|
|
|
619
619
|
/**
|
|
620
620
|
* Helper function for dispatching custom events
|
|
621
621
|
* @param {string} name
|
|
622
|
-
* @param {Object} data
|
|
623
|
-
* @param {CustomEventInit} options
|
|
624
|
-
* @param {boolean} cancelable - DEPRECATED
|
|
625
|
-
* @param {boolean} composed - DEPRECATED
|
|
622
|
+
* @param {Object} [data]
|
|
623
|
+
* @param {CustomEventInit} [options]
|
|
624
|
+
* @param {boolean} [cancelable] - DEPRECATED
|
|
625
|
+
* @param {boolean} [composed] - DEPRECATED
|
|
626
626
|
*/
|
|
627
627
|
dispatch(name, data, options, cancelable = false, composed = false) {
|
|
628
628
|
let eventInit = {};
|
|
@@ -120,6 +120,7 @@ export class AttributePart extends Part {
|
|
|
120
120
|
*/
|
|
121
121
|
constructor(node, name, initialValue) {
|
|
122
122
|
super();
|
|
123
|
+
node.__part = this; // add Part to comment node for debugging in the browser
|
|
123
124
|
this.name = name;
|
|
124
125
|
this.initialValue = initialValue;
|
|
125
126
|
this.processor = processAttributePart(node.nextElementSibling, this.name);
|
|
@@ -212,6 +212,8 @@ export class ChildNodePart extends Part {
|
|
|
212
212
|
|
|
213
213
|
let serverSideRendered = false;
|
|
214
214
|
if (startNode) {
|
|
215
|
+
startNode.__part = this; // add Part to comment node for debugging in the browser
|
|
216
|
+
|
|
215
217
|
const placeholder = startNode.data;
|
|
216
218
|
const childNodes = [startNode];
|
|
217
219
|
let childNode = startNode.nextSibling;
|
|
@@ -22,6 +22,7 @@ export class NodePart extends Part {
|
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
super();
|
|
25
|
+
node.__part = this; // add Part to comment node for debugging in the browser
|
|
25
26
|
this.node = node.nextElementSibling;
|
|
26
27
|
const { directiveClass, values } = initialValue;
|
|
27
28
|
this.directive = new directiveClass(node.nextElementSibling);
|
|
@@ -54,12 +54,14 @@ const choose = (value, cases, defaultCase) => {
|
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
* Renders a given string as HTML instead of text
|
|
57
|
+
* Renders a given string as HTML instead of text or as unescaped string in SSR mode
|
|
58
58
|
* @param {string} string
|
|
59
|
-
* @returns {function(): Node | string}
|
|
59
|
+
* @returns {(function(): Node) | { __unsafeHTML: true, string: string }}
|
|
60
60
|
*/
|
|
61
61
|
const unsafeHTML = (string) => {
|
|
62
|
-
if (!globalThis.DOMParser)
|
|
62
|
+
if (!globalThis.DOMParser) {
|
|
63
|
+
return { __unsafeHTML: true, string };
|
|
64
|
+
}
|
|
63
65
|
const node = convertStringToHTML(string).firstChild;
|
|
64
66
|
const importedNode = globalThis.document?.importNode(node, true);
|
|
65
67
|
return () => importedNode;
|