@webqit/oohtml 2.1.34 → 2.1.35

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.
Files changed (52) hide show
  1. package/.gitignore +3 -3
  2. package/LICENSE +20 -20
  3. package/README.md +733 -67
  4. package/dist/bindings-api.js +1 -1
  5. package/dist/bindings-api.js.map +3 -3
  6. package/dist/context-api.js +1 -1
  7. package/dist/context-api.js.map +3 -3
  8. package/dist/html-imports.js +1 -1
  9. package/dist/html-imports.js.map +3 -3
  10. package/dist/main.js +12 -12
  11. package/dist/main.js.map +3 -3
  12. package/dist/namespace-api.js +1 -1
  13. package/dist/namespace-api.js.map +3 -3
  14. package/dist/scoped-css.js +2 -2
  15. package/dist/scoped-css.js.map +3 -3
  16. package/dist/scoped-js.js +7 -7
  17. package/dist/scoped-js.js.map +3 -3
  18. package/package.json +76 -76
  19. package/src/bindings-api/index.js +83 -83
  20. package/src/bindings-api/targets.browser.js +10 -10
  21. package/src/context-api/HTMLContext.js +76 -157
  22. package/src/context-api/HTMLContextProvider.js +158 -0
  23. package/src/context-api/_ContextRequestEvent.js +25 -25
  24. package/src/context-api/index.js +51 -51
  25. package/src/context-api/targets.browser.js +9 -9
  26. package/src/{html-modules/HTMLExportsManager.js → html-imports/_HTMLExportsManager.js} +185 -199
  27. package/src/html-imports/_HTMLImportElement.js +211 -213
  28. package/src/{html-modules/_HTMLImportsContext.js → html-imports/_HTMLImportsProvider.js} +122 -114
  29. package/src/html-imports/index.js +197 -88
  30. package/src/html-imports/targets.browser.js +9 -9
  31. package/src/index.js +30 -32
  32. package/src/namespace-api/index.js +144 -144
  33. package/src/namespace-api/targets.browser.js +10 -10
  34. package/src/scoped-css/index.js +45 -45
  35. package/src/scoped-css/targets.browser.js +10 -10
  36. package/src/scoped-js/Compiler.js +297 -297
  37. package/src/scoped-js/index.js +112 -112
  38. package/src/scoped-js/targets.browser.js +10 -10
  39. package/src/targets.browser.js +9 -9
  40. package/src/util.js +34 -34
  41. package/test/bindings-api.test.js +42 -42
  42. package/test/imports.test.js +221 -221
  43. package/test/index.js +50 -50
  44. package/test/modules.test.js +200 -200
  45. package/test/namespace-api.test.js +51 -51
  46. package/test/scoped-css.test.js +31 -31
  47. package/test/scoped-js.test.js +29 -29
  48. package/dist/html-modules.js +0 -2
  49. package/dist/html-modules.js.map +0 -7
  50. package/src/context-api/HTMLContextManager.js +0 -77
  51. package/src/html-modules/index.js +0 -131
  52. package/src/html-modules/targets.browser.js +0 -10
