@webqit/oohtml 3.1.13 → 3.1.15

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/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "wicg-proposal"
15
15
  ],
16
16
  "homepage": "https://webqit.io/tooling/oohtml",
17
- "version": "3.1.13",
17
+ "version": "3.1.15",
18
18
  "license": "MIT",
19
19
  "repository": {
20
20
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  "scripts": {
30
30
  "test": "mocha --extension .test.js --exit",
31
31
  "test:coverage": "c8 --reporter=text-lcov npm run test | coveralls",
32
- "build": "esbuild main=src/api.global.js main.lite=src/api.global.lite.js namespaced-html=src/namespaced-html/targets.browser.js scoped-css=src/scoped-css/targets.browser.js scoped-js=src/scoped-js/targets.browser.js context-api=src/context-api/targets.browser.js bindings-api=src/bindings-api/targets.browser.js html-imports=src/html-imports/targets.browser.js data-binding=src/data-binding/targets.browser.js --bundle --minify --sourcemap --outdir=dist",
32
+ "build": "esbuild main=src/api.global.js main.lite=src/api.global.lite.js context-api=src/context-api/targets.browser.js bindings-api=src/bindings-api/targets.browser.js namespaced-html=src/namespaced-html/targets.browser.js html-imports=src/html-imports/targets.browser.js data-binding=src/data-binding/targets.browser.js scoped-css=src/scoped-css/targets.browser.js scoped-js=src/scoped-js/targets.browser.js --bundle --minify --sourcemap --outdir=dist",
33
33
  "preversion": "npm run test && npm run build && git add -A dist",
34
34
  "postversion": "npm publish",
35
35
  "postpublish": "git push && git push --tags"
@@ -52,5 +52,5 @@ export default class DOMBindingsContext extends DOMContext {
52
52
  /**
53
53
  * @unsubscribed()
54
54
  */
55
- unsubscribed( event ) { event._controller?.abort(); }
55
+ unsubscribed( event ) { event._controller?.abort(); }
56
56
  }
@@ -55,27 +55,6 @@ function getBindings( config, node ) {
55
55
  return _( node ).get( 'bindings' );
56
56
  }
57
57
 
58
- /**
59
- * Exposes Bindings with native APIs.
60
- *
61
- * @param Object config
62
- * @param document|Element target
63
- * @param Object bindings
64
- * @param Object params
65
- *
66
- * @return Void
67
- */
68
- function applyBindings( config, target, bindings, { merge, diff, namespace } = {} ) {
69
- const window = this, { webqit: { Observer } } = window;
70
- const bindingsObj = getBindings.call( this, config, target );
71
- const $params = { diff, namespace };
72
- const exitingKeys = merge ? [] : Observer.ownKeys( bindingsObj, $params ).filter( key => !( key in bindings ) );
73
- return Observer.batch( bindingsObj, () => {
74
- if ( exitingKeys.length ) { Observer.deleteProperties( bindingsObj, exitingKeys, $params ); }
75
- return Observer.set( bindingsObj, bindings, $params );
76
- }, $params );
77
- }
78
-
79
58
  /**
80
59
  * Exposes Bindings with native APIs.
81
60
  *
@@ -104,3 +83,24 @@ function exposeAPIs( config ) {
104
83
  return Observer.proxy( getBindings.call( window, config, this ) );
105
84
  } } );
106
85
  }
86
+
87
+ /**
88
+ * Exposes Bindings with native APIs.
89
+ *
90
+ * @param Object config
91
+ * @param document|Element target
92
+ * @param Object bindings
93
+ * @param Object params
94
+ *
95
+ * @return Void
96
+ */
97
+ function applyBindings( config, target, bindings, { merge, diff, namespace } = {} ) {
98
+ const window = this, { webqit: { Observer } } = window;
99
+ const bindingsObj = getBindings.call( this, config, target );
100
+ const $params = { diff, namespace };
101
+ const exitingKeys = merge ? [] : Observer.ownKeys( bindingsObj, $params ).filter( key => !( key in bindings ) );
102
+ return Observer.batch( bindingsObj, () => {
103
+ if ( exitingKeys.length ) { Observer.deleteProperties( bindingsObj, exitingKeys, $params ); }
104
+ return Observer.set( bindingsObj, bindings, $params );
105
+ }, $params );
106
+ }
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * @imports
4
4
  */
5
- import { _, _init } from '../util.js';
5
+ import { _, _init, _splitOuter } from '../util.js';
6
6
 
7
7
  /**
8
8
  * Initializes DOM Parts.
@@ -156,8 +156,8 @@ const inlineParseCache = new Map;
156
156
  function compileInlineBindings( config, str ) {
157
157
  if ( inlineParseCache.has( str ) ) return inlineParseCache.get( str );
158
158
  const validation = {};
159
- const source = splitOuter( str, ';' ).map( str => {
160
- const [ left, right ] = splitOuter( str, ':' ).map( x => x.trim() );
159
+ const source = _splitOuter( str, ';' ).map( str => {
160
+ const [ left, right ] = _splitOuter( str, ':' ).map( x => x.trim() );
161
161
  const directive = left[ 0 ], param = left.slice( 1 ).trim();
162
162
  const arg = `(${ right })`, $arg = `(${ arg } ?? '')`;
163
163
  if ( directive === '&' ) {
@@ -175,7 +175,7 @@ function compileInlineBindings( config, str ) {
175
175
  if ( param === 'text' ) return `$assign__(this, 'textContent', ${ $arg });`;
176
176
  if ( param === 'html' ) return `$exec__(this, 'setHTML', ${ $arg });`;
177
177
  if ( param === 'items' ) {
178
- const [ iterationSpec, importSpec ] = splitOuter( right, '/' );
178
+ const [ iterationSpec, importSpec ] = _splitOuter( right, '/' );
179
179
  if ( !importSpec ) throw new Error( `Invalid ${ directive }items spec: ${ str }; no import specifier.` );
180
180
  let [ raw, production, kind, iteratee ] = iterationSpec.trim().match( /(.*?[\)\s+])(of|in)([\(\{\[\s+].*)/i ) || [];
181
181
  if ( !raw ) throw new Error( `Invalid ${ directive }items spec: ${ str }.` );
@@ -227,19 +227,4 @@ function compileInlineBindings( config, str ) {
227
227
  return compiled;
228
228
  }
229
229
 
230
- export function splitOuter( str, delim ) {
231
- return [ ...str ].reduce( ( [ quote, depth, splits, skip ], x ) => {
232
- if ( !quote && depth === 0 && ( Array.isArray( delim ) ? delim : [ delim ] ).includes( x ) ) {
233
- return [ quote, depth, [ '' ].concat( splits ) ];
234
- }
235
- if ( !quote && [ '(', '[', '{' ].includes( x ) && !splits[ 0 ].endsWith( '\\' ) ) depth++;
236
- if ( !quote && [ ')', ']', '}' ].includes( x ) && !splits[ 0 ].endsWith( '\\' ) ) depth--;
237
- if ( [ '"', "'", '`' ].includes( x ) && !splits[ 0 ].endsWith( '\\' ) ) {
238
- quote = quote === x ? null : ( quote || x );
239
- }
240
- splits[ 0 ] += x;
241
- return [ quote, depth, splits ]
242
- }, [ null, 0, [ '' ] ] )[ 2 ].reverse();
243
- }
244
-
245
230
  const escDouble = str => str.replace(/"/g, '\\"');
@@ -44,11 +44,9 @@ export default class HTMLImportsContext extends DOMContext {
44
44
 
45
45
  // Parse and translate detail
46
46
  if ( ( event.detail || '' ).trim() === '/' ) return event.respondWith( this.localModules );
47
- const $config = this.configs.HTML_IMPORTS;
48
47
  let path = ( event.detail || '' ).split( /\/|(?<=\w)(?=#)/g ).map( x => x.trim() ).filter( x => x );
49
- if ( path.length ) { path = path.join( `/${ $config.api.defs }/` )?.split( '/' ) || []; }
50
- // No detail?
51
48
  if ( !path.length ) return event.respondWith();
49
+ path = path.join( `/${ this.configs.HTML_IMPORTS.api.defs }/` )?.split( '/' ) || [];
52
50
 
53
51
 
54
52
  // We'll now fulfill request
@@ -73,6 +73,11 @@ function exposeAPIs( config ) {
73
73
  Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.def, { get: function() {
74
74
  return this.getAttribute( config.attr.def );
75
75
  } } );
76
+ Object.defineProperty( window.HTMLTemplateElement.prototype, 'scoped', {
77
+ configurable: true,
78
+ get() { return this.hasAttribute( 'scoped' ); },
79
+ set( value ) { this.toggleAttribute( 'scoped', value ); },
80
+ } );
76
81
  Object.defineProperty( window.document, config.api.import, { value: function( ref, live = false, callback = null ) {
77
82
  return importRequest( window.document, ...arguments );
78
83
  } } );
@@ -102,6 +107,7 @@ function exposeAPIs( config ) {
102
107
  */
103
108
  function realtime( config ) {
104
109
  const window = this, { webqit: { Observer, realdom, oohtml: { configs }, HTMLImportElement, HTMLImportsContext } } = window;
110
+
105
111
  // ------------
106
112
  // MODULES
107
113
  // ------------
@@ -124,7 +130,6 @@ function realtime( config ) {
124
130
  realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( [ config.templateSelector, config.importsContextSelector ], record => {
125
131
  record.entrants.forEach( entry => {
126
132
  if ( entry.matches( config.templateSelector ) ) {
127
- Object.defineProperty( entry, 'scoped', { value: entry.hasAttribute( 'scoped' ) } );
128
133
  const htmlModule = HTMLModule.instance( entry );
129
134
  htmlModule.ownerContext = entry.scoped ? record.target : window.document;
130
135
  const ownerContextModulesObj = getDefs( htmlModule.ownerContext );
@@ -148,6 +153,7 @@ function realtime( config ) {
148
153
  }
149
154
  } );
150
155
  }, { live: true, timing: 'sync', staticSensitivity: true } );
156
+
151
157
  // ------------
152
158
  // IMPORTS
153
159
  // ------------
package/src/index.js CHANGED
@@ -17,12 +17,12 @@ export default function init( QuantumJS, configs = {} ) {
17
17
  if ( !this.webqit ) { this.webqit = {}; }
18
18
  Object.assign( this.webqit, QuantumJS );
19
19
  // --------------
20
- NamespacedHTML.call( this, ( configs.NAMESPACED_HTML || {} ) );
21
- ScopedCSS.call( this, ( configs.SCOPED_CSS || {} ) );
22
- ScopedJS.call( this, ( configs.SCOPED_JS || {} ) );
23
20
  ContextAPI.call( this, ( configs.CONTEXT_API || {} ) );
24
21
  BindingsAPI.call( this, ( configs.BINDINGS_API || {} ) ); // Depends on ContextAPI
22
+ NamespacedHTML.call( this, ( configs.NAMESPACED_HTML || {} ) ); // Depends on ContextAPI
25
23
  HTMLImports.call( this, ( configs.HTML_IMPORTS || {} ) ); // Depends on ContextAPI
26
24
  DataBinding.call( this, ( configs.DATA_BINDING || {} ) ); // Depends on ContextAPI, BindingsAPI, HTMLImports
25
+ ScopedCSS.call( this, ( configs.SCOPED_CSS || {} ) ); // Depends on NamespacedHTML
26
+ ScopedJS.call( this, ( configs.SCOPED_JS || {} ) );
27
27
  // --------------
28
28
  }
@@ -0,0 +1,54 @@
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import DOMContext from '../context-api/DOMContext.js';
6
+ import { env } from '../util.js';
7
+
8
+ export default class DOMNamingContext extends DOMContext {
9
+
10
+ static kind = 'namespace';
11
+
12
+ /**
13
+ * @createRequest
14
+ */
15
+ static createRequest( detail = null ) {
16
+ const request = super.createRequest();
17
+ if ( detail?.startsWith( '@' ) ) {
18
+ const [ targetContext, ...detail ] = detail.slice( 1 ).split( '/' ).map( s => s.trim() );
19
+ request.targetContext = targetContext;
20
+ request.detail = detail.join( '/' );
21
+ } else { request.detail = detail; }
22
+ return request;
23
+ }
24
+
25
+ /**
26
+ * @namespaceObj
27
+ */
28
+ get namespaceObj() { return this.host[ this.configs.NAMESPACED_HTML.api.namespace ]; }
29
+
30
+ /**
31
+ * @handle()
32
+ */
33
+ handle( event ) {
34
+ const { window: { webqit: { Observer } } } = env;
35
+ // Any existing event._controller? Abort!
36
+ event._controller?.abort();
37
+
38
+ // Parse and translate detail
39
+ if ( !( event.detail || '' ).trim() ) return event.respondWith( Observer.unproxy( this.namespaceObj ) );
40
+ let path = ( event.detail || '' ).split( '/' ).map( x => x.trim() ).filter( x => x );
41
+ if ( !path.length ) return event.respondWith();
42
+ path = path.join( `/${ this.configs.NAMESPACED_HTML.api.namespace }/` )?.split( '/' ) || [];
43
+
44
+ event._controller = Observer.reduce( this.namespaceObj, path, Observer.get, descriptor => {
45
+ if ( this.disposed ) return; // If already scheduled but aborted as in provider unmounting
46
+ event.respondWith( descriptor.value );
47
+ }, { live: event.live, signal: event.signal, descripted: true } );
48
+ }
49
+
50
+ /**
51
+ * @unsubscribed()
52
+ */
53
+ unsubscribed( event ) { event._controller?.abort(); }
54
+ }