@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/README.md +212 -217
- package/dist/bindings-api.js +1 -1
- package/dist/bindings-api.js.map +2 -2
- package/dist/context-api.js +1 -1
- package/dist/context-api.js.map +1 -1
- package/dist/data-binding.js +8 -8
- package/dist/data-binding.js.map +2 -2
- package/dist/html-imports.js +1 -1
- package/dist/html-imports.js.map +2 -2
- package/dist/main.js +22 -24
- package/dist/main.js.map +3 -3
- package/dist/main.lite.js +20 -22
- package/dist/main.lite.js.map +3 -3
- package/dist/namespaced-html.js +1 -1
- package/dist/namespaced-html.js.map +3 -3
- package/dist/scoped-css.js +1 -3
- package/dist/scoped-css.js.map +3 -3
- package/dist/scoped-js.js +1 -1
- package/dist/scoped-js.js.map +3 -3
- package/package.json +2 -2
- package/src/bindings-api/DOMBindingsContext.js +1 -1
- package/src/bindings-api/index.js +21 -21
- package/src/data-binding/index.js +4 -19
- package/src/html-imports/HTMLImportsContext.js +1 -3
- package/src/html-imports/index.js +7 -1
- package/src/index.js +3 -3
- package/src/namespaced-html/DOMNamingContext.js +54 -0
- package/src/namespaced-html/index.js +287 -60
- package/src/scoped-css/index.js +114 -16
- package/src/scoped-js/index.js +48 -25
- package/src/util.js +38 -0
- package/test/scoped-css.test.js +2 -2
- package/src/scoped-js/Hash.js +0 -26
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.
|
|
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
|
|
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"
|
|
@@ -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 =
|
|
160
|
-
const [ left, right ] =
|
|
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 ] =
|
|
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
|
+
}
|