@webqit/oohtml 3.1.8 → 3.1.9

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.
@@ -12,7 +12,7 @@ import { _, _init } from '../util.js';
12
12
  */
13
13
  export default function init( $config = {} ) {
14
14
  const { config, window } = _init.call( this, 'bindings-api', $config, {
15
- context: { attr: { bindingsreflection: 'bindings' }, },
15
+ attr: { bindingsreflection: 'bindings' },
16
16
  api: { bind: 'bind', bindings: 'bindings', },
17
17
  } );
18
18
  window.webqit.DOMBindingsContext = DOMBindingsContext;
@@ -34,11 +34,11 @@ function getBindings( config, node ) {
34
34
  // Reflection
35
35
  const props = Object.keys( bindingsObj );
36
36
  const targetNode = node === window.document ? window.document.documentElement : node;
37
- const bindingsReflection = config.context.attr.bindingsreflection;
37
+ const bindingsReflection = config.attr.bindingsreflection;
38
38
  if ( props.length && bindingsReflection ) {
39
- targetNode.setAttribute( config.context.attr.bindingsreflection, props.join( ' ') );
39
+ targetNode.setAttribute( config.attr.bindingsreflection, props.join( ' ') );
40
40
  } else if ( bindingsReflection ) {
41
- targetNode.toggleAttribute( config.context.attr.bindingsreflection, false );
41
+ targetNode.toggleAttribute( config.attr.bindingsreflection, false );
42
42
  }
43
43
  // Re: DOMBindingsContext
44
44
  const contextsApi = node[ ctxConfig.api.contexts ];
@@ -12,11 +12,9 @@ import { _, _init } from '../util.js';
12
12
  * @return Void
13
13
  */
14
14
  export default function init( $config = {} ) {
15
- const { config, window } = _init.call( this, 'html-bindings', $config, {
15
+ const { config, window } = _init.call( this, 'data-binding', $config, {
16
16
  attr: { expr: 'expr', itemIndex: 'data-key' },
17
17
  tokens: { nodeType: 'processing-instruction', tagStart: '?{', tagEnd: '}?', stateStart: '; [=', stateEnd: ']' },
18
- staticsensitivity: true,
19
- isomorphic: true,
20
18
  } );
21
19
  ( { CONTEXT_API: config.CONTEXT_API, BINDINGS_API: config.BINDINGS_API, HTML_IMPORTS: config.HTML_IMPORTS } = window.webqit.oohtml.configs );
22
20
  config.attrSelector = `[${ window.CSS.escape( config.attr.expr ) }]`;
@@ -46,7 +44,7 @@ function realtime( config ) {
46
44
  realdom.realtime( window.document ).subtree( config.attrSelector, record => {
47
45
  cleanup.call( this, ...record.exits );
48
46
  mountInlineBindings.call( this, config, ...record.entrants );
49
- }, { live: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
47
+ }, { live: true, timing: 'sync', staticSensitivity: true } );
50
48
  }
51
49
 
52
50
  function createDynamicScope( config, root ) {
@@ -188,7 +186,7 @@ function compileInlineBindings( config, str ) {
188
186
  const indices = kind === 'in' ? production[ 2 ] : ( production[ 1 ] || '$index__' );
189
187
  return `
190
188
  let $iteratee__ = ${ iteratee };
191
- let $import__ = this.${ config.HTML_IMPORTS.context.api.import }( ${ importSpec.trim() }, true );
189
+ let $import__ = this.${ config.HTML_IMPORTS.api.import }( ${ importSpec.trim() }, true );
192
190
  this.$oohtml_internal_databinding_signals?.push( $import__ );
193
191
 
194
192
  if ( $import__.value && $iteratee__ ) {
@@ -46,7 +46,7 @@ export default class HTMLImportsContext extends DOMContext {
46
46
  if ( ( event.detail || '' ).trim() === '/' ) return event.respondWith( this.localModules );
47
47
  const $config = this.configs.HTML_IMPORTS;
48
48
  let path = ( event.detail || '' ).split( /\/|(?<=\w)(?=#)/g ).map( x => x.trim() ).filter( x => x );
49
- if ( path.length ) { path = path.join( `/${ $config.template.api.exports }/` )?.split( '/' ) || []; }
49
+ if ( path.length ) { path = path.join( `/${ $config.api.defs }/` )?.split( '/' ) || []; }
50
50
  // No detail?
51
51
  if ( !path.length ) return event.respondWith();
52
52
 
@@ -89,11 +89,11 @@ export default class HTMLImportsContext extends DOMContext {
89
89
  };
90
90
  // ----------------
91
91
  const $config = this.configs.HTML_IMPORTS;
92
- if ( !this.host.matches || !$config.context.attr.importscontext ) return;
92
+ if ( !this.host.matches || !$config.attr.importscontext ) return;
93
93
  // Any existing this.refdSourceController? Abort!
94
94
  this.refdSourceController?.disconnect();
95
95
  const realdom = this.host.ownerDocument.defaultView.webqit.realdom;
96
- this.refdSourceController = realdom.realtime( this.host ).attr( $config.context.attr.importscontext, ( record, { signal } ) => {
96
+ this.refdSourceController = realdom.realtime( this.host ).attr( $config.attr.importscontext, ( record, { signal } ) => {
97
97
  // No importscontext attr set. But we're still watching
98
98
  if ( !record.value ) {
99
99
  this.contextModules = undefined;
@@ -12,7 +12,7 @@ export default class HTMLModule {
12
12
  * @instance
13
13
  */
14
14
  static instance( host ) {
15
- return _( host ).get( 'exportsmanager::instance' ) || new this( host );
15
+ return _( host ).get( 'defsmanager::instance' ) || new this( host );
16
16
  }
17
17
 
18
18
  /**
@@ -20,14 +20,14 @@ export default class HTMLModule {
20
20
  */
21
21
  constructor( host, parent = null, level = 0 ) {
22
22
  const { window } = env, { webqit: { realdom, oohtml: { configs } } } = window;
23
- _( host ).get( `exportsmanager::instance` )?.dispose();
24
- _( host ).set( `exportsmanager::instance`, this );
23
+ _( host ).get( `defsmanager::instance` )?.dispose();
24
+ _( host ).set( `defsmanager::instance`, this );
25
25
  this.host = host;
26
26
  this.config = configs.HTML_IMPORTS;
27
27
  this.parent = parent;
28
28
  this.level = level;
29
- this.exports = getExports( this.host );
30
- this.defId = ( this.host.getAttribute( this.config.template?.attr.moduledef ) || '' ).trim();
29
+ this.defs = getExports( this.host );
30
+ this.defId = ( this.host.getAttribute( this.config.attr.def ) || '' ).trim();
31
31
  this.validateDefId( this.defId );
32
32
  // ----------
33
33
  this.realtimeA = realdom.realtime( this.host.content ).children( record => {
@@ -60,7 +60,7 @@ export default class HTMLModule {
60
60
  }
61
61
 
62
62
  /**
63
- * Maps module contents as exports.
63
+ * Maps module contents as defs.
64
64
  *
65
65
  * @param Array entries
66
66
  * @param Bool isConnected
@@ -69,12 +69,12 @@ export default class HTMLModule {
69
69
  */
70
70
  export( entries, isConnected ) {
71
71
  const { window } = env, { webqit: { Observer } } = window;
72
- let dirty, allFragments = this.exports[ '#' ] || [];
73
- Observer.batch( this.exports, () => {
72
+ let dirty, allFragments = this.defs[ '#' ] || [];
73
+ Observer.batch( this.defs, () => {
74
74
  entries.forEach( entry => {
75
75
  if ( entry.nodeType !== 1 ) return;
76
76
  const isTemplate = entry.matches( this.config.templateSelector );
77
- const defId = ( entry.getAttribute( isTemplate ? this.config.template.attr.moduledef : this.config.template.attr.fragmentdef ) || '' ).trim();
77
+ const defId = ( entry.getAttribute( isTemplate ? this.config.attr.def : this.config.attr.fragmentdef ) || '' ).trim();
78
78
  if ( isConnected ) {
79
79
  if ( isTemplate && defId ) { new HTMLModule( entry, this.host, this.level + 1 ); }
80
80
  else {
@@ -83,7 +83,7 @@ export default class HTMLModule {
83
83
  }
84
84
  if ( defId ) {
85
85
  this.validateDefId( defId );
86
- Observer.set( this.exports, ( !isTemplate && '#' || '' ) + defId, entry );
86
+ Observer.set( this.defs, ( !isTemplate && '#' || '' ) + defId, entry );
87
87
  }
88
88
  } else {
89
89
  if ( isTemplate && defId ) { HTMLModule.instance( entry ).dispose(); }
@@ -91,10 +91,10 @@ export default class HTMLModule {
91
91
  allFragments = allFragments.filter( x => x !== entry );
92
92
  dirty = true;
93
93
  }
94
- if ( defId ) Observer.deleteProperty( this.exports, ( !isTemplate && '#' || '' ) + defId );
94
+ if ( defId ) Observer.deleteProperty( this.defs, ( !isTemplate && '#' || '' ) + defId );
95
95
  }
96
96
  } );
97
- if ( dirty ) Observer.set( this.exports, '#', allFragments );
97
+ if ( dirty ) Observer.set( this.defs, '#', allFragments );
98
98
  } );
99
99
  }
100
100
 
@@ -114,7 +114,7 @@ export default class HTMLModule {
114
114
  $loadingPromise = promise.then( () => interception.remove() ); // Set
115
115
  };
116
116
  const loading = ( record2.value || '' ).trim();
117
- const interception = Observer.intercept( this.exports, 'get', async ( descriptor, recieved, next ) => {
117
+ const interception = Observer.intercept( this.defs, 'get', async ( descriptor, recieved, next ) => {
118
118
  if ( loading === 'lazy' ) { loadingPromise( this.load( src, true ) ); }
119
119
  await loadingPromise();
120
120
  return next();
@@ -162,22 +162,22 @@ export default class HTMLModule {
162
162
  evalInheritance( ) {
163
163
  if ( !this.parent ) return [];
164
164
  const { window: { webqit: { Observer } } } = env;
165
- let extendedId = ( this.host.getAttribute( this.config.template.attr.extends ) || '' ).trim();
166
- let inheritedIds = ( this.host.getAttribute( this.config.template.attr.inherits ) || '' ).trim();
165
+ let extendedId = ( this.host.getAttribute( this.config.attr.extends ) || '' ).trim();
166
+ let inheritedIds = ( this.host.getAttribute( this.config.attr.inherits ) || '' ).trim();
167
167
  const handleInherited = records => {
168
168
  records.forEach( record => {
169
- if ( Observer.get( this.exports, record.key ) !== record.oldValue ) return;
169
+ if ( Observer.get( this.defs, record.key ) !== record.oldValue ) return;
170
170
  if ( [ 'get'/*initial get*/, 'set', 'def' ].includes( record.type ) ) {
171
- Observer[ record.type.replace( 'get', 'set' ) ]( this.exports, record.key, record.value );
171
+ Observer[ record.type.replace( 'get', 'set' ) ]( this.defs, record.key, record.value );
172
172
  } else if ( record.type === 'delete' ) {
173
- Observer.deleteProperty( this.exports, record.key );
173
+ Observer.deleteProperty( this.defs, record.key );
174
174
  }
175
175
  } );
176
176
  };
177
177
  const realtimes = [];
178
178
  const parentExportsObj = getExports( this.parent );
179
179
  if ( extendedId ) {
180
- realtimes.push( Observer.reduce( parentExportsObj, [ extendedId, this.config.template.api.exports, Infinity ], Observer.get, handleInherited, { live: true } ) );
180
+ realtimes.push( Observer.reduce( parentExportsObj, [ 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
183
  realtimes.push( Observer.get( parentExportsObj, inheritedIds, handleInherited, { live: true } ) );
@@ -194,7 +194,7 @@ export default class HTMLModule {
194
194
  this.realtimeA.disconnect();
195
195
  this.realtimeB.disconnect();
196
196
  this.realtimeC.forEach( r => ( r instanceof Promise ? r.then( r => r.abort() ) : r.abort() ) );
197
- Object.entries( this.exports ).forEach( ( [ key, entry ] ) => {
197
+ Object.entries( this.defs ).forEach( ( [ key, entry ] ) => {
198
198
  if ( key.startsWith( '#' ) ) return;
199
199
  HTMLModule.instance( entry ).dispose();
200
200
  } );
@@ -13,9 +13,9 @@ import { _, env } from '../util.js';
13
13
  * @return HTMLImportElement
14
14
  */
15
15
  export default function() {
16
- const { window } = env, { webqit } = window, { Observer, realdom, oohtml: { configs } } = webqit;
16
+ const { window } = env, { webqit } = window, { realdom, oohtml: { configs } } = webqit;
17
17
  if ( webqit.HTMLImportElement ) return webqit.HTMLImportElement;
18
- const BaseElement = configs.HTML_IMPORTS.import.tagName.includes( '-' ) ? window.HTMLElement : class {};
18
+ const BaseElement = configs.HTML_IMPORTS.elements.import.includes( '-' ) ? window.HTMLElement : class {};
19
19
  class HTMLImportElement extends BaseElement {
20
20
 
21
21
  /**
@@ -26,7 +26,7 @@ export default function() {
26
26
  * @returns
27
27
  */
28
28
  static instance( node ) {
29
- if ( configs.HTML_IMPORTS.import.tagName.includes( '-' ) && ( node instanceof this ) ) return node;
29
+ if ( configs.HTML_IMPORTS.elements.import.includes( '-' ) && ( node instanceof this ) ) return node;
30
30
  return _( node ).get( 'import::instance' ) || new this( node );
31
31
  }
32
32
 
@@ -60,7 +60,7 @@ export default function() {
60
60
 
61
61
  priv.hydrate = ( anchorNode, slottedElements ) => {
62
62
  // ----------------
63
- priv.moduleRef = ( this.el.getAttribute( configs.HTML_IMPORTS.import.attr.moduleref ) || '' ).trim();
63
+ priv.moduleRef = ( this.el.getAttribute( configs.HTML_IMPORTS.attr.ref ) || '' ).trim();
64
64
  anchorNode.replaceWith( priv.setAnchorNode( this.createAnchorNode() ) );
65
65
  priv.autoRestore( () => {
66
66
  slottedElements.forEach( slottedElement => {
@@ -72,10 +72,10 @@ export default function() {
72
72
  priv.hydrationImportRequest = new AbortController;
73
73
  priv.importRequest( fragments => {
74
74
  if ( priv.originalsRemapped ) { return this.fill( fragments ); }
75
- const identifiersMap = fragments.map( ( fragment, i ) => ( { el: fragment, fragmentDef: fragment.getAttribute( configs.HTML_IMPORTS.template.attr.fragmentdef ) || '', tagName: fragment.tagName, i } ) );
75
+ const identifiersMap = fragments.map( ( fragment, i ) => ( { el: fragment, fragmentDef: fragment.getAttribute( configs.HTML_IMPORTS.attr.fragmentdef ) || '', tagName: fragment.tagName, i } ) );
76
76
  let i = -1;
77
77
  slottedElements.forEach( slottedElement => {
78
- const tagName = slottedElement.tagName, fragmentDef = slottedElement.getAttribute( configs.HTML_IMPORTS.template.attr.fragmentdef ) || '';
78
+ const tagName = slottedElement.tagName, fragmentDef = slottedElement.getAttribute( configs.HTML_IMPORTS.attr.fragmentdef ) || '';
79
79
  const originalsMatch = ( i ++, identifiersMap.find( fragmentIdentifiers => fragmentIdentifiers.tagName === tagName && fragmentIdentifiers.fragmentDef === fragmentDef && fragmentIdentifiers.i === i ) );
80
80
  if ( !originalsMatch ) return; // Or should we throw integrity error?
81
81
  _( slottedElement ).set( 'original@imports', originalsMatch.el );
@@ -113,7 +113,7 @@ export default function() {
113
113
  if ( priv.slottedElements.size ) throw new Error( `Illegal reinsertion into the DOM; import slot is not empty!` );
114
114
  // Totally initialize this instance?
115
115
  if ( priv.moduleRefRealtime ) return;
116
- priv.moduleRefRealtime = realdom.realtime( this.el ).attr( configs.HTML_IMPORTS.import.attr.moduleref, ( record, { signal } ) => {
116
+ priv.moduleRefRealtime = realdom.realtime( this.el ).attr( configs.HTML_IMPORTS.attr.ref, ( record, { signal } ) => {
117
117
  priv.moduleRef = record.value;
118
118
  // Below, we ignore first restore from hydration
119
119
  priv.importRequest( fragments => !priv.hydrationImportRequest && this.fill( fragments ), signal );
@@ -182,8 +182,8 @@ export default function() {
182
182
  // Clone each slottable element and give it a reference to its original
183
183
  const slottableElementClone = slottableElement.cloneNode( true );
184
184
  // The folllowing references must be set before adding to DODM
185
- if ( !slottableElementClone.hasAttribute( configs.HTML_IMPORTS.template.attr.fragmentdef ) ) {
186
- slottableElementClone.toggleAttribute( configs.HTML_IMPORTS.template.attr.fragmentdef, true );
185
+ if ( !slottableElementClone.hasAttribute( configs.HTML_IMPORTS.attr.fragmentdef ) ) {
186
+ slottableElementClone.toggleAttribute( configs.HTML_IMPORTS.attr.fragmentdef, true );
187
187
  }
188
188
  _( slottableElementClone ).set( 'original@imports', slottableElement );
189
189
  _( slottableElementClone ).set( 'slot@imports', this.el );
@@ -221,7 +221,7 @@ export default function() {
221
221
  */
222
222
  get slottedElements() { return this[ '#' ].slottedElements; }
223
223
  }
224
- if ( configs.HTML_IMPORTS.import.tagName.includes( '-' ) ) { customElements.define( configs.HTML_IMPORTS.import.tagName, HTMLImportElement ); }
224
+ if ( configs.HTML_IMPORTS.elements.import.includes( '-' ) ) { customElements.define( configs.HTML_IMPORTS.elements.import, HTMLImportElement ); }
225
225
  webqit.HTMLImportElement = HTMLImportElement;
226
226
  return HTMLImportElement;
227
227
  }
@@ -15,22 +15,21 @@ import { _, _init } from '../util.js';
15
15
  * @return Void
16
16
  */
17
17
  export default function init( $config = {} ) {
18
- const { config, realdom, window } = _init.call( this, 'html-imports', $config, {
19
- template: { attr: { moduledef: 'def', fragmentdef: 'def', extends: 'extends', inherits: 'inherits' }, api: { exports: 'exports', moduledef: 'def' }, },
20
- context: { attr: { importscontext: 'importscontext', }, api: { import: 'import' }, },
21
- import: { tagName: 'import', attr: { moduleref: 'ref' }, },
22
- staticsensitivity: true,
23
- isomorphic: true,
18
+ const { config, window } = _init.call( this, 'html-imports', $config, {
19
+ elements: { import: 'import', },
20
+ attr: { def: 'def', extends: 'extends', inherits: 'inherits', ref: 'ref', importscontext: 'importscontext', },
21
+ api: { def: 'def', defs: 'defs', import: 'import' },
24
22
  } );
25
- config.templateSelector = `template[${ window.CSS.escape( config.template.attr.moduledef ) }]`;
26
- config.importsContextSelector = `[${ window.CSS.escape( config.context.attr.importscontext ) }]`;
27
- config.slottedElementsSelector = `[${ window.CSS.escape( config.template.attr.fragmentdef ) }]:not(template)`;
23
+ if ( !config.attr.fragmentdef ) { config.attr.fragmentdef = config.attr.def; }
24
+ config.templateSelector = `template[${ window.CSS.escape( config.attr.def ) }]`;
25
+ config.importsContextSelector = `[${ window.CSS.escape( config.attr.importscontext ) }]`;
26
+ config.slottedElementsSelector = `[${ window.CSS.escape( config.attr.fragmentdef ) }]:not(template)`;
28
27
  const anchorNodeMatch = ( start, end ) => {
29
28
  const starting = `starts-with(., "${ start }")`;
30
29
  const ending = `substring(., string-length(.) - string-length("${ end }") + 1) = "${ end }"`;
31
30
  return `${ starting } and ${ ending }`;
32
31
  }
33
- config.anchorNodeSelector = `comment()[${ anchorNodeMatch( `&lt;${ config.import.tagName }`, `&lt;/${ config.import.tagName }&gt;` ) }]`;
32
+ config.anchorNodeSelector = `comment()[${ anchorNodeMatch( `&lt;${ config.elements.import }`, `&lt;/${ config.elements.import }&gt;` ) }]`;
34
33
  window.webqit.HTMLImportsContext = HTMLImportsContext;
35
34
  window.webqit.HTMLImportElement = _HTMLImportElement();
36
35
  exposeAPIs.call( window, config );
@@ -38,7 +37,7 @@ export default function init( $config = {} ) {
38
37
  }
39
38
 
40
39
  /**
41
- * Returns the "exports" object associated with the given node.
40
+ * Returns the "defs" object associated with the given node.
42
41
  *
43
42
  * @param Element node
44
43
  * @param Bool autoCreate
@@ -46,11 +45,11 @@ export default function init( $config = {} ) {
46
45
  * @return Object
47
46
  */
48
47
  export function getExports( node, autoCreate = true ) {
49
- if ( !_( node ).has( 'exports' ) && autoCreate ) {
50
- const exports = Object.create( null );
51
- _( node ).set( 'exports', exports );
48
+ if ( !_( node ).has( 'defs' ) && autoCreate ) {
49
+ const defs = Object.create( null );
50
+ _( node ).set( 'defs', defs );
52
51
  }
53
- return _( node ).get( 'exports' );
52
+ return _( node ).get( 'defs' );
54
53
  }
55
54
 
56
55
  /**
@@ -63,21 +62,21 @@ export function getExports( node, autoCreate = true ) {
63
62
  function exposeAPIs( config ) {
64
63
  const window = this, { webqit: { oohtml: { configs } } } = window;
65
64
  // Assertions
66
- if ( config.template.api.exports in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.template.api.exports }" property!` ); }
67
- if ( config.template.api.moduledef in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.template.api.moduledef }" property!` ); }
68
- if ( config.context.api.import in window.document ) { throw new Error( `document already has a "${ config.context.api.import }" property!` ); }
69
- if ( config.context.api.import in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.context.api.import }" property!` ); }
65
+ if ( config.api.defs in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.api.defs }" property!` ); }
66
+ if ( config.api.def in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.api.def }" property!` ); }
67
+ if ( config.api.import in window.document ) { throw new Error( `document already has a "${ config.api.import }" property!` ); }
68
+ if ( config.api.import in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.api.import }" property!` ); }
70
69
  // Definitions
71
- Object.defineProperty( window.HTMLTemplateElement.prototype, config.template.api.exports, { get: function() {
70
+ Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.defs, { get: function() {
72
71
  return getExports( this );
73
72
  } } );
74
- Object.defineProperty( window.HTMLTemplateElement.prototype, config.template.api.moduledef, { get: function() {
75
- return this.getAttribute( config.template.attr.moduledef );
73
+ Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.def, { get: function() {
74
+ return this.getAttribute( config.attr.def );
76
75
  } } );
77
- Object.defineProperty( window.document, config.context.api.import, { value: function( ref, live = false, callback = null ) {
76
+ Object.defineProperty( window.document, config.api.import, { value: function( ref, live = false, callback = null ) {
78
77
  return importRequest( window.document, ...arguments );
79
78
  } } );
80
- Object.defineProperty( window.HTMLElement.prototype, config.context.api.import, { value: function( ref, live = false, callback = null ) {
79
+ Object.defineProperty( window.HTMLElement.prototype, config.api.import, { value: function( ref, live = false, callback = null ) {
81
80
  return importRequest( this, ...arguments );
82
81
  } } );
83
82
  function importRequest( context, ref, live = false, callback = null ) {
@@ -130,7 +129,7 @@ function realtime( config ) {
130
129
  htmlModule.ownerContext = entry.scoped ? record.target : window.document;
131
130
  const ownerContextModulesObj = getExports( htmlModule.ownerContext );
132
131
  if ( htmlModule.defId ) { Observer.set( ownerContextModulesObj, htmlModule.defId, entry ); }
133
- // The ownerContext's exports - ownerContextModulesObj - has to be populated
132
+ // The ownerContext's defs - ownerContextModulesObj - has to be populated
134
133
  // Before attaching a context instance to it, to give the just created context something to use for
135
134
  // fullfiling reclaimed requests.
136
135
  attachImportsContext( htmlModule.ownerContext );
@@ -148,11 +147,11 @@ function realtime( config ) {
148
147
  detachImportsContext( entry );
149
148
  }
150
149
  } );
151
- }, { live: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
150
+ }, { live: true, timing: 'sync', staticSensitivity: true } );
152
151
  // ------------
153
152
  // IMPORTS
154
153
  // ------------
155
- realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.import.tagName, record => {
154
+ realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.elements.import, record => {
156
155
  record.entrants.forEach( node => handleRealtime( node, true, record ) );
157
156
  record.exits.forEach( node => handleRealtime( node, false, record ) );
158
157
  }, { live: true, timing: 'sync' } );
@@ -11,14 +11,12 @@ import { _, _init } from '../util.js';
11
11
  */
12
12
  export default function init( $config = {} ) {
13
13
  const { config, window } = _init.call( this, 'namespaced-html', $config, {
14
- id: { attr: 'id' },
15
- namespace: { attr: 'namespace', api: 'namespace', },
14
+ attr: { namespace: 'namespace', id: 'id', },
15
+ api: { namespace: 'namespace', eagermode: true, },
16
16
  target: { attr: ':target', event: ':target', scrolling: true },
17
- staticsensitivity: true,
18
- eagermode: true,
19
17
  } );
20
- config.idSelector = `[${ window.CSS.escape( config.id.attr ) }]`;
21
- config.namespaceSelector = `[${ window.CSS.escape( config.namespace.attr ) }]`;
18
+ config.idSelector = `[${ window.CSS.escape( config.attr.id ) }]`;
19
+ config.namespaceSelector = `[${ window.CSS.escape( config.attr.namespace ) }]`;
22
20
  exposeAPIs.call( window, config );
23
21
  realtime.call( window, config );
24
22
  }
@@ -35,8 +33,8 @@ function getNamespaceObject( node, config ) {
35
33
  if ( !_( node ).has( 'namespace' ) ) {
36
34
  const namespaceObj = Object.create( null );
37
35
  Observer.intercept( namespaceObj, 'get', ( event, receiver, next ) => {
38
- if ( Observer.has( namespaceObj, event.key ) || !config.eagermode ) return next();
39
- const selector = `[${ window.CSS.escape( config.id.attr ) }="${ event.key }"]`;
36
+ if ( Observer.has( namespaceObj, event.key ) || !config.api.eagermode ) return next();
37
+ const selector = `[${ window.CSS.escape( config.attr.id ) }="${ event.key }"]`;
40
38
  const resultNode = Array.from( node.querySelectorAll( selector ) ).filter( idNode => {
41
39
  const ownerRoot = idNode.parentNode.closest( config.namespaceSelector );
42
40
  if ( node === window.document ) {
@@ -63,13 +61,13 @@ function getNamespaceObject( node, config ) {
63
61
  function exposeAPIs( config ) {
64
62
  const window = this, { webqit: { Observer } } = window;
65
63
  // Assertions
66
- if ( config.namespace.api in window.document ) { throw new Error( `document already has a "${ config.namespace.api }" property!` ); }
67
- if ( config.namespace.api in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.namespace.api }" property!` ); }
64
+ if ( config.api.namespace in window.document ) { throw new Error( `document already has a "${ config.api.namespace }" property!` ); }
65
+ if ( config.api.namespace in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.api.namespace }" property!` ); }
68
66
  // Definitions
69
- Object.defineProperty( window.document, config.namespace.api, { get: function() {
67
+ Object.defineProperty( window.document, config.api.namespace, { get: function() {
70
68
  return Observer.proxy( getNamespaceObject.call( window, window.document, config ) );
71
69
  } });
72
- Object.defineProperty( window.Element.prototype, config.namespace.api, { get: function() {
70
+ Object.defineProperty( window.Element.prototype, config.api.namespace, { get: function() {
73
71
  return Observer.proxy( getNamespaceObject.call( window, this, config ) );
74
72
  } } );
75
73
  }
@@ -85,7 +83,7 @@ function realtime( config ) {
85
83
  const window = this, { webqit: { Observer, realdom } } = window;
86
84
  // ----------------
87
85
  const handle = ( target, entry, incoming ) => {
88
- const identifier = entry.getAttribute( config.id.attr );
86
+ const identifier = entry.getAttribute( config.attr.id );
89
87
  const ownerRoot = target.closest( config.namespaceSelector ) || _( entry ).get( 'ownerNamespace' ) || window.document;
90
88
  const namespaceObj = getNamespaceObject.call( window, ownerRoot, config );
91
89
  if ( incoming ) {
@@ -101,10 +99,10 @@ function realtime( config ) {
101
99
  realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.idSelector, record => {
102
100
  record.entrants.forEach( entry => handle( record.target, entry, true ) );
103
101
  record.exits.forEach( entry => handle( record.target, entry, false ) );
104
- }, { live: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
102
+ }, { live: true, timing: 'sync', staticSensitivity: true } );
105
103
  // ----------------
106
- if ( config.staticsensitivity ) {
107
- realdom.realtime( window.document, 'attr' ).observe( config.namespace.attr, record => {
104
+ if ( true/*config.staticsensitivity*/ ) {
105
+ realdom.realtime( window.document, 'attr' ).observe( config.attr.namespace, record => {
108
106
  const ownerRoot = record.target.parentNode?.closest( config.namespaceSelector ) || _( record.target ).get( 'ownerNamespace' ) || window.document;
109
107
  const ownerRootNamespaceObj = getNamespaceObject.call( window, ownerRoot, config );
110
108
  const namespaceObj = getNamespaceObject.call( window, record.target, config );
@@ -126,7 +124,7 @@ function realtime( config ) {
126
124
  let prevTarget;
127
125
  const activateTarget = () => {
128
126
  const path = window.location.hash?.substring( 1 ).split( '/' ).map( s => s.trim() ).filter( s => s ) || [];
129
- const currTarget = path.reduce( ( prev, segment ) => prev && prev[ config.namespace.api ][ segment ], window.document );
127
+ const currTarget = path.reduce( ( prev, segment ) => prev && prev[ config.api.namespace ][ segment ], window.document );
130
128
  if ( prevTarget && config.target.attr ) { prevTarget.toggleAttribute( config.target.attr, false ); }
131
129
  if ( currTarget && currTarget !== window.document ) {
132
130
  if ( config.target.attr ) { currTarget.toggleAttribute( config.target.attr, true ); }
package/src/util.js CHANGED
@@ -5,6 +5,7 @@
5
5
  import realdomInit from '@webqit/realdom';
6
6
  import { _internals } from '@webqit/util/js/index.js';
7
7
  import { _merge } from '@webqit/util/obj/index.js';
8
+ import { _toTitle } from '@webqit/util/str/index.js';
8
9
 
9
10
  export const _ = ( ...args ) => _internals( 'oohtml', ...args );
10
11
 
@@ -12,14 +13,31 @@ export const env = {};
12
13
 
13
14
  export function _init( name, $config, $defaults ) {
14
15
  const window = this, realdom = realdomInit.call( window );
16
+ env.window = window;
17
+ if ( !window.webqitConfig ) {
18
+ window.webqitConfig = realdom.meta( 'webqit' ).json();
19
+ }
15
20
  window.webqit || ( window.webqit = {} );
16
21
  window.webqit.oohtml || ( window.webqit.oohtml = {} );
17
22
  window.webqit.oohtml.configs || ( window.webqit.oohtml.configs = {} );
18
- const configKey = name.toUpperCase().replace( '-', '_' );
19
- window.webqit.oohtml.configs[ configKey ] || ( window.webqit.oohtml.configs[ configKey ] = {} );
20
- env.window = window;
21
23
  // ---------------------
22
- _merge( 2, window.webqit.oohtml.configs[ configKey ], $defaults, $config, realdom.meta( name ).json() );
24
+ const configKey = name.toUpperCase().replace( '-', '_' );
25
+ if ( !window.webqit.oohtml.configs[ configKey ] ) {
26
+ window.webqit.oohtml.configs[ configKey ] = {};
27
+ const config = window.webqit.oohtml.configs[ configKey ];
28
+ _merge( 2, config, $defaults, $config, realdom.meta( name ).json() );
29
+ if ( window.webqitConfig.prefix ) {
30
+ Object.keys( config ).forEach( main => {
31
+ Object.keys( config[ main ] ).forEach( key => {
32
+ if ( main === 'api' && typeof config[ main ][ key ] === 'string' ) {
33
+ config[ main ][ key ] = `${ window.webqitConfig.prefix }${ _toTitle( config[ main ][ key ] ) }`
34
+ } else if ( [ 'attr', 'elements' ].includes( main ) && config[ main ][ key ]?.startsWith( 'data-' ) === false ) {
35
+ config[ main ][ key ] = `${ window.webqitConfig.prefix }-${ config[ main ][ key ] }`
36
+ }
37
+ } );
38
+ } );
39
+ }
40
+ }
23
41
  // ---------------------
24
42
  return { config: window.webqit.oohtml.configs[ configKey ], realdom, window };
25
43
  }
@@ -3,7 +3,7 @@
3
3
  * @imports
4
4
  */
5
5
  import { expect } from 'chai';
6
- import { createDocument, mockRemoteFetch, delay } from './index.js';
6
+ import { createDocument, createDocumentPrefixed, mockRemoteFetch, delay } from './index.js';
7
7
 
8
8
  describe(`HTML Imports`, function() {
9
9
 
@@ -38,73 +38,73 @@ describe(`HTML Imports`, function() {
38
38
  describe( `Dynamic...`, function() {
39
39
 
40
40
  const head = `
41
- <template def="temp0">
41
+ <template wq-def="temp0">
42
42
  <!-- ------- -->
43
43
  <p>Hello world Export</p>
44
44
  <p>Hellort</p>
45
- <input def="input" />
46
- <template def="temp1">
47
- <textarea def="input"></textarea>
48
- <template def="temp2">
49
- <select def="input"></select>
45
+ <input wq-def="input" />
46
+ <template wq-def="temp1">
47
+ <textarea wq-def="input"></textarea>
48
+ <template wq-def="temp2">
49
+ <select wq-def="input"></select>
50
50
  </template>
51
51
  </template>
52
52
  <!-- ------- -->
53
- <template def="_landing1">
54
- <div def="main.html">a</div>
55
- <template def="_landing2">
56
- <div def="main.html">b</div>
57
- <template def="_docs">
58
- <div def="main.html">c</div>
53
+ <template wq-def="_landing1">
54
+ <div wq-def="main.html">a</div>
55
+ <template wq-def="_landing2">
56
+ <div wq-def="main.html">b</div>
57
+ <template wq-def="_docs">
58
+ <div wq-def="main.html">c</div>
59
59
  </template>
60
60
  </template>
61
61
  </template>
62
62
  <!-- ------- -->
63
- <template def="landing1" extends="_landing1">
64
- <div def="README.md">1</div>
65
- <template def="landing2" extends="_landing2">
66
- <div def="README.md">2</div>
67
- <template def="docs" extends="_docs">
68
- <div def="README.md">3</div>
63
+ <template wq-def="landing1" wq-extends="_landing1">
64
+ <div wq-def="README.md">1</div>
65
+ <template wq-def="landing2" wq-extends="_landing2">
66
+ <div wq-def="README.md">2</div>
67
+ <template wq-def="docs" wq-extends="_docs">
68
+ <div wq-def="README.md">3</div>
69
69
  </template>
70
70
  </template>
71
71
  </template>
72
72
  <!-- ------- -->
73
73
  </template>`;
74
74
  const body = `
75
- <import ref="temp0/uuu"></import>`;
76
- const { document } = createDocument( head, body );
77
- const importEl = document.querySelector( 'import' );
75
+ <wq-import wq-ref="temp0/uuu"></wq-import>`;
76
+ const { document } = createDocumentPrefixed( 'wq', head, body );
77
+ const importEl = document.querySelector( 'wq-import' );
78
78
 
79
79
  it ( `<import> element should not be resolved: no match for given import ID...`, async function() {
80
- expect( document.body.firstElementChild.nodeName ).to.eq( 'IMPORT' );
80
+ expect( document.body.firstElementChild.nodeName ).to.eq( 'WQ-IMPORT' );
81
81
  } );
82
82
 
83
83
  it ( `<import> element should be automatically resolved: new import ID is set...`, async function() {
84
- importEl.setAttribute( 'ref', 'temp0#input' );
84
+ importEl.setAttribute( 'wq-ref', 'temp0#input' );
85
85
  expect( document.body.firstElementChild.nodeName ).to.eq( 'INPUT' );
86
86
  } );
87
87
 
88
88
  it ( `<import> element should be automatically resolved: new moduleref is set - nested...`, async function() {
89
- importEl.setAttribute( 'ref', 'temp0/temp1#input' );
89
+ importEl.setAttribute( 'wq-ref', 'temp0/temp1#input' );
90
90
  expect( document.body.firstElementChild.nodeName ).to.eq( 'TEXTAREA' );
91
91
  } );
92
92
 
93
93
  it ( `<import> element should be automatically resolved: moduleref is unset - should now be inherited from <body>...`, async function() {
94
- importEl.setAttribute( 'ref', '#input' );
95
- expect( document.body.firstElementChild.nodeName ).to.eq( 'IMPORT' );
96
- document.body.setAttribute( 'importscontext', 'temp0/temp1/temp2' );
94
+ importEl.setAttribute( 'wq-ref', '#input' );
95
+ expect( document.body.firstElementChild.nodeName ).to.eq( 'WQ-IMPORT' );
96
+ document.body.setAttribute( 'wq-importscontext', 'temp0/temp1/temp2' );
97
97
  expect( document.body.firstElementChild.nodeName ).to.eq( 'SELECT' );
98
98
  } );
99
99
 
100
100
  it ( `<import> element should be automatically resolved: moduleref at <body> is changed...`, async function() {
101
- document.body.setAttribute( 'importscontext', 'temp0' );
101
+ document.body.setAttribute( 'wq-importscontext', 'temp0' );
102
102
  expect( document.body.firstElementChild.nodeName ).to.eq( 'INPUT' );
103
103
  } );
104
104
 
105
105
  it ( `<import> element should be automatically RESTORED: slotted element is removed from DOM...`, async function() {
106
106
  document.body.querySelector( 'input' ).remove();
107
- expect( document.body.firstElementChild.nodeName ).to.eq( 'IMPORT' );
107
+ expect( document.body.firstElementChild.nodeName ).to.eq( 'WQ-IMPORT' );
108
108
  } );
109
109
 
110
110
  } );
@@ -170,7 +170,7 @@ describe(`HTML Imports`, function() {
170
170
  const routingElement = document.body.firstElementChild;
171
171
  expect( routingElement.firstElementChild.nodeName ).to.eq( 'TEXTAREA' );
172
172
  document.import( 'temp0/temp1', temp1 => {
173
- const textarea = temp1.exports[ '#input' ];
173
+ const textarea = temp1.defs[ '#input' ];
174
174
  textarea.remove();
175
175
  expect( routingElement.firstElementChild.nodeName ).to.eq( 'IMPORT' );
176
176
  temp1.content.prepend( textarea );