@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,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 );
@@ -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 );