@webqit/oohtml 2.1.34 → 2.1.36
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/.gitignore +3 -3
- package/LICENSE +20 -20
- package/README.md +733 -67
- package/dist/bindings-api.js +1 -1
- package/dist/bindings-api.js.map +3 -3
- package/dist/context-api.js +1 -1
- package/dist/context-api.js.map +3 -3
- package/dist/html-imports.js +1 -1
- package/dist/html-imports.js.map +3 -3
- package/dist/main.js +12 -12
- package/dist/main.js.map +3 -3
- package/dist/namespace-api.js +1 -1
- package/dist/namespace-api.js.map +3 -3
- package/dist/scoped-css.js +2 -2
- package/dist/scoped-css.js.map +3 -3
- package/dist/scoped-js.js +7 -7
- package/dist/scoped-js.js.map +3 -3
- package/package.json +76 -76
- package/src/bindings-api/index.js +83 -83
- package/src/bindings-api/targets.browser.js +10 -10
- package/src/context-api/HTMLContext.js +76 -157
- package/src/context-api/HTMLContextProvider.js +158 -0
- package/src/context-api/_ContextRequestEvent.js +25 -25
- package/src/context-api/index.js +51 -51
- package/src/context-api/targets.browser.js +9 -9
- package/src/{html-modules/HTMLExportsManager.js → html-imports/_HTMLExportsManager.js} +185 -199
- package/src/html-imports/_HTMLImportElement.js +211 -213
- package/src/{html-modules/_HTMLImportsContext.js → html-imports/_HTMLImportsProvider.js} +122 -114
- package/src/html-imports/index.js +197 -88
- package/src/html-imports/targets.browser.js +9 -9
- package/src/index.js +30 -32
- package/src/namespace-api/index.js +144 -144
- package/src/namespace-api/targets.browser.js +10 -10
- package/src/scoped-css/index.js +45 -45
- package/src/scoped-css/targets.browser.js +10 -10
- package/src/scoped-js/Compiler.js +297 -297
- package/src/scoped-js/index.js +112 -112
- package/src/scoped-js/targets.browser.js +10 -10
- package/src/targets.browser.js +9 -9
- package/src/util.js +34 -34
- package/test/bindings-api.test.js +42 -42
- package/test/imports.test.js +221 -221
- package/test/index.js +50 -50
- package/test/modules.test.js +200 -200
- package/test/namespace-api.test.js +51 -51
- package/test/scoped-css.test.js +31 -31
- package/test/scoped-js.test.js +29 -29
- package/dist/html-modules.js +0 -2
- package/dist/html-modules.js.map +0 -7
- package/src/context-api/HTMLContextManager.js +0 -77
- package/src/html-modules/index.js +0 -131
- package/src/html-modules/targets.browser.js +0 -10
|
@@ -1,214 +1,212 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import {
|
|
6
|
-
import _HTMLImportsContext from '
|
|
7
|
-
import { _ } from '../util.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Creates the HTMLImportElement class.
|
|
11
|
-
*
|
|
12
|
-
* @param Object config
|
|
13
|
-
*
|
|
14
|
-
* @return HTMLImportElement
|
|
15
|
-
*/
|
|
16
|
-
export default function( config ) {
|
|
17
|
-
const window = this, { realdom } = window.webqit;
|
|
18
|
-
const BaseElement = config.import.tagName.includes( '-' ) ? window.HTMLElement : class {};
|
|
19
|
-
return class HTMLImportElement extends BaseElement {
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @instance
|
|
23
|
-
*
|
|
24
|
-
* @param HTMLElement node
|
|
25
|
-
*
|
|
26
|
-
* @returns
|
|
27
|
-
*/
|
|
28
|
-
static instance( node ) {
|
|
29
|
-
if ( config.import.tagName.includes( '-' ) && ( node instanceof this ) ) return node;
|
|
30
|
-
return _( node ).get( 'import::instance' ) || new this( node );;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @constructor
|
|
35
|
-
*/
|
|
36
|
-
constructor( ...args ) {
|
|
37
|
-
super();
|
|
38
|
-
// --------
|
|
39
|
-
const el = args[ 0 ] || this;
|
|
40
|
-
_( el ).set( 'import::instance', this );
|
|
41
|
-
Object.defineProperty( this, 'el', { get: () => el, configurable: false } );
|
|
42
|
-
|
|
43
|
-
const priv = {};
|
|
44
|
-
Object.defineProperty( this, '#', { get: () => priv, configurable: false } );
|
|
45
|
-
priv.slottedElements = new Set;
|
|
46
|
-
|
|
47
|
-
priv.setAnchorNode = anchorNode => {
|
|
48
|
-
priv.anchorNode = anchorNode;
|
|
49
|
-
_( anchorNode ).set( 'anchoredNode@imports', this.el );
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
priv.importRequest = ( callback, signal = null ) => {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
priv.
|
|
63
|
-
priv.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
priv.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
priv.
|
|
126
|
-
priv.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
*
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* @
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
*
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
*
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
*
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
*
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
get slottedElements() { return this[ '#' ].slottedElements; }
|
|
213
|
-
}
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import { HTMLContext } from '../context-api/index.js';
|
|
6
|
+
import _HTMLImportsContext from './_HTMLImportsProvider.js';
|
|
7
|
+
import { _ } from '../util.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates the HTMLImportElement class.
|
|
11
|
+
*
|
|
12
|
+
* @param Object config
|
|
13
|
+
*
|
|
14
|
+
* @return HTMLImportElement
|
|
15
|
+
*/
|
|
16
|
+
export default function( config ) {
|
|
17
|
+
const window = this, { realdom } = window.webqit;
|
|
18
|
+
const BaseElement = config.import.tagName.includes( '-' ) ? window.HTMLElement : class {};
|
|
19
|
+
return class HTMLImportElement extends BaseElement {
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @instance
|
|
23
|
+
*
|
|
24
|
+
* @param HTMLElement node
|
|
25
|
+
*
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
static instance( node ) {
|
|
29
|
+
if ( config.import.tagName.includes( '-' ) && ( node instanceof this ) ) return node;
|
|
30
|
+
return _( node ).get( 'import::instance' ) || new this( node );;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @constructor
|
|
35
|
+
*/
|
|
36
|
+
constructor( ...args ) {
|
|
37
|
+
super();
|
|
38
|
+
// --------
|
|
39
|
+
const el = args[ 0 ] || this;
|
|
40
|
+
_( el ).set( 'import::instance', this );
|
|
41
|
+
Object.defineProperty( this, 'el', { get: () => el, configurable: false } );
|
|
42
|
+
|
|
43
|
+
const priv = {};
|
|
44
|
+
Object.defineProperty( this, '#', { get: () => priv, configurable: false } );
|
|
45
|
+
priv.slottedElements = new Set;
|
|
46
|
+
|
|
47
|
+
priv.setAnchorNode = anchorNode => {
|
|
48
|
+
priv.anchorNode = anchorNode;
|
|
49
|
+
_( anchorNode ).set( 'anchoredNode@imports', this.el );
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
priv.importRequest = ( callback, signal = null ) => {
|
|
53
|
+
const request = _HTMLImportsContext.createRequest( { detail: priv.moduleRef, live: signal && true, signal } );
|
|
54
|
+
HTMLContext.instance( this.el.isConnected ? this.el.parentNode : priv.anchorNode.parentNode ).request( request, response => {
|
|
55
|
+
callback( ( response instanceof window.HTMLTemplateElement ? [ ...response.content.children ] : response && [ response ] ) || [] );
|
|
56
|
+
} );
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
priv.hydrate = ( anchorNode, slottedElements ) => {
|
|
60
|
+
// ----------------
|
|
61
|
+
priv.moduleRef = ( this.el.getAttribute( config.import.attr.moduleref ) || '' ).trim();
|
|
62
|
+
priv.setAnchorNode( anchorNode );
|
|
63
|
+
priv.autoRestore( () => {
|
|
64
|
+
slottedElements.forEach( slottedElement => {
|
|
65
|
+
priv.slottedElements.add( slottedElement );
|
|
66
|
+
_( slottedElement ).set( 'slot@imports', this.el );
|
|
67
|
+
} );
|
|
68
|
+
} );
|
|
69
|
+
// ----------------
|
|
70
|
+
priv.hydrationImportRequest = new AbortController;
|
|
71
|
+
priv.importRequest( modules => {
|
|
72
|
+
if ( priv.originalsRemapped ) { return this.fill( modules ); }
|
|
73
|
+
const identifiersMap = modules.map( module => ( { el: module, exportId: module.getAttribute( config.export.attr.exportid ), tagName: module.tagName, } ) );
|
|
74
|
+
slottedElements.forEach( slottedElement => {
|
|
75
|
+
const tagName = slottedElement.tagName, exportId = slottedElement.getAttribute( config.export.attr.exportid );
|
|
76
|
+
const originalsMatch = identifiersMap.filter( moduleIdentifiers => tagName === moduleIdentifiers.tagName && exportId === moduleIdentifiers.exportId );
|
|
77
|
+
if ( originalsMatch.length !== 1 ) return;
|
|
78
|
+
_( slottedElement ).set( 'original@imports', originalsMatch[ 0 ].el );
|
|
79
|
+
} );
|
|
80
|
+
priv.originalsRemapped = true;
|
|
81
|
+
}, priv.hydrationImportRequest.signal );
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
priv.autoRestore = ( callback = null ) => {
|
|
85
|
+
priv.autoRestoreRealtime?.disconnect();
|
|
86
|
+
if ( callback ) callback();
|
|
87
|
+
if ( !priv.slottedElements.size ) {
|
|
88
|
+
priv.anchorNode.replaceWith( this.el );
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const autoRestoreRealtime = realdom.realtime( window.document ).observe( [ ...priv.slottedElements ], record => {
|
|
92
|
+
record.exits.forEach( outgoingNode => {
|
|
93
|
+
_( outgoingNode ).delete( 'slot@imports' );
|
|
94
|
+
priv.slottedElements.delete( outgoingNode );
|
|
95
|
+
} );
|
|
96
|
+
if ( !priv.slottedElements.size ) {
|
|
97
|
+
autoRestoreRealtime.disconnect();
|
|
98
|
+
// At this point, ignore if this is a removal involving the whole parent node
|
|
99
|
+
if ( !record.target.isConnected ) return;
|
|
100
|
+
priv.anchorNode.replaceWith( this.el );
|
|
101
|
+
}
|
|
102
|
+
}, { subtree: true, timing: 'sync', generation: 'exits' } );
|
|
103
|
+
priv.autoRestoreRealtime = autoRestoreRealtime;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
priv.connectedCallback = () => {
|
|
107
|
+
// In case this is DOM node relocation or induced reinsertion into the DOM
|
|
108
|
+
if ( priv.slottedElements.size ) throw new Error( `Illegal reinsertion into the DOM; import slot is not empty!` );
|
|
109
|
+
// Totally initialize this instance?
|
|
110
|
+
if ( !priv.anchorNode ) { priv.setAnchorNode( this.createAnchorNode() ); }
|
|
111
|
+
if ( priv.moduleRefRealtime ) return;
|
|
112
|
+
priv.moduleRefRealtime = realdom.realtime( this.el ).attr( config.import.attr.moduleref, ( record, { signal } ) => {
|
|
113
|
+
priv.moduleRef = record.value;
|
|
114
|
+
// Below, we ignore first restore from hydration
|
|
115
|
+
priv.importRequest( modules => !priv.hydrationImportRequest && this.fill( modules ), signal );
|
|
116
|
+
}, { live: true, timing: 'sync', lifecycleSignals: true } );
|
|
117
|
+
// Must come after
|
|
118
|
+
priv.hydrationImportRequest?.abort();
|
|
119
|
+
priv.hydrationImportRequest = null;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
priv.disconnectedCallback = () => {
|
|
123
|
+
priv.hydrationImportRequest?.abort();
|
|
124
|
+
priv.hydrationImportRequest = null;
|
|
125
|
+
if ( priv.anchorNode.isConnected ) return;
|
|
126
|
+
priv.moduleRefRealtime?.disconnect();
|
|
127
|
+
priv.moduleRefRealtime = null;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Creates the slot's anchor node.
|
|
133
|
+
*
|
|
134
|
+
* @return Element
|
|
135
|
+
*/
|
|
136
|
+
createAnchorNode() {
|
|
137
|
+
if ( !config.isomorphic ) { return window.document.createTextNode( '' ) }
|
|
138
|
+
return window.document.createComment( this.el.outerHTML );
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Fills the slot with slottableElements
|
|
143
|
+
*
|
|
144
|
+
* @param Iterable slottableElements
|
|
145
|
+
*
|
|
146
|
+
* @return void
|
|
147
|
+
*/
|
|
148
|
+
fill( slottableElements ) {
|
|
149
|
+
if ( Array.isArray( slottableElements ) ) { slottableElements = new Set( slottableElements ) }
|
|
150
|
+
this[ '#' ].autoRestore( () => {
|
|
151
|
+
this[ '#' ].slottedElements.forEach( slottedElement => {
|
|
152
|
+
const slottedElementOriginal = _( slottedElement ).get( 'original@imports' );
|
|
153
|
+
// If still available in source, simply leave unchanged
|
|
154
|
+
// otherwise remove it from slot... to reflect this change
|
|
155
|
+
if ( slottableElements.has( slottedElementOriginal ) ) {
|
|
156
|
+
slottableElements.delete( slottedElementOriginal );
|
|
157
|
+
} else {
|
|
158
|
+
this[ '#' ].slottedElements.delete( slottedElement );
|
|
159
|
+
// This removal will not be caught
|
|
160
|
+
slottedElement.remove();
|
|
161
|
+
}
|
|
162
|
+
} );
|
|
163
|
+
// Make sure anchor node is what's in place...
|
|
164
|
+
// not the import element itslef - but all only when we have slottableElements.size
|
|
165
|
+
if ( this.el.isConnected && slottableElements.size ) {
|
|
166
|
+
this.el.replaceWith( this[ '#' ].anchorNode );
|
|
167
|
+
}
|
|
168
|
+
// Insert slottables now
|
|
169
|
+
slottableElements.forEach( slottableElement => {
|
|
170
|
+
// Clone each slottable element and give it a reference to its original
|
|
171
|
+
const slottableElementClone = slottableElement.cloneNode( true );
|
|
172
|
+
// The folllowing references must be set before adding to DODM
|
|
173
|
+
if ( !slottableElementClone.hasAttribute( config.export.attr.exportid ) ) {
|
|
174
|
+
slottableElementClone.toggleAttribute( config.export.attr.exportid, true );
|
|
175
|
+
}
|
|
176
|
+
_( slottableElementClone ).set( 'original@imports', slottableElement );
|
|
177
|
+
_( slottableElementClone ).set( 'slot@imports', this.el );
|
|
178
|
+
this[ '#' ].slottedElements.add( slottableElementClone );
|
|
179
|
+
this[ '#' ].anchorNode.before( slottableElementClone );
|
|
180
|
+
} );
|
|
181
|
+
} );
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Empty slot.
|
|
186
|
+
*
|
|
187
|
+
* @return void
|
|
188
|
+
*/
|
|
189
|
+
empty() { this[ '#' ].slottedElements.forEach( slottedElement => slottedElement.remove() ); }
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Returns the slot's anchorNode.
|
|
193
|
+
*
|
|
194
|
+
* @return array
|
|
195
|
+
*/
|
|
196
|
+
get anchorNode() { return this[ '#' ].anchorNode; }
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Returns the slot's module reference, if any.
|
|
200
|
+
*
|
|
201
|
+
* @return string
|
|
202
|
+
*/
|
|
203
|
+
get moduleRef() { return this[ '#' ].moduleRef; }
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Returns the slot's slotted elements.
|
|
207
|
+
*
|
|
208
|
+
* @return array
|
|
209
|
+
*/
|
|
210
|
+
get slottedElements() { return this[ '#' ].slottedElements; }
|
|
211
|
+
}
|
|
214
212
|
}
|