@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.
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,199 +1,185 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import Observer from '@webqit/observer';
6
- import { getModulesObject } from './index.js';
7
- import { _ } from '../util.js';
8
-
9
- export default class HTMLExportsManager {
10
-
11
- /**
12
- * @instance
13
- */
14
- static instance( window, host, config ) {
15
- return _( host ).get( 'exportsmanager::instance' ) || new this( window, host, config );
16
- }
17
-
18
- /**
19
- * @constructor
20
- */
21
- constructor( window, host, config = {}, parent = null, level = 0 ) {
22
- _( host ).get( `exportsmanager::instance` )?.dispose();
23
- _( host ).set( `exportsmanager::instance`, this );
24
- this.host = host;
25
- this.window = window;
26
- this.config = config;
27
- this.parent = parent;
28
- this.level = level;
29
- this.modules = getModulesObject( this.host );
30
- this.exportId = ( this.host.getAttribute( this.config.template?.attr.exportid ) || '' ).trim();
31
- this.validateExportId( this.exportId );
32
- const realdom = this.window.webqit.realdom;
33
- // ----------
34
- this.realtimeA = realdom.realtime( this.host.content ).children( record => {
35
- this.export( record.entrants, true );
36
- this.export( record.exits, false );
37
- }, { live: true, timing: 'sync' } );
38
- // ----------
39
- this.realtimeB = realdom.realtime( this.host ).attr( [ 'src', 'loading' ], ( ...args ) => this.evaluateLoading( ...args ), {
40
- live: true,
41
- atomic: true,
42
- timing: 'sync',
43
- lifecycleSignals: true
44
- } );
45
- // ----------
46
- this.realtimeC = this.evalInheritance();
47
- // ----------
48
- }
49
-
50
- /**
51
- * Validates export ID.
52
- *
53
- * @param String exportId
54
- *
55
- * @returns Void
56
- */
57
- validateExportId( exportId ) {
58
- if ( [ '@', '#', ':' ].some( token => exportId.includes( token ) ) ) {
59
- throw new Error( `The export ID "${ exportId }" contains an invalid character.` );
60
- }
61
- }
62
-
63
- /**
64
- * Maps module contents as exports.
65
- *
66
- * @param Array entries
67
- * @param Bool isConnected
68
- *
69
- * @returns Void
70
- */
71
- export( entries, isConnected ) {
72
- const fragmentsExports = new Map;
73
- entries.forEach( entry => {
74
- if ( entry.nodeType !== 1 ) return;
75
- const exportId = ( entry.getAttribute( this.config.export.attr.exportid ) || '' ).trim() || '#default';
76
- const isPackage = entry.matches( this.config.templateSelector );
77
- if ( exportId.startsWith( '#' ) ) {
78
- this.validateExportId( exportId.substring( 1 ) );
79
- if ( !fragmentsExports.has( exportId ) ) { fragmentsExports.set( exportId, [] ); }
80
- fragmentsExports.get( exportId ).push( entry );
81
- } else {
82
- if ( isConnected ) {
83
- if ( isPackage ) { new HTMLExportsManager( this.window, entry, this.config, this.host, this.level + 1 ); }
84
- Observer.set( this.modules, exportId, entry );
85
- } else {
86
- if ( isPackage ) { HTMLExportsManager.instance( this.window, entry ).dispose(); }
87
- Observer.deleteProperty( this.modules, exportId );
88
- }
89
- }
90
- } );
91
- // ----------------
92
- fragmentsExports.forEach( ( fragments, exportId ) => {
93
- let existingFragments = Observer.get( this.modules, exportId );
94
- if ( isConnected ) {
95
- existingFragments = new Set( ( existingFragments ? [ ...existingFragments ] : [] ).concat( fragments ) );
96
- } else if ( existingFragments ) {
97
- fragments.forEach( el => existingFragments.delete( el ) );
98
- }
99
- if ( !isConnected && !existingFragments.size ) { Observer.deleteProperty( this.modules, exportId ); }
100
- else { Observer.set( this.modules, exportId, existingFragments ) }
101
- } );
102
- }
103
-
104
- /**
105
- * Evaluates remote content loading.
106
- *
107
- * @param AbortSignal signal
108
- *
109
- * @returns Void
110
- */
111
- evaluateLoading( [ record1, record2 ], { signal } ) {
112
- const src = ( record1.value || '' ).trim();
113
- if ( !src ) return;
114
- const loading = ( record2.value || '' ).trim();
115
- if ( loading === 'lazy' ) {
116
- const interception = Observer.intercept( this.modules, 'get', async ( descriptor, recieved, next ) => {
117
- await this.load( src, true );
118
- interception.remove();
119
- return next();
120
- }, { signal } );
121
- } else { this.load( src ); }
122
- }
123
-
124
- /**
125
- * Fetches a module's "src".
126
- *
127
- * @param String src
128
- *
129
- * @return Promise
130
- */
131
- load( src ) {
132
- if ( this.host.content.children.length ) return;
133
- // Ongoing request?
134
- if ( this.fetchInFlight?.src === src ) return this.fetchInFlight.request;
135
- this.fetchInFlight?.controller.abort();
136
- // The promise
137
- const controller = new AbortController();
138
- const fire = ( type, detail ) => this.host.dispatchEvent( new this.window.CustomEvent( type, { detail } ) );
139
- const request = this.window.fetch( src, { signal: controller.signal, element: this.host } ).then( response => {
140
- return response.ok ? response.text() : Promise.reject( response.statusText );
141
- }).then( content => {
142
- this.host.innerHTML = content.trim(); // IMPORTANT: .trim()
143
- fire( 'load' );
144
- return this.host;
145
- } ).catch( e => {
146
- console.error( `Error fetching the bundle at "${ src }": ${ e.message }` );
147
- this.fetchInFlight = null;
148
- fire( 'loaderror' );
149
- return this.host;
150
- } );
151
- this.fetchInFlight = { src, request, controller };
152
- return request;
153
- }
154
-
155
- /**
156
- * Evaluates module inheritance.
157
- *
158
- * @returns Void|AbortController
159
- */
160
- evalInheritance( ) {
161
- if ( !this.parent ) return [];
162
- let extendedId = ( this.host.getAttribute( this.config.template.attr.extends ) || '' ).trim();
163
- let inheritedIds = ( this.host.getAttribute( this.config.template.attr.inherits ) || '' ).trim();
164
- const handleInherited = records => {
165
- records.forEach( record => {
166
- if ( Observer.get( this.modules, record.key ) !== record.oldValue ) return;
167
- if ( [ 'get'/*initial get*/, 'set', 'defineProperty' ].includes( record.type ) ) {
168
- Observer[ record.type.replace( 'get', 'set' ) ]( this.modules, record.key, record.value );
169
- } else if ( record.type === 'deleteProperty' ) {
170
- Observer.deleteProperty( this.modules, record.key );
171
- }
172
- } );
173
- };
174
- const realtimes = [];
175
- const parentExportsObj = getModulesObject( this.parent );
176
- if ( extendedId ) {
177
- realtimes.push( Observer.deep( parentExportsObj, [ extendedId, this.config.template.api.modules, Infinity ], Observer.get, handleInherited, { live: true } ) );
178
- }
179
- if ( ( inheritedIds = inheritedIds.split( ' ' ).map( id => id.trim() ).filter( x => x ) ).length ) {
180
- realtimes.push( Observer.get( parentExportsObj, inheritedIds, handleInherited, { live: true } ) );
181
- }
182
- return realtimes;
183
- }
184
-
185
- /**
186
- * Disposes the instance and its processes.
187
- *
188
- * @returns Void
189
- */
190
- dispose() {
191
- this.realtimeA.disconnect();
192
- this.realtimeB.disconnect();
193
- this.realtimeC.forEach( r => r.abort() );
194
- Object.entries( this.modules ).forEach( ( [ key, entry ] ) => {
195
- if ( key.startsWith( '#' ) ) return;
196
- HTMLExportsManager.instance( this.window, entry ).dispose();
197
- } );
198
- }
199
- }
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import Observer from '@webqit/observer';
6
+ import { getModulesObject } from './index.js';
7
+ import { _ } from '../util.js';
8
+
9
+ export default class _HTMLExportsManager {
10
+
11
+ /**
12
+ * @instance
13
+ */
14
+ static instance( window, host, config ) {
15
+ return _( host ).get( 'exportsmanager::instance' ) || new this( window, host, config );
16
+ }
17
+
18
+ /**
19
+ * @constructor
20
+ */
21
+ constructor( window, host, config = {}, parent = null, level = 0 ) {
22
+ _( host ).get( `exportsmanager::instance` )?.dispose();
23
+ _( host ).set( `exportsmanager::instance`, this );
24
+ this.host = host;
25
+ this.window = window;
26
+ this.config = config;
27
+ this.parent = parent;
28
+ this.level = level;
29
+ this.modules = getModulesObject( this.host );
30
+ this.exportId = ( this.host.getAttribute( this.config.template?.attr.exportid ) || '' ).trim();
31
+ this.validateExportId( this.exportId );
32
+ const realdom = this.window.webqit.realdom;
33
+ // ----------
34
+ this.realtimeA = realdom.realtime( this.host.content ).children( record => {
35
+ this.export( record.entrants, true );
36
+ this.export( record.exits, false );
37
+ }, { live: true, timing: 'sync' } );
38
+ // ----------
39
+ this.realtimeB = realdom.realtime( this.host ).attr( [ 'src', 'loading' ], ( ...args ) => this.evaluateLoading( ...args ), {
40
+ live: true,
41
+ atomic: true,
42
+ timing: 'sync',
43
+ lifecycleSignals: true
44
+ } );
45
+ // ----------
46
+ this.realtimeC = this.evalInheritance();
47
+ // ----------
48
+ }
49
+
50
+ /**
51
+ * Validates export ID.
52
+ *
53
+ * @param String exportId
54
+ *
55
+ * @returns Void
56
+ */
57
+ validateExportId( exportId ) {
58
+ if ( [ '@', '/', '#' ].some( token => exportId.includes( token ) ) ) {
59
+ throw new Error( `The export ID "${ exportId }" contains an invalid character.` );
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Maps module contents as exports.
65
+ *
66
+ * @param Array entries
67
+ * @param Bool isConnected
68
+ *
69
+ * @returns Void
70
+ */
71
+ export( entries, isConnected ) {
72
+ entries.forEach( entry => {
73
+ if ( entry.nodeType !== 1 ) return;
74
+ const exportId = ( entry.getAttribute( this.config.export.attr.exportid ) || '' ).trim();
75
+ if ( !exportId ) return;
76
+ const isPackage = entry.matches( this.config.templateSelector );
77
+ if ( isConnected ) {
78
+ if ( isPackage ) { new _HTMLExportsManager( this.window, entry, this.config, this.host, this.level + 1 ); }
79
+ Observer.set( this.modules, ( !isPackage && '#' || '' ) + exportId, entry );
80
+ } else {
81
+ if ( isPackage ) { _HTMLExportsManager.instance( this.window, entry ).dispose(); }
82
+ Observer.deleteProperty( this.modules, ( !isPackage && '#' || '' ) + exportId );
83
+ }
84
+ } );
85
+ }
86
+
87
+ /**
88
+ * Evaluates remote content loading.
89
+ *
90
+ * @param AbortSignal signal
91
+ *
92
+ * @returns Void
93
+ */
94
+ evaluateLoading( [ record1, record2 ], { signal } ) {
95
+ const src = ( record1.value || '' ).trim();
96
+ if ( !src ) return;
97
+ let $loadingPromise, loadingPromise = promise => {
98
+ if ( !promise ) return $loadingPromise; // Get
99
+ $loadingPromise = promise.then( () => interception.remove() ); // Set
100
+ };
101
+ const loading = ( record2.value || '' ).trim();
102
+ const interception = Observer.intercept( this.modules, 'get', async ( descriptor, recieved, next ) => {
103
+ if ( loading === 'lazy' ) { loadingPromise( this.load( src, true ) ); }
104
+ await loadingPromise();
105
+ return next();
106
+ }, { signal } );
107
+ if ( loading !== 'lazy' ) { loadingPromise( this.load( src ) ); }
108
+ }
109
+
110
+ /**
111
+ * Fetches a module's "src".
112
+ *
113
+ * @param String src
114
+ *
115
+ * @return Promise
116
+ */
117
+ load( src ) {
118
+ if ( this.host.content.children.length ) return Promise.resolve();
119
+ // Ongoing request?
120
+ if ( this.fetchInFlight?.src === src ) return this.fetchInFlight.request;
121
+ this.fetchInFlight?.controller.abort();
122
+ // The promise
123
+ const controller = new AbortController();
124
+ const fire = ( type, detail ) => this.host.dispatchEvent( new this.window.CustomEvent( type, { detail } ) );
125
+ const request = this.window.fetch( src, { signal: controller.signal, element: this.host } ).then( response => {
126
+ return response.ok ? response.text() : Promise.reject( response.statusText );
127
+ }).then( content => {
128
+ this.host.innerHTML = content.trim(); // IMPORTANT: .trim()
129
+ fire( 'load' );
130
+ return this.host;
131
+ } ).catch( e => {
132
+ console.error( `Error fetching the bundle at "${ src }": ${ e.message }` );
133
+ this.fetchInFlight = null;
134
+ fire( 'loaderror' );
135
+ return this.host;
136
+ } );
137
+ this.fetchInFlight = { src, request, controller };
138
+ return request;
139
+ }
140
+
141
+ /**
142
+ * Evaluates module inheritance.
143
+ *
144
+ * @returns Void|AbortController
145
+ */
146
+ evalInheritance( ) {
147
+ if ( !this.parent ) return [];
148
+ let extendedId = ( this.host.getAttribute( this.config.template.attr.extends ) || '' ).trim();
149
+ let inheritedIds = ( this.host.getAttribute( this.config.template.attr.inherits ) || '' ).trim();
150
+ const handleInherited = records => {
151
+ records.forEach( record => {
152
+ if ( Observer.get( this.modules, record.key ) !== record.oldValue ) return;
153
+ if ( [ 'get'/*initial get*/, 'set', 'defineProperty' ].includes( record.type ) ) {
154
+ Observer[ record.type.replace( 'get', 'set' ) ]( this.modules, record.key, record.value );
155
+ } else if ( record.type === 'deleteProperty' ) {
156
+ Observer.deleteProperty( this.modules, record.key );
157
+ }
158
+ } );
159
+ };
160
+ const realtimes = [];
161
+ const parentExportsObj = getModulesObject( this.parent );
162
+ if ( extendedId ) {
163
+ realtimes.push( Observer.deep( parentExportsObj, [ extendedId, this.config.template.api.modules, Infinity ], Observer.get, handleInherited, { live: true } ) );
164
+ }
165
+ if ( ( inheritedIds = inheritedIds.split( ' ' ).map( id => id.trim() ).filter( x => x ) ).length ) {
166
+ realtimes.push( Observer.get( parentExportsObj, inheritedIds, handleInherited, { live: true } ) );
167
+ }
168
+ return realtimes;
169
+ }
170
+
171
+ /**
172
+ * Disposes the instance and its processes.
173
+ *
174
+ * @returns Void
175
+ */
176
+ dispose() {
177
+ this.realtimeA.disconnect();
178
+ this.realtimeB.disconnect();
179
+ this.realtimeC.forEach( r => r.abort() );
180
+ Object.entries( this.modules ).forEach( ( [ key, entry ] ) => {
181
+ if ( key.startsWith( '#' ) ) return;
182
+ _HTMLExportsManager.instance( this.window, entry ).dispose();
183
+ } );
184
+ }
185
+ }