@@ -1,114 +1,122 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import Observer from '@webqit/observer';
6
- import { HTMLContextManager, HTMLContext } from '../context-api/index.js';
7
- import { getModulesObject } from './index.js';
8
- import { _ } from '../util.js';
9
-
10
- export default class _HTMLImportsContext extends HTMLContext {
11
-
12
- /**
13
- * @createRequest
14
- */
15
- static createRequest( fields = {} ) {
16
- const request = { type: 'HTMLModules', ...fields };
17
- if ( !request.name && request.detail?.startsWith( '/' ) ) { request.name = 'root'; }
18
- else if ( request.detail?.startsWith( '@' ) ) {
19
- const [ contextName, detail ] = request.detail.split( ':' ).map( s => s.trim() );
20
- request.name = contextName.slice( 1 );
21
- request.detail = detail;
22
- }
23
- return request;
24
- }
25
-
26
- /**
27
- * @modules
28
- */
29
- get modules() {
30
- return getModulesObject( this.host );
31
- }
32
-
33
- /**
34
- * @handle()
35
- */
36
- handle( event ) {
37
- // Any existing event.request.controller? Abort!
38
- event.request.controller?.abort();
39
-
40
- // Parse and translate detail
41
- if ( ( event.request.detail || '' ).trim() === '/' ) return event.respondWith( this.modules );
42
- const $config = this.constructor.config;
43
- let path = ( event.request.detail || '' ).split( /\/|(?<=\w)(?=#)/g ).map( x => x.trim() ).filter( x => x );
44
- if ( path.length ) { path = path.join( `/${ $config.template.api.modules }/` )?.split( '/' ) || []; }
45
- // No detail?
46
- if ( !path.length ) return event.respondWith();
47
-
48
- // We'll now fulfill request
49
- const params = { live: event.request.live, descripted: true, midwayResults: true };
50
- // Find a way to resolve request against two sources
51
- event.request.controller = Observer.deep( this.modules, path, Observer.get, ( result, { signal } = {} ) => {
52
- if ( !result.value && this.host.isConnected === false ) return; // Subtree is being disposed
53
- if ( result.value || !this.altModules ) return event.respondWith( result.value );
54
- // This superModules binding is automatically aborted by the injected control.signal; see below
55
- return Observer.deep( this.altModules, path, Observer.get, result => {
56
- return event.respondWith( result.value );
57
- }, { signal, ...params } );
58
- }, params );
59
- }
60
-
61
- /**
62
- * @startRealtime()
63
- */
64
- realtimeSources( host ) {
65
- this.host = host;
66
- // ----------------
67
- const update = () => {
68
- for ( const subscriptionEvent of this.subscriptions ) {
69
- this.handle( subscriptionEvent );
70
- }
71
- };
72
- // ----------------
73
- const $config = this.constructor.config;
74
- if ( !this.host.matches || !$config.context.attr.importscontext ) return;
75
- // Any existing this.refdSourceController? Abort!
76
- this.refdSourceController?.disconnect();
77
- const realdom = this.host.ownerDocument.defaultView.webqit.realdom;
78
- this.refdSourceController = realdom.realtime( this.host ).attr( $config.context.attr.importscontext, ( record, { signal } ) => {
79
- // No importscontext attr set. But we're still watching
80
- if ( !record.value ) {
81
- this.altModules = undefined;
82
- return update();
83
- }
84
- // This superModules contextrequest is automatically aborted by the injected signal below
85
- const request = this.constructor.createRequest( { detail: record.value.trim(), live: true, signal, superContextOnly: true } );
86
- HTMLContextManager.instance( this.host ).ask( request, response => {
87
- this.altModules = !( response && Object.getPrototypeOf( response ) ) ? response : getModulesObject( response );
88
- update();
89
- } );
90
- }, { live: true, timing: 'sync', lifecycleSignals: true } );
91
- }
92
-
93
- /**
94
- * @initialize()
95
- */
96
- initialize( host ) {
97
- // If host has importscontext attr, compute that
98
- this.realtimeSources( host );
99
- // Now, listen for contextrequest and contextclaim events
100
- // And process own claim
101
- return super.initialize( host );
102
- }
103
-
104
- /**
105
- * @dispose()
106
- */
107
- dispose( host ) {
108
- // Stop listening for sources
109
- this.refdSourceController?.disconnect();
110
- // Now, stop listening for contextrequest and contextclaim events
111
- // And relinquish own subscribers to owner context
112
- return super.dispose( host );
113
- }
114
- }
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import Observer from '@webqit/observer';
6
+ import { HTMLContext, HTMLContextProvider } from '../context-api/index.js';
7
+ import { getModulesObject } from './index.js';
8
+ import { _ } from '../util.js';
9
+
10
+ export default class _HTMLImportsProvider extends HTMLContextProvider {
11
+
12
+ /**
13
+ * @createId
14
+ */
15
+ static createId( host, fields = {} ) {
16
+ if ( !( 'type' in fields ) ) fields = { type: 'htmlimports', ...fields };
17
+ return super.createId( host, fields );
18
+ }
19
+
20
+ /**
21
+ * @createRequest
22
+ */
23
+ static createRequest( fields = {} ) {
24
+ const request = { type: 'htmlimports', ...fields };
25
+ if ( !request.contextName && request.detail?.startsWith( '/' ) ) { request.contextName = 'root'; }
26
+ else if ( request.detail?.startsWith( '@' ) ) {
27
+ const [ contextName, ...detail ] = request.detail.slice( 1 ).split( /(?<=\w)(?=\/|#)/ ).map( s => s.trim() );
28
+ request.contextName = contextName;
29
+ request.detail = detail.join( '' );
30
+ }
31
+ return request;
32
+ }
33
+
34
+ /**
35
+ * @localModules
36
+ */
37
+ get localModules() {
38
+ return getModulesObject( this.host );
39
+ }
40
+
41
+ /**
42
+ * @handle()
43
+ */
44
+ handle( event ) {
45
+ // Any existing event.request.controller? Abort!
46
+ event.request.controller?.abort();
47
+
48
+ // Parse and translate detail
49
+ if ( ( event.request.detail || '' ).trim() === '/' ) return event.respondWith( this.localModules );
50
+ const $config = this.constructor.config;
51
+ let path = ( event.request.detail || '' ).split( /\/|(?<=\w)(?=#)/g ).map( x => x.trim() ).filter( x => x );
52
+ if ( path.length ) { path = path.join( `/${ $config.template.api.modules }/` )?.split( '/' ) || []; }
53
+ // No detail?
54
+ if ( !path.length ) return event.respondWith();
55
+
56
+ // We'll now fulfill request
57
+ const options = { live: event.request.live, descripted: true, midwayResults: true };
58
+ // Find a way to resolve request against two sources
59
+ event.request.controller = Observer.deep( this.localModules, path, Observer.get, ( result, { signal } = {} ) => {
60
+ if ( !result.value && this.host.isConnected === false ) return; // Subtree is being disposed
61
+ if ( result.value || !this.contextModules ) return event.respondWith( result.value );
62
+ // This superModules binding is automatically aborted by the injected control.signal; see below
63
+ return Observer.deep( this.contextModules, path, Observer.get, result => {
64
+ return event.respondWith( result.value );
65
+ }, { signal, ...options } );
66
+ }, options );
67
+ }
68
+
69
+ /**
70
+ * @startRealtime()
71
+ */
72
+ realtimeSources( host ) {
73
+ this.host = host;
74
+ // ----------------
75
+ const update = () => {
76
+ for ( const subscriptionEvent of this.subscriptions ) {
77
+ this.handle( subscriptionEvent );
78
+ }
79
+ };
80
+ // ----------------
81
+ const $config = this.constructor.config;
82
+ if ( !this.host.matches || !$config.context.attr.importscontext ) return;
83
+ // Any existing this.refdSourceController? Abort!
84
+ this.refdSourceController?.disconnect();
85
+ const realdom = this.host.ownerDocument.defaultView.webqit.realdom;
86
+ this.refdSourceController = realdom.realtime( this.host ).attr( $config.context.attr.importscontext, ( record, { signal } ) => {
87
+ // No importscontext attr set. But we're still watching
88
+ if ( !record.value ) {
89
+ this.contextModules = undefined;
90
+ return update();
91
+ }
92
+ // This superModules contextrequest is automatically aborted by the injected signal below
93
+ const request = this.constructor.createRequest( { detail: record.value.trim(), live: true, signal, superContextOnly: true } );
94
+ HTMLContext.instance( this.host ).request( request, response => {
95
+ this.contextModules = !( response && Object.getPrototypeOf( response ) ) ? response : getModulesObject( response );
96
+ update();
97
+ } );
98
+ }, { live: true, timing: 'sync', lifecycleSignals: true } );
99
+ }
100
+
101
+ /**
102
+ * @initialize()
103
+ */
104
+ initialize( host ) {
105
+ // If host has importscontext attr, compute that
106
+ this.realtimeSources( host );
107
+ // Now, listen for contextrequest and contextclaim events
108
+ // And process own claim
109
+ return super.initialize( host );
110
+ }
111
+
112
+ /**
113
+ * @dispose()
114
+ */
115
+ dispose( host ) {
116
+ // Stop listening for sources
117
+ this.refdSourceController?.disconnect();
118
+ // Now, stop listening for contextrequest and contextclaim events
119
+ // And relinquish own subscribers to owner context
120
+ return super.dispose( host );
121
+ }
122
+ }
@@ -1,88 +1,197 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import _HTMLImportElement from './_HTMLImportElement.js';
6
- import { _, _init } from '../util.js';
7
-
8
- /**
9
- * Initializes HTML Modules.
10
- *
11
- * @param $config Object
12
- *
13
- * @return Void
14
- */
15
- export default function init( $config = {} ) {
16
- const { config, realdom, window } = _init.call( this, 'html-imports', $config, {
17
- import: { tagName: 'import', attr: { moduleref: 'module' }, },
18
- export: { attr: { exportid: 'exportid' }, },
19
- isomorphic: true,
20
- } );
21
- config.slottedElementsSelector = `[${ window.CSS.escape( config.export.attr.exportid ) }]`;
22
- window.webqit.HTMLImportElement = _HTMLImportElement.call( window, config );
23
- realdom.ready( () => hydration.call( window, config ) );
24
- realtime.call( window, config );
25
- }
26
-
27
- /**
28
- * Performs realtime capture of elements and their attributes
29
- * and their module query results; then resolves the respective import elements.
30
- *
31
- * @param Object config
32
- *
33
- * @return Void
34
- */
35
- function realtime( config ) {
36
- const window = this, { realdom, HTMLImportElement } = window.webqit;
37
- realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.import.tagName, record => {
38
- record.entrants.forEach( node => handleRealtime( node, true, record ) );
39
- record.exits.forEach( node => handleRealtime( node, false, record ) );
40
- }, { live: true, timing: 'sync' } );
41
- function handleRealtime( entry, connectedState, record ) {
42
- const elInstance = HTMLImportElement.instance( entry );
43
- if ( connectedState ) { elInstance[ '#' ].connectedCallback(); }
44
- else { elInstance[ '#' ].disconnectedCallback(); }
45
- }
46
- }
47
-
48
- /**
49
- * Performs hydration for server-slotted elements.
50
- *
51
- * @param Object config
52
- *
53
- * @return Void
54
- */
55
- function hydration( config ) {
56
- const window = this, { HTMLImportElement } = window.webqit;
57
- function scan( context ) {
58
- const slottedElements = new Set;
59
- context.childNodes.forEach( node => {
60
- if ( node.nodeType === 1/** ELEMENT_NODE */ ) {
61
- if ( !node.matches( config.slottedElementsSelector ) ) return;
62
- if ( _( node ).get( 'slot@imports' ) ) return;
63
- slottedElements.add( node );
64
- } else if ( node.nodeType === 8/** COMMENT_NODE */ ) {
65
- const nodeValue = node.nodeValue.trim();
66
- if ( !nodeValue.startsWith( '<' + config.import.tagName ) ) return;
67
- if ( !nodeValue.endsWith( '</' + config.import.tagName + '>' ) ) return;
68
- const reviver = window.document.createElement( 'div' );
69
- reviver.innerHTML = nodeValue;
70
- const importEl = reviver.firstChild;
71
- if ( !importEl.matches( config.import.tagName ) ) return;
72
- HTMLImportElement.instance( importEl )[ '#' ].hydrate(
73
- node/* the comment node */, slottedElements
74
- );
75
- slottedElements.clear();
76
- }
77
- } );
78
- }
79
- Array.from( window.document.querySelectorAll( config.slottedElementsSelector ) ).forEach( slottedElement => {
80
- // hydration() might be running AFTER certain <slots> have resolved
81
- // and slottedElement might be a just-resolved node
82
- if ( _( slottedElement ).get( 'slot@imports' ) ) return;
83
- if ( _( slottedElement.parentNode ).get( 'alreadyscanned@imports' ) ) return;
84
- scan( slottedElement.parentNode );
85
- // Scanning is once for every parent
86
- _( slottedElement.parentNode ).set( 'alreadyscanned@imports', true );
87
- } );
88
- }
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import Observer from '@webqit/observer';
6
+ import { HTMLContext } from '../context-api/index.js';
7
+ import _HTMLExportsManager from './_HTMLExportsManager.js';
8
+ import _HTMLImportElement from './_HTMLImportElement.js';
9
+ import _HTMLImportsProvider from './_HTMLImportsProvider.js';
10
+ import { _, _init } from '../util.js';
11
+
12
+ /**
13
+ * Initializes HTML Modules.
14
+ *
15
+ * @param $config Object
16
+ *
17
+ * @return Void
18
+ */
19
+ export default function init( $config = {} ) {
20
+ const { config, realdom, window } = _init.call( this, 'html-imports', $config, {
21
+ export: { attr: { exportid: 'as' }, },
22
+ template: { attr: { exportid: 'as', extends: 'extends', inherits: 'inherits' }, api: { modules: 'modules', exportid: 'exportid' }, },
23
+ context: { attr: { importscontext: 'importscontext', contextname: 'contextname' }, api: { modules: 'modules' }, },
24
+ import: { tagName: 'import', attr: { moduleref: 'ref' }, },
25
+ staticsensitivity: true,
26
+ isomorphic: true,
27
+ } );
28
+ config.templateSelector = `template[${ window.CSS.escape( config.template.attr.exportid ) }]`;
29
+ config.ownerContextSelector = [ config.context.attr.contextname, config.context.attr.importscontext ].map( a => `[${ window.CSS.escape( a ) }]` ).join( ',' );
30
+ config.slottedElementsSelector = `[${ window.CSS.escape( config.export.attr.exportid ) }]`;
31
+ window.webqit.HTMLImportElement = _HTMLImportElement.call( window, config );
32
+ window.webqit.HTMLImportsProvider = class extends _HTMLImportsProvider {
33
+ static get config() { return config; }
34
+ };
35
+ window.webqit.Observer = Observer;
36
+ exposeModulesObjects.call( window, config );
37
+ realdom.ready( () => hydration.call( window, config ) );
38
+ realtime.call( window, config );
39
+ }
40
+
41
+ export { Observer }
42
+
43
+ /**
44
+ * Returns the "exports" object associated with the given node.
45
+ *
46
+ * @param Element node
47
+ * @param Bool autoCreate
48
+ *
49
+ * @return Object
50
+ */
51
+ export function getModulesObject( node, autoCreate = true ) {
52
+ if ( !_( node ).has( 'modules' ) && autoCreate ) {
53
+ const modulesObj = Object.create( null );
54
+ _( node ).set( 'modules', modulesObj );
55
+ }
56
+ return _( node ).get( 'modules' );
57
+ }
58
+
59
+ /**
60
+ * Exposes HTML Modules with native APIs.
61
+ *
62
+ * @param Object config
63
+ *
64
+ * @return Void
65
+ */
66
+ function exposeModulesObjects( config ) {
67
+ const window = this;
68
+ // Assertions
69
+ if ( config.template.api.modules in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.template.api.modules }" property!` ); }
70
+ if ( config.template.api.exportid in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.template.api.exportid }" property!` ); }
71
+ if ( config.context.api.import in window.document ) { throw new Error( `document already has a "${ config.context.api.import }" property!` ); }
72
+ if ( config.context.api.import in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.context.api.import }" property!` ); }
73
+ // Definitions
74
+ Object.defineProperty( window.HTMLTemplateElement.prototype, config.template.api.modules, { get: function() {
75
+ return getModulesObject( this );
76
+ } } );
77
+ Object.defineProperty( window.HTMLTemplateElement.prototype, config.template.api.exportid, { get: function() {
78
+ return this.getAttribute( config.template.attr.exportid );
79
+ } } );
80
+ Object.defineProperty( window.document, config.context.api.import, { value: function( ref, callback, options = {} ) {
81
+ return importRequest( window.document, ref, callback, options );
82
+ } } );
83
+ Object.defineProperty( window.HTMLElement.prototype, config.context.api.import, { value: function( ref, callback, options = {} ) {
84
+ return importRequest( this, ref, callback, options );
85
+ } } );
86
+ function importRequest( context, ref, callback, options ) {
87
+ const request = _HTMLImportsProvider.createRequest( { detail: ref, ...options } );
88
+ return HTMLContext.instance( context ).request( request, callback );
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Performs realtime capture of elements and their attributes
94
+ * and their module query results; then resolves the respective import elements.
95
+ *
96
+ * @param Object config
97
+ *
98
+ * @return Void
99
+ */
100
+ function realtime( config ) {
101
+ const window = this, { realdom, HTMLImportElement, HTMLImportsProvider } = window.webqit;
102
+ // ------------
103
+ // MODULES
104
+ // ------------
105
+ const attachImportsContext = host => {
106
+ const contextId = HTMLImportsProvider.createId( host );
107
+ HTMLImportsProvider.attachTo( host, contextId );
108
+ };
109
+ const detachImportsContext = ( host, force ) => {
110
+ const contextId = HTMLImportsProvider.createId( host );
111
+ HTMLImportsProvider.detachFrom( host, contextId, cx => {
112
+ return force || host.matches && !host.matches( config.ownerContextSelector ) && !Object.keys( cx.localModules ).length;
113
+ } );
114
+ };
115
+ // ------------
116
+ realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( [ config.templateSelector, config.ownerContextSelector ], record => {
117
+ record.entrants.forEach( entry => {
118
+ if ( entry.matches( config.templateSelector ) ) {
119
+ Object.defineProperty( entry, 'scoped', { value: entry.hasAttribute( 'scoped' ) } );
120
+ const moduleExport = new _HTMLExportsManager( window, entry, config );
121
+ moduleExport.ownerContext = entry.scoped ? record.target : window.document;
122
+ const ownerContextModulesObj = getModulesObject( moduleExport.ownerContext );
123
+ if ( moduleExport.exportId ) { Observer.set( ownerContextModulesObj, moduleExport.exportId, entry ); }
124
+ // The ownerContext's modulesObj - ownerContextModulesObj - has to be populated
125
+ // Before attaching a context instance to it, to give the just created context something to use for
126
+ // fullfiling reclaimed requests.
127
+ attachImportsContext( moduleExport.ownerContext );
128
+ } else {
129
+ attachImportsContext( entry );
130
+ }
131
+ } );
132
+ record.exits.forEach( entry => {
133
+ if ( entry.matches( config.templateSelector ) ) {
134
+ const moduleExport = _HTMLExportsManager.instance( window, entry, config );
135
+ const ownerContextModulesObj = getModulesObject( moduleExport.ownerContext );
136
+ if ( moduleExport.exportId ) { Observer.deleteProperty( ownerContextModulesObj, moduleExport.exportId ); }
137
+ detachImportsContext( moduleExport.ownerContext );
138
+ } else {
139
+ detachImportsContext( entry, true );
140
+ }
141
+ } );
142
+ }, { live: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
143
+ // ------------
144
+ // IMPORTS
145
+ // ------------
146
+ realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.import.tagName, record => {
147
+ record.entrants.forEach( node => handleRealtime( node, true, record ) );
148
+ record.exits.forEach( node => handleRealtime( node, false, record ) );
149
+ }, { live: true, timing: 'sync' } );
150
+ function handleRealtime( entry, connectedState, record ) {
151
+ const elInstance = HTMLImportElement.instance( entry );
152
+ if ( connectedState ) { elInstance[ '#' ].connectedCallback(); }
153
+ else { elInstance[ '#' ].disconnectedCallback(); }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Performs hydration for server-slotted elements.
159
+ *
160
+ * @param Object config
161
+ *
162
+ * @return Void
163
+ */
164
+ function hydration( config ) {
165
+ const window = this, { HTMLImportElement } = window.webqit;
166
+ function scan( context ) {
167
+ const slottedElements = new Set;
168
+ context.childNodes.forEach( node => {
169
+ if ( node.nodeType === 1/** ELEMENT_NODE */ ) {
170
+ if ( !node.matches( config.slottedElementsSelector ) ) return;
171
+ if ( _( node ).get( 'slot@imports' ) ) return;
172
+ slottedElements.add( node );
173
+ } else if ( node.nodeType === 8/** COMMENT_NODE */ ) {
174
+ const nodeValue = node.nodeValue.trim();
175
+ if ( !nodeValue.startsWith( '<' + config.import.tagName ) ) return;
176
+ if ( !nodeValue.endsWith( '</' + config.import.tagName + '>' ) ) return;
177
+ const reviver = window.document.createElement( 'div' );
178
+ reviver.innerHTML = nodeValue;
179
+ const importEl = reviver.firstChild;
180
+ if ( !importEl.matches( config.import.tagName ) ) return;
181
+ HTMLImportElement.instance( importEl )[ '#' ].hydrate(
182
+ node/* the comment node */, slottedElements
183
+ );
184
+ slottedElements.clear();
185
+ }
186
+ } );
187
+ }
188
+ Array.from( window.document.querySelectorAll( config.slottedElementsSelector ) ).forEach( slottedElement => {
189
+ // hydration() might be running AFTER certain <slots> have resolved
190
+ // and slottedElement might be a just-resolved node
191
+ if ( _( slottedElement ).get( 'slot@imports' ) ) return;
192
+ if ( _( slottedElement.parentNode ).get( 'alreadyscanned@imports' ) ) return;
193
+ scan( slottedElement.parentNode );
194
+ // Scanning is once for every parent
195
+ _( slottedElement.parentNode ).set( 'alreadyscanned@imports', true );
196
+ } );
197
+ }
@@ -1,10 +1,10 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import init from './index.js';
6
-
7
- /**
8
- * @init
9
- */
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import init from './index.js';
6
+
7
+ /**
8
+ * @init
9
+ */
10
10
  init.call( window );
package/src/index.js CHANGED
@@ -1,33 +1,31 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import Observer from '@webqit/observer';
6
- import BindingsAPI from './bindings-api/index.js';
7
- import ContextAPI from './context-api/index.js';
8
- import NamespaceAPI from './namespace-api/index.js';
9
- import HTMLModules from './html-modules/index.js';
10
- import HTMLImports from './html-imports/index.js';
11
- import ScopedCSS from './scoped-css/index.js';
12
- import ScopedJS from './scoped-js/index.js';
13
-
14
- /**
15
- * @init
16
- */
17
- export default function init( configs = {} ) {
18
- if ( !this.webqit ) { this.webqit = {}; }
19
- // --------------
20
- BindingsAPI.call( this, ( configs.BINDINGS_API || {} ) );
21
- ContextAPI.call( this, ( configs.CONTEXT_API || {} ) );
22
- NamespaceAPI.call( this, ( configs.NAMESPACE_API || {} ) );
23
- HTMLModules.call( this, ( configs.HTML_MODULES || {} ) );
24
- HTMLImports.call( this, ( configs.HTML_IMPORTS || {} ) );
25
- ScopedCSS.call( this, ( configs.SCOPED_CSS || {} ) );
26
- ScopedJS.call( this, ( configs.SCOPED_JS || {} ) );
27
- // --------------
28
- }
29
-
30
- /**
31
- * @exports
32
- */
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import Observer from '@webqit/observer';
6
+ import BindingsAPI from './bindings-api/index.js';
7
+ import ContextAPI from './context-api/index.js';
8
+ import ScopedCSS from './scoped-css/index.js';
9
+ import ScopedJS from './scoped-js/index.js';
10
+ import NamespaceAPI from './namespace-api/index.js';
11
+ import HTMLImports from './html-imports/index.js';
12
+
13
+ /**
14
+ * @init
15
+ */
16
+ export default function init( configs = {} ) {
17
+ if ( !this.webqit ) { this.webqit = {}; }
18
+ // --------------
19
+ BindingsAPI.call( this, ( configs.BINDINGS_API || {} ) );
20
+ ContextAPI.call( this, ( configs.CONTEXT_API || {} ) );
21
+ ScopedJS.call( this, ( configs.SCOPED_JS || {} ) );
22
+ ScopedCSS.call( this, ( configs.SCOPED_CSS || {} ) );
23
+ NamespaceAPI.call( this, ( configs.NAMESPACE_API || {} ) );
24
+ HTMLImports.call( this, ( configs.HTML_IMPORTS || {} ) );
25
+ // --------------
26
+ }
27
+
28
+ /**
29
+ * @exports
30
+ */
33
31
  export { Observer }