@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,144 +1,144 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import Observer from '@webqit/observer';
|
|
6
|
-
import { _, _init } from '../util.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @init
|
|
10
|
-
*
|
|
11
|
-
* @param Object $config
|
|
12
|
-
*/
|
|
13
|
-
export default function init( $config = {} ) {
|
|
14
|
-
const { config, window } = _init.call( this, 'namespace-api', $config, {
|
|
15
|
-
id: { attr: 'id' },
|
|
16
|
-
namespace: { attr: 'namespace', api: 'namespace', },
|
|
17
|
-
target: { attr: ':target', event: ':target', scrolling: true },
|
|
18
|
-
staticsensitivity: true,
|
|
19
|
-
eagermode: true,
|
|
20
|
-
} );
|
|
21
|
-
config.idSelector = `[${ window.CSS.escape( config.id.attr ) }]`;
|
|
22
|
-
config.namespaceSelector = `[${ window.CSS.escape( config.namespace.attr ) }]`;
|
|
23
|
-
window.webqit.Observer = Observer;
|
|
24
|
-
exposeNamespaceObjects.call( window, config );
|
|
25
|
-
realtime.call( window, config );
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export { Observer }
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Exposes Namespaced HTML with native APIs.
|
|
32
|
-
*
|
|
33
|
-
* @param Object config
|
|
34
|
-
*
|
|
35
|
-
* @return Void
|
|
36
|
-
*/
|
|
37
|
-
function exposeNamespaceObjects( config ) {
|
|
38
|
-
const window = this;
|
|
39
|
-
// Assertions
|
|
40
|
-
if ( config.namespace.api in window.document ) { throw new Error( `document already has a "${ config.namespace.api }" property!` ); }
|
|
41
|
-
if ( config.namespace.api in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.namespace.api }" property!` ); }
|
|
42
|
-
// Definitions
|
|
43
|
-
Object.defineProperty( window.document, config.namespace.api, { get: function() {
|
|
44
|
-
return Observer.proxy( getNamespaceObject.call( window, window.document, config ) );
|
|
45
|
-
} });
|
|
46
|
-
Object.defineProperty( window.Element.prototype, config.namespace.api, { get: function() {
|
|
47
|
-
return Observer.proxy( getNamespaceObject.call( window, this, config ) );
|
|
48
|
-
} } );
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Returns the "namespace" object associated with the given node.
|
|
53
|
-
*
|
|
54
|
-
* @param Element node
|
|
55
|
-
*
|
|
56
|
-
* @return Object
|
|
57
|
-
*/
|
|
58
|
-
function getNamespaceObject( node, config ) {
|
|
59
|
-
const window = this;
|
|
60
|
-
if ( !_( node ).has( 'namespace' ) ) {
|
|
61
|
-
const namespaceObj = Object.create( null );
|
|
62
|
-
Observer.intercept( namespaceObj, 'get', ( event, receiver, next ) => {
|
|
63
|
-
if ( Observer.has( namespaceObj, event.key ) || !config.eagermode ) return next();
|
|
64
|
-
const selector = `[${ window.CSS.escape( config.id.attr ) }="${ event.key }"]`;
|
|
65
|
-
const resultNode = Array.from( node.querySelectorAll( selector ) ).filter( idNode => {
|
|
66
|
-
const ownerRoot = idNode.parentNode.closest( config.namespaceSelector );
|
|
67
|
-
if ( node === window.document ) {
|
|
68
|
-
// Only IDs without a scope actually belong to the document scope
|
|
69
|
-
return !ownerRoot;
|
|
70
|
-
}
|
|
71
|
-
return ownerRoot === node;
|
|
72
|
-
} )[ 0 ];
|
|
73
|
-
if ( resultNode ) Observer.set( namespaceObj, event.key, resultNode );
|
|
74
|
-
return next();
|
|
75
|
-
} );
|
|
76
|
-
_( node ).set( 'namespace', namespaceObj );
|
|
77
|
-
}
|
|
78
|
-
return _( node ).get( 'namespace' );
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Performs realtime capture of elements and builds their relationships.
|
|
83
|
-
*
|
|
84
|
-
* @param Object config
|
|
85
|
-
*
|
|
86
|
-
* @return Void
|
|
87
|
-
*/
|
|
88
|
-
function realtime( config ) {
|
|
89
|
-
const window = this, { realdom } = window.webqit;
|
|
90
|
-
// ----------------
|
|
91
|
-
const handle = ( target, entry, incoming ) => {
|
|
92
|
-
const identifier = entry.getAttribute( config.id.attr );
|
|
93
|
-
const ownerRoot = target.closest( config.namespaceSelector ) || _( entry ).get( 'ownerNamespace' ) || window.document;
|
|
94
|
-
const namespaceObj = getNamespaceObject.call( window, ownerRoot, config );
|
|
95
|
-
if ( incoming ) {
|
|
96
|
-
if ( Observer.get( namespaceObj, identifier ) !== entry ) {
|
|
97
|
-
_( entry ).set( 'ownerNamespace', ownerRoot );
|
|
98
|
-
Observer.set( namespaceObj, identifier, entry );
|
|
99
|
-
}
|
|
100
|
-
} else if ( Observer.get( namespaceObj, identifier ) === entry ) {
|
|
101
|
-
_( entry ).delete( 'ownerNamespace' );
|
|
102
|
-
Observer.deleteProperty( namespaceObj, identifier );
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.idSelector, record => {
|
|
106
|
-
record.entrants.forEach( entry => handle( record.target, entry, true ) );
|
|
107
|
-
record.exits.forEach( entry => handle( record.target, entry, false ) );
|
|
108
|
-
}, { live: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
|
|
109
|
-
// ----------------
|
|
110
|
-
if ( config.staticsensitivity ) {
|
|
111
|
-
realdom.realtime( window.document, 'attr' ).observe( config.namespaceSelector, record => {
|
|
112
|
-
const ownerRoot = record.target.parentNode?.closest( config.namespaceSelector ) || _( record.target ).get( 'ownerNamespace' ) || window.document;
|
|
113
|
-
const ownerRootNamespaceObj = getNamespaceObject.call( window, ownerRoot, config );
|
|
114
|
-
const namespaceObj = getNamespaceObject.call( window, record.target, config );
|
|
115
|
-
if ( record.target.matches( config.namespaceSelector ) ) {
|
|
116
|
-
for ( const [ key, entry ] of Object.entries( ownerRootNamespaceObj ) ) {
|
|
117
|
-
if ( !record.target.contains( entry.parentNode ) ) continue;
|
|
118
|
-
Observer.deleteProperty( ownerRootNamespaceObj, key );
|
|
119
|
-
Observer.set( namespaceObj, key, entry );
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
for ( const [ key, entry ] of Object.entries( namespaceObj ) ) {
|
|
123
|
-
Observer.deleteProperty( namespaceObj, key );
|
|
124
|
-
Observer.set( ownerRootNamespaceObj, key, entry );
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}, { subtree: true, timing: 'sync' } );
|
|
128
|
-
}
|
|
129
|
-
// ----------------
|
|
130
|
-
let prevTarget;
|
|
131
|
-
const activateTarget = () => {
|
|
132
|
-
const path = window.location.hash?.substring( 1 ).split( '/' ).map( s => s.trim() ).filter( s => s ) || [];
|
|
133
|
-
const currTarget = path.reduce( ( prev, segment ) => prev && prev[ config.namespace.api ][ segment ], window.document );
|
|
134
|
-
if ( prevTarget && config.target.attr ) { prevTarget.toggleAttribute( config.target.attr, false ); }
|
|
135
|
-
if ( currTarget && currTarget !== window.document ) {
|
|
136
|
-
if ( config.target.attr ) { currTarget.toggleAttribute( config.target.attr, true ); }
|
|
137
|
-
if ( config.target.event ) { currTarget.dispatchEvent( new window.CustomEvent( config.target.event ) ); }
|
|
138
|
-
if ( config.target.scrolling && path.length > 1 ) { currTarget.scrollIntoView(); }
|
|
139
|
-
prevTarget = currTarget;
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
window.addEventListener( 'hashchange', activateTarget );
|
|
143
|
-
realdom.ready( activateTarget );
|
|
144
|
-
}
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import Observer from '@webqit/observer';
|
|
6
|
+
import { _, _init } from '../util.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @init
|
|
10
|
+
*
|
|
11
|
+
* @param Object $config
|
|
12
|
+
*/
|
|
13
|
+
export default function init( $config = {} ) {
|
|
14
|
+
const { config, window } = _init.call( this, 'namespace-api', $config, {
|
|
15
|
+
id: { attr: 'id' },
|
|
16
|
+
namespace: { attr: 'namespace', api: 'namespace', },
|
|
17
|
+
target: { attr: ':target', event: ':target', scrolling: true },
|
|
18
|
+
staticsensitivity: true,
|
|
19
|
+
eagermode: true,
|
|
20
|
+
} );
|
|
21
|
+
config.idSelector = `[${ window.CSS.escape( config.id.attr ) }]`;
|
|
22
|
+
config.namespaceSelector = `[${ window.CSS.escape( config.namespace.attr ) }]`;
|
|
23
|
+
window.webqit.Observer = Observer;
|
|
24
|
+
exposeNamespaceObjects.call( window, config );
|
|
25
|
+
realtime.call( window, config );
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { Observer }
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Exposes Namespaced HTML with native APIs.
|
|
32
|
+
*
|
|
33
|
+
* @param Object config
|
|
34
|
+
*
|
|
35
|
+
* @return Void
|
|
36
|
+
*/
|
|
37
|
+
function exposeNamespaceObjects( config ) {
|
|
38
|
+
const window = this;
|
|
39
|
+
// Assertions
|
|
40
|
+
if ( config.namespace.api in window.document ) { throw new Error( `document already has a "${ config.namespace.api }" property!` ); }
|
|
41
|
+
if ( config.namespace.api in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.namespace.api }" property!` ); }
|
|
42
|
+
// Definitions
|
|
43
|
+
Object.defineProperty( window.document, config.namespace.api, { get: function() {
|
|
44
|
+
return Observer.proxy( getNamespaceObject.call( window, window.document, config ) );
|
|
45
|
+
} });
|
|
46
|
+
Object.defineProperty( window.Element.prototype, config.namespace.api, { get: function() {
|
|
47
|
+
return Observer.proxy( getNamespaceObject.call( window, this, config ) );
|
|
48
|
+
} } );
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Returns the "namespace" object associated with the given node.
|
|
53
|
+
*
|
|
54
|
+
* @param Element node
|
|
55
|
+
*
|
|
56
|
+
* @return Object
|
|
57
|
+
*/
|
|
58
|
+
function getNamespaceObject( node, config ) {
|
|
59
|
+
const window = this;
|
|
60
|
+
if ( !_( node ).has( 'namespace' ) ) {
|
|
61
|
+
const namespaceObj = Object.create( null );
|
|
62
|
+
Observer.intercept( namespaceObj, 'get', ( event, receiver, next ) => {
|
|
63
|
+
if ( Observer.has( namespaceObj, event.key ) || !config.eagermode ) return next();
|
|
64
|
+
const selector = `[${ window.CSS.escape( config.id.attr ) }="${ event.key }"]`;
|
|
65
|
+
const resultNode = Array.from( node.querySelectorAll( selector ) ).filter( idNode => {
|
|
66
|
+
const ownerRoot = idNode.parentNode.closest( config.namespaceSelector );
|
|
67
|
+
if ( node === window.document ) {
|
|
68
|
+
// Only IDs without a scope actually belong to the document scope
|
|
69
|
+
return !ownerRoot;
|
|
70
|
+
}
|
|
71
|
+
return ownerRoot === node;
|
|
72
|
+
} )[ 0 ];
|
|
73
|
+
if ( resultNode ) Observer.set( namespaceObj, event.key, resultNode );
|
|
74
|
+
return next();
|
|
75
|
+
} );
|
|
76
|
+
_( node ).set( 'namespace', namespaceObj );
|
|
77
|
+
}
|
|
78
|
+
return _( node ).get( 'namespace' );
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Performs realtime capture of elements and builds their relationships.
|
|
83
|
+
*
|
|
84
|
+
* @param Object config
|
|
85
|
+
*
|
|
86
|
+
* @return Void
|
|
87
|
+
*/
|
|
88
|
+
function realtime( config ) {
|
|
89
|
+
const window = this, { realdom } = window.webqit;
|
|
90
|
+
// ----------------
|
|
91
|
+
const handle = ( target, entry, incoming ) => {
|
|
92
|
+
const identifier = entry.getAttribute( config.id.attr );
|
|
93
|
+
const ownerRoot = target.closest( config.namespaceSelector ) || _( entry ).get( 'ownerNamespace' ) || window.document;
|
|
94
|
+
const namespaceObj = getNamespaceObject.call( window, ownerRoot, config );
|
|
95
|
+
if ( incoming ) {
|
|
96
|
+
if ( Observer.get( namespaceObj, identifier ) !== entry ) {
|
|
97
|
+
_( entry ).set( 'ownerNamespace', ownerRoot );
|
|
98
|
+
Observer.set( namespaceObj, identifier, entry );
|
|
99
|
+
}
|
|
100
|
+
} else if ( Observer.get( namespaceObj, identifier ) === entry ) {
|
|
101
|
+
_( entry ).delete( 'ownerNamespace' );
|
|
102
|
+
Observer.deleteProperty( namespaceObj, identifier );
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.idSelector, record => {
|
|
106
|
+
record.entrants.forEach( entry => handle( record.target, entry, true ) );
|
|
107
|
+
record.exits.forEach( entry => handle( record.target, entry, false ) );
|
|
108
|
+
}, { live: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
|
|
109
|
+
// ----------------
|
|
110
|
+
if ( config.staticsensitivity ) {
|
|
111
|
+
realdom.realtime( window.document, 'attr' ).observe( config.namespaceSelector, record => {
|
|
112
|
+
const ownerRoot = record.target.parentNode?.closest( config.namespaceSelector ) || _( record.target ).get( 'ownerNamespace' ) || window.document;
|
|
113
|
+
const ownerRootNamespaceObj = getNamespaceObject.call( window, ownerRoot, config );
|
|
114
|
+
const namespaceObj = getNamespaceObject.call( window, record.target, config );
|
|
115
|
+
if ( record.target.matches( config.namespaceSelector ) ) {
|
|
116
|
+
for ( const [ key, entry ] of Object.entries( ownerRootNamespaceObj ) ) {
|
|
117
|
+
if ( !record.target.contains( entry.parentNode ) ) continue;
|
|
118
|
+
Observer.deleteProperty( ownerRootNamespaceObj, key );
|
|
119
|
+
Observer.set( namespaceObj, key, entry );
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
for ( const [ key, entry ] of Object.entries( namespaceObj ) ) {
|
|
123
|
+
Observer.deleteProperty( namespaceObj, key );
|
|
124
|
+
Observer.set( ownerRootNamespaceObj, key, entry );
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}, { subtree: true, timing: 'sync' } );
|
|
128
|
+
}
|
|
129
|
+
// ----------------
|
|
130
|
+
let prevTarget;
|
|
131
|
+
const activateTarget = () => {
|
|
132
|
+
const path = window.location.hash?.substring( 1 ).split( '/' ).map( s => s.trim() ).filter( s => s ) || [];
|
|
133
|
+
const currTarget = path.reduce( ( prev, segment ) => prev && prev[ config.namespace.api ][ segment ], window.document );
|
|
134
|
+
if ( prevTarget && config.target.attr ) { prevTarget.toggleAttribute( config.target.attr, false ); }
|
|
135
|
+
if ( currTarget && currTarget !== window.document ) {
|
|
136
|
+
if ( config.target.attr ) { currTarget.toggleAttribute( config.target.attr, true ); }
|
|
137
|
+
if ( config.target.event ) { currTarget.dispatchEvent( new window.CustomEvent( config.target.event ) ); }
|
|
138
|
+
if ( config.target.scrolling && path.length > 1 ) { currTarget.scrollIntoView(); }
|
|
139
|
+
prevTarget = currTarget;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
window.addEventListener( 'hashchange', activateTarget );
|
|
143
|
+
realdom.ready( activateTarget );
|
|
144
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import init from './index.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @init
|
|
9
|
-
*/
|
|
10
|
-
init.call( window );
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import init from './index.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @init
|
|
9
|
+
*/
|
|
10
|
+
init.call( window );
|
package/src/scoped-css/index.js
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import { _init } from '../util.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @init
|
|
9
|
-
*
|
|
10
|
-
* @param Object $config
|
|
11
|
-
*/
|
|
12
|
-
export default function init( { advanced = {}, ...$config } ) {
|
|
13
|
-
const { config, window } = _init.call( this, 'scoped-css', $config, {
|
|
14
|
-
style: { retention: 'retain', mimeType: '' },
|
|
15
|
-
} );
|
|
16
|
-
config.styleSelector = ( Array.isArray( config.style.mimeType ) ? config.style.mimeType : [ config.style.mimeType ] ).reduce( ( selector, mm ) => {
|
|
17
|
-
const qualifier = mm ? `[type=${ window.CSS.escape( mm ) }]` : '';
|
|
18
|
-
return selector.concat( `style${ qualifier }[scoped]` );
|
|
19
|
-
}, [] ).join( ',' );
|
|
20
|
-
realtime.call( window, config );
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Performs realtime capture of elements and builds their relationships.
|
|
25
|
-
*
|
|
26
|
-
* @param Object config
|
|
27
|
-
*
|
|
28
|
-
* @return Void
|
|
29
|
-
*/
|
|
30
|
-
function realtime( config ) {
|
|
31
|
-
const window = this, { realdom } = window.webqit;
|
|
32
|
-
if ( !window.HTMLScriptElement.supports ) { window.HTMLScriptElement.supports = () => false; }
|
|
33
|
-
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.styleSelector, record => {
|
|
34
|
-
record.entrants.forEach( style => {
|
|
35
|
-
if ( 'scoped' in style ) return handled( style );
|
|
36
|
-
Object.defineProperty( style, 'scoped', { value: style.hasAttribute( 'scoped' ) } );
|
|
37
|
-
if ( style.hasAttribute( 'ref' ) ) return; // Server-rendered
|
|
38
|
-
const uuid = `scoped${ uniqId() }`;
|
|
39
|
-
style.setAttribute( 'ref', uuid );
|
|
40
|
-
style.textContent = `@scope from (:has(> style[ref="${ uuid }"])) {\n${ style.textContent }\n}`;
|
|
41
|
-
} );
|
|
42
|
-
}, { live: true, timing: 'intercept', generation: 'entrants' } );
|
|
43
|
-
// ---
|
|
44
|
-
}
|
|
45
|
-
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import { _init } from '../util.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @init
|
|
9
|
+
*
|
|
10
|
+
* @param Object $config
|
|
11
|
+
*/
|
|
12
|
+
export default function init( { advanced = {}, ...$config } ) {
|
|
13
|
+
const { config, window } = _init.call( this, 'scoped-css', $config, {
|
|
14
|
+
style: { retention: 'retain', mimeType: '' },
|
|
15
|
+
} );
|
|
16
|
+
config.styleSelector = ( Array.isArray( config.style.mimeType ) ? config.style.mimeType : [ config.style.mimeType ] ).reduce( ( selector, mm ) => {
|
|
17
|
+
const qualifier = mm ? `[type=${ window.CSS.escape( mm ) }]` : '';
|
|
18
|
+
return selector.concat( `style${ qualifier }[scoped]` );
|
|
19
|
+
}, [] ).join( ',' );
|
|
20
|
+
realtime.call( window, config );
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Performs realtime capture of elements and builds their relationships.
|
|
25
|
+
*
|
|
26
|
+
* @param Object config
|
|
27
|
+
*
|
|
28
|
+
* @return Void
|
|
29
|
+
*/
|
|
30
|
+
function realtime( config ) {
|
|
31
|
+
const window = this, { realdom } = window.webqit;
|
|
32
|
+
if ( !window.HTMLScriptElement.supports ) { window.HTMLScriptElement.supports = () => false; }
|
|
33
|
+
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.styleSelector, record => {
|
|
34
|
+
record.entrants.forEach( style => {
|
|
35
|
+
if ( 'scoped' in style ) return handled( style );
|
|
36
|
+
Object.defineProperty( style, 'scoped', { value: style.hasAttribute( 'scoped' ) } );
|
|
37
|
+
if ( style.hasAttribute( 'ref' ) ) return; // Server-rendered
|
|
38
|
+
const uuid = `scoped${ uniqId() }`;
|
|
39
|
+
style.setAttribute( 'ref', uuid );
|
|
40
|
+
style.textContent = `@scope from (:has(> style[ref="${ uuid }"])) {\n${ style.textContent }\n}`;
|
|
41
|
+
} );
|
|
42
|
+
}, { live: true, timing: 'intercept', generation: 'entrants' } );
|
|
43
|
+
// ---
|
|
44
|
+
}
|
|
45
|
+
|
|
46
46
|
const uniqId = () => (0|Math.random()*9e6).toString(36);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import init from './index.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @init
|
|
9
|
-
*/
|
|
10
|
-
init.call( window );
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import init from './index.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @init
|
|
9
|
+
*/
|
|
10
|
+
init.call( window );
|