@webqit/oohtml 3.1.12 → 3.1.14
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 +2 -2
- 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 +25 -23
- package/dist/main.js.map +3 -3
- package/dist/main.lite.js +25 -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 +5 -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 +3 -3
- package/src/bindings-api/DOMBindingsContext.js +1 -1
- package/src/bindings-api/index.js +22 -22
- package/src/data-binding/index.js +4 -19
- package/src/html-imports/HTMLImportsContext.js +4 -6
- package/src/html-imports/HTMLModule.js +5 -5
- package/src/html-imports/index.js +11 -5
- package/src/index.js +3 -3
- package/src/namespaced-html/DOMNamingContext.js +54 -0
- package/src/namespaced-html/index.js +237 -60
- package/src/scoped-css/index.js +108 -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.14",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
@@ -29,13 +29,13 @@
|
|
|
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"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@webqit/quantum-js": "^4.2.
|
|
38
|
+
"@webqit/quantum-js": "^4.2.11",
|
|
39
39
|
"@webqit/realdom": "^2.1.22",
|
|
40
40
|
"@webqit/util": "^0.8.11"
|
|
41
41
|
},
|
|
@@ -20,7 +20,7 @@ export default function init( $config = {} ) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* @
|
|
23
|
+
* @Defs
|
|
24
24
|
*
|
|
25
25
|
* The internal bindings object
|
|
26
26
|
* within elements and the document object.
|
|
@@ -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, '\\"');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @imports
|
|
4
4
|
*/
|
|
5
5
|
import DOMContext from '../context-api/DOMContext.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getDefs } from './index.js';
|
|
7
7
|
import { _, env } from '../util.js';
|
|
8
8
|
|
|
9
9
|
export default class HTMLImportsContext extends DOMContext {
|
|
@@ -32,7 +32,7 @@ export default class HTMLImportsContext extends DOMContext {
|
|
|
32
32
|
/**
|
|
33
33
|
* @localModules
|
|
34
34
|
*/
|
|
35
|
-
get localModules() { return
|
|
35
|
+
get localModules() { return getDefs( this.host ); }
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* @handle()
|
|
@@ -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
|
|
@@ -102,7 +100,7 @@ export default class HTMLImportsContext extends DOMContext {
|
|
|
102
100
|
// This superModules contextrequest is automatically aborted by the injected signal below
|
|
103
101
|
const request = { ...this.constructor.createRequest( record.value.trim() ), live: true, signal };
|
|
104
102
|
this.host.parentNode[ this.configs.CONTEXT_API.api.contexts ].request( request, response => {
|
|
105
|
-
this.contextModules = !( response && Object.getPrototypeOf( response ) ) ? response :
|
|
103
|
+
this.contextModules = !( response && Object.getPrototypeOf( response ) ) ? response : getDefs( response );
|
|
106
104
|
update();
|
|
107
105
|
} );
|
|
108
106
|
}, { live: true, timing: 'sync', lifecycleSignals: true } );
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @imports
|
|
4
4
|
*/
|
|
5
5
|
import { _isNumeric } from '@webqit/util/js/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getDefs } from './index.js';
|
|
7
7
|
import { _, env } from '../util.js';
|
|
8
8
|
|
|
9
9
|
export default class HTMLModule {
|
|
@@ -26,7 +26,7 @@ export default class HTMLModule {
|
|
|
26
26
|
this.config = configs.HTML_IMPORTS;
|
|
27
27
|
this.parent = parent;
|
|
28
28
|
this.level = level;
|
|
29
|
-
this.defs =
|
|
29
|
+
this.defs = getDefs( this.host );
|
|
30
30
|
this.defId = ( this.host.getAttribute( this.config.attr.def ) || '' ).trim();
|
|
31
31
|
this.validateDefId( this.defId );
|
|
32
32
|
// ----------
|
|
@@ -175,12 +175,12 @@ export default class HTMLModule {
|
|
|
175
175
|
} );
|
|
176
176
|
};
|
|
177
177
|
const realtimes = [];
|
|
178
|
-
const
|
|
178
|
+
const parentDefsObj = getDefs( this.parent );
|
|
179
179
|
if ( extendedId ) {
|
|
180
|
-
realtimes.push( Observer.reduce(
|
|
180
|
+
realtimes.push( Observer.reduce( parentDefsObj, [ extendedId, this.config.api.defs, Infinity ], Observer.get, handleInherited, { live: true } ) );
|
|
181
181
|
}
|
|
182
182
|
if ( ( inheritedIds = inheritedIds.split( ' ' ).map( id => id.trim() ).filter( x => x ) ).length ) {
|
|
183
|
-
realtimes.push( Observer.get(
|
|
183
|
+
realtimes.push( Observer.get( parentDefsObj, inheritedIds, handleInherited, { live: true } ) );
|
|
184
184
|
}
|
|
185
185
|
return realtimes;
|
|
186
186
|
}
|
|
@@ -44,7 +44,7 @@ export default function init( $config = {} ) {
|
|
|
44
44
|
*
|
|
45
45
|
* @return Object
|
|
46
46
|
*/
|
|
47
|
-
export function
|
|
47
|
+
export function getDefs( node, autoCreate = true ) {
|
|
48
48
|
if ( !_( node ).has( 'defs' ) && autoCreate ) {
|
|
49
49
|
const defs = Object.create( null );
|
|
50
50
|
_( node ).set( 'defs', defs );
|
|
@@ -68,11 +68,16 @@ function exposeAPIs( config ) {
|
|
|
68
68
|
if ( config.api.import in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.api.import }" property!` ); }
|
|
69
69
|
// Definitions
|
|
70
70
|
Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.defs, { get: function() {
|
|
71
|
-
return
|
|
71
|
+
return getDefs( this );
|
|
72
72
|
} } );
|
|
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,10 +130,9 @@ 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
|
-
const ownerContextModulesObj =
|
|
135
|
+
const ownerContextModulesObj = getDefs( htmlModule.ownerContext );
|
|
131
136
|
if ( htmlModule.defId ) { Observer.set( ownerContextModulesObj, htmlModule.defId, entry ); }
|
|
132
137
|
// The ownerContext's defs - ownerContextModulesObj - has to be populated
|
|
133
138
|
// Before attaching a context instance to it, to give the just created context something to use for
|
|
@@ -140,7 +145,7 @@ function realtime( config ) {
|
|
|
140
145
|
record.exits.forEach( entry => {
|
|
141
146
|
if ( entry.matches( config.templateSelector ) ) {
|
|
142
147
|
const htmlModule = HTMLModule.instance( entry );
|
|
143
|
-
const ownerContextModulesObj =
|
|
148
|
+
const ownerContextModulesObj = getDefs( htmlModule.ownerContext );
|
|
144
149
|
if ( htmlModule.defId ) { Observer.deleteProperty( ownerContextModulesObj, htmlModule.defId ); }
|
|
145
150
|
detachImportsContext( htmlModule.ownerContext );
|
|
146
151
|
} else {
|
|
@@ -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
|
+
}
|