@webqit/oohtml 2.1.8 → 2.1.10

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 (40) hide show
  1. package/dist/bindings-api.js +2 -0
  2. package/dist/bindings-api.js.map +7 -0
  3. package/dist/context-api.js +1 -1
  4. package/dist/context-api.js.map +3 -3
  5. package/dist/html-imports.js +1 -1
  6. package/dist/html-imports.js.map +3 -3
  7. package/dist/html-modules.js +1 -1
  8. package/dist/html-modules.js.map +3 -3
  9. package/dist/main.js +9 -9
  10. package/dist/main.js.map +3 -3
  11. package/dist/namespace-api.js +2 -0
  12. package/dist/namespace-api.js.map +7 -0
  13. package/dist/scoped-js.js +7 -7
  14. package/dist/scoped-js.js.map +3 -3
  15. package/package.json +6 -6
  16. package/src/bindings-api/index.js +84 -0
  17. package/src/context-api/HTMLContext.js +3 -3
  18. package/src/context-api/index.js +13 -17
  19. package/src/html-imports/_HTMLImportElement.js +13 -15
  20. package/src/html-imports/index.js +20 -26
  21. package/src/html-modules/HTMLExportsManager.js +17 -17
  22. package/src/html-modules/_HTMLImportsContext.js +6 -6
  23. package/src/html-modules/index.js +31 -37
  24. package/src/index.js +9 -11
  25. package/src/{namespaced-html → namespace-api}/index.js +35 -40
  26. package/src/scoped-js/Compiler.js +7 -7
  27. package/src/scoped-js/index.js +19 -24
  28. package/src/targets.browser.js +2 -2
  29. package/src/util.js +13 -1
  30. package/test/bindings-api.test.js +42 -0
  31. package/test/index.js +11 -9
  32. package/dist/namespaced-html.js +0 -2
  33. package/dist/namespaced-html.js.map +0 -7
  34. package/dist/state-api.js +0 -2
  35. package/dist/state-api.js.map +0 -7
  36. package/src/state-api/index.js +0 -59
  37. package/test/state-api.test.js +0 -34
  38. /package/src/{namespaced-html → bindings-api}/targets.browser.js +0 -0
  39. /package/src/{state-api → namespace-api}/targets.browser.js +0 -0
  40. /package/test/{namespaced-html.test.js → namespace-api.test.js} +0 -0
@@ -2,39 +2,33 @@
2
2
  /**
3
3
  * @imports
4
4
  */
5
- import wqDom from '@webqit/dom';
6
5
  import Observer from '@webqit/observer';
7
6
  import _HTMLImportsContext from './_HTMLImportsContext.js';
8
7
  import HTMLExportsManager from './HTMLExportsManager.js';
9
- import { _ } from '../util.js';
8
+ import { _, _init } from '../util.js';
10
9
 
11
10
  /**
12
11
  * Initializes HTML Modules.
13
12
  *
14
- * @param Object $params
13
+ * @param Object $config
15
14
  *
16
15
  * @return Void
17
16
  */
18
- export default function init( $params = {} ) {
19
- const window = this, dom = wqDom.call( window );
20
- if ( !window.wq ) { window.wq = {}; }
21
- window.wq.Observer = Observer;
22
- window.wq.HTMLImportsContext = class extends _HTMLImportsContext {
23
- static get params() { return params; }
24
- };
25
- // -------
26
- const params = dom.meta( 'oohtml' ).copyWithDefaults( $params, {
17
+ export default function init( $config = {} ) {
18
+ const { config, window } = _init.call( this, 'html-modules', $config, {
27
19
  template: { attr: { exportid: 'exportid', extends: 'extends', inherits: 'inherits' }, api: { modules: 'modules', exportid: 'exportid' }, },
28
20
  context: { attr: { importscontext: 'importscontext', contextname: 'contextname' }, api: { modules: 'modules' }, },
29
21
  export: { attr: { exportid: 'exportid' }, },
30
22
  staticsensitivity: true,
31
23
  } );
32
- params.window = window;
33
- params.templateSelector = `template[${ window.CSS.escape( params.template.attr.exportid ) }]`;
34
- params.ownerContextSelector = [ params.context.attr.contextname, params.context.attr.importscontext ].map( a => `[${ window.CSS.escape( a ) }]` ).join( ',' );
35
- // -------
36
- exposeModulesObjects.call( this, params );
37
- realtime.call( this, params );
24
+ config.templateSelector = `template[${ window.CSS.escape( config.template.attr.exportid ) }]`;
25
+ config.ownerContextSelector = [ config.context.attr.contextname, config.context.attr.importscontext ].map( a => `[${ window.CSS.escape( a ) }]` ).join( ',' );
26
+ window.webqit.HTMLImportsContext = class extends _HTMLImportsContext {
27
+ static get config() { return config; }
28
+ };
29
+ window.webqit.Observer = Observer;
30
+ exposeModulesObjects.call( window, config );
31
+ realtime.call( window, config );
38
32
  }
39
33
 
40
34
  export { Observer }
@@ -64,37 +58,37 @@ export function getModulesObject( node, autoCreate = true ) {
64
58
  /**
65
59
  * Exposes HTML Modules with native APIs.
66
60
  *
67
- * @param Object params
61
+ * @param Object config
68
62
  *
69
63
  * @return Void
70
64
  */
71
- function exposeModulesObjects( params ) {
65
+ function exposeModulesObjects( config ) {
72
66
  const window = this;
73
67
  // Assertions
74
- if ( params.context.api.modules in window.document ) { throw new Error( `document already has a "${ params.context.api.modules }" property!` ); }
75
- if ( params.template.api.modules in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ params.template.api.modules }" property!` ); }
76
- if ( params.template.api.exportid in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ params.template.api.exportid }" property!` ); }
68
+ if ( config.context.api.modules in window.document ) { throw new Error( `document already has a "${ config.context.api.modules }" property!` ); }
69
+ if ( config.template.api.modules in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.template.api.modules }" property!` ); }
70
+ if ( config.template.api.exportid in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.template.api.exportid }" property!` ); }
77
71
  // Definitions
78
- Object.defineProperty( window.document, params.context.api.modules, { get: function() {
72
+ Object.defineProperty( window.document, config.context.api.modules, { get: function() {
79
73
  return getModulesObject( window.document );
80
74
  } } );
81
- Object.defineProperty( window.HTMLElement.prototype, params.template.api.modules, { get: function() {
75
+ Object.defineProperty( window.HTMLElement.prototype, config.template.api.modules, { get: function() {
82
76
  return getModulesObject( this );
83
77
  } } );
84
- Object.defineProperty( window.HTMLTemplateElement.prototype, params.template.api.exportid, { get: function() {
85
- return this.isConnected ? HTMLExportsManager.instance( this, params ).exportId : this.getAttribute( params.template.attr.exportid );
78
+ Object.defineProperty( window.HTMLTemplateElement.prototype, config.template.api.exportid, { get: function() {
79
+ return this.getAttribute( config.template.attr.exportid );
86
80
  } } );
87
81
  }
88
82
 
89
83
  /**
90
84
  * Performs realtime capture of elements and builds their contents graph.
91
85
  *
92
- * @param Object params
86
+ * @param Object config
93
87
  *
94
88
  * @return Void
95
89
  */
96
- function realtime( params ) {
97
- const window = this, { dom, HTMLImportsContext } = window.wq;
90
+ function realtime( config ) {
91
+ const window = this, { dom, HTMLImportsContext } = window.webqit;
98
92
  // ------------
99
93
  const attachImportsContext = host => {
100
94
  const contextId = HTMLImportsContext.createId( host );
@@ -103,15 +97,15 @@ function realtime( params ) {
103
97
  const detachImportsContext = ( host, force ) => {
104
98
  const contextId = HTMLImportsContext.createId( host );
105
99
  HTMLImportsContext.detachFrom( host, contextId, cx => {
106
- return force || host.matches && !host.matches( params.ownerContextSelector ) && !Object.keys( cx.modules ).length;
100
+ return force || host.matches && !host.matches( config.ownerContextSelector ) && !Object.keys( cx.modules ).length;
107
101
  } );
108
102
  };
109
103
  // ------------
110
- dom.realtime( window.document ).observe( [ params.templateSelector, params.ownerContextSelector ], record => {
104
+ dom.realtime( window.document ).observe( [ config.templateSelector, config.ownerContextSelector ], record => {
111
105
  record.entrants.forEach( entry => {
112
- if ( entry.matches( params.templateSelector ) ) {
106
+ if ( entry.matches( config.templateSelector ) ) {
113
107
  Object.defineProperty( entry, 'scoped', { value: entry.hasAttribute( 'scoped' ) } );
114
- const moduleExport = new HTMLExportsManager( entry, params );
108
+ const moduleExport = new HTMLExportsManager( window, entry, config );
115
109
  moduleExport.ownerContext = entry.scoped ? record.target : window.document;
116
110
  const ownerContextModulesObj = getModulesObject( moduleExport.ownerContext );
117
111
  if ( moduleExport.exportId ) { Observer.set( ownerContextModulesObj, moduleExport.exportId, entry ); }
@@ -124,8 +118,8 @@ function realtime( params ) {
124
118
  }
125
119
  } );
126
120
  record.exits.forEach( entry => {
127
- if ( entry.matches( params.templateSelector ) ) {
128
- const moduleExport = HTMLExportsManager.instance( entry, params );
121
+ if ( entry.matches( config.templateSelector ) ) {
122
+ const moduleExport = HTMLExportsManager.instance( window, entry, config );
129
123
  const ownerContextModulesObj = getModulesObject( moduleExport.ownerContext );
130
124
  if ( moduleExport.exportId ) { Observer.deleteProperty( ownerContextModulesObj, moduleExport.exportId ); }
131
125
  detachImportsContext( moduleExport.ownerContext );
@@ -133,5 +127,5 @@ function realtime( params ) {
133
127
  detachImportsContext( entry, true );
134
128
  }
135
129
  } );
136
- }, { subtree: true, timing: 'sync', staticSensitivity: params.staticsensitivity } );
130
+ }, { subtree: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
137
131
  }
package/src/index.js CHANGED
@@ -3,27 +3,25 @@
3
3
  * @imports
4
4
  */
5
5
  import Observer from '@webqit/observer';
6
- import StateAPI from './state-api/index.js';
6
+ import BindingsAPI from './bindings-api/index.js';
7
7
  import ContextAPI from './context-api/index.js';
8
+ import NamespaceAPI from './namespace-api/index.js';
8
9
  import HTMLModules from './html-modules/index.js';
9
10
  import HTMLImports from './html-imports/index.js';
10
- import NamespacedHTML from './namespaced-html/index.js';
11
11
  import ScopedJS from './scoped-js/index.js';
12
12
 
13
13
  /**
14
14
  * @init
15
15
  */
16
16
  export default function init( configs = {} ) {
17
- if ( !this.wq ) { this.wq = {}; }
18
- if ( this.wq.oohtml ) return;
19
- this.wq.oohtml = {};
17
+ if ( !this.webqit ) { this.webqit = {}; }
20
18
  // --------------
21
- StateAPI.call(this, ( configs.StateAPI || {} ) );
22
- ContextAPI.call( this, ( configs.ContextAPI || {} ) );
23
- HTMLModules.call( this, ( configs.HTMLModules || {} ) );
24
- HTMLImports.call( this, ( configs.HTMLImports || {} ) );
25
- NamespacedHTML.call(this, ( configs.NamespacedHTML || {} ) );
26
- ScopedJS.call( this, ( configs.ScopedJS || {} ) );
19
+ BindingsAPI.call(this, ( configs.BINDINGS_API || {} ) );
20
+ ContextAPI.call( this, ( configs.CONTEXT_API || {} ) );
21
+ NamespaceAPI.call(this, ( configs.NAMESPACE_API || {} ) );
22
+ HTMLModules.call( this, ( configs.HTML_MODULES || {} ) );
23
+ HTMLImports.call( this, ( configs.HTML_IMPORTS || {} ) );
24
+ ScopedJS.call( this, ( configs.SCOPED_JS || {} ) );
27
25
  // --------------
28
26
  }
29
27
 
@@ -3,30 +3,25 @@
3
3
  * @imports
4
4
  */
5
5
  import Observer from '@webqit/observer';
6
- import wqDom from '@webqit/dom';
7
- import { _ } from '../util.js';
6
+ import { _, _init } from '../util.js';
8
7
 
9
8
  /**
10
9
  * @init
11
10
  *
12
- * @param Object $params
11
+ * @param Object $config
13
12
  */
14
- export default function init( $params = {} ) {
15
- const window = this, dom = wqDom.call( window );
16
- if ( !window.wq ) { window.wq = {}; }
17
- window.wq.Observer = Observer;
18
- // -------
19
- const params = dom.meta( 'oohtml' ).copyWithDefaults( $params, {
13
+ export default function init( $config = {} ) {
14
+ const { config, window } = _init.call( this, 'namespace-api', $config, {
20
15
  attr: { namespace: 'namespace', id: ':id', },
21
16
  api: { namespace: 'namespace', },
22
17
  staticsensitivity: true,
23
18
  eagermode: true,
24
19
  } );
25
- params.idSelector = `[${ window.CSS.escape( params.attr.id ) }]`;
26
- params.namespaceSelector = `[${ window.CSS.escape( params.attr.namespace ) }]`;
27
- // -------
28
- exposeNamespaceObjects.call( this, params );
29
- realtime.call( this, params );
20
+ config.idSelector = `[${ window.CSS.escape( config.attr.id ) }]`;
21
+ config.namespaceSelector = `[${ window.CSS.escape( config.attr.namespace ) }]`;
22
+ window.webqit.Observer = Observer;
23
+ exposeNamespaceObjects.call( window, config );
24
+ realtime.call( window, config );
30
25
  }
31
26
 
32
27
  export { Observer }
@@ -34,21 +29,21 @@ export { Observer }
34
29
  /**
35
30
  * Exposes Namespaced HTML with native APIs.
36
31
  *
37
- * @param Object params
32
+ * @param Object config
38
33
  *
39
34
  * @return Void
40
35
  */
41
- function exposeNamespaceObjects( params ) {
36
+ function exposeNamespaceObjects( config ) {
42
37
  const window = this;
43
38
  // Assertions
44
- if ( params.api.namespace in window.document ) { throw new Error( `document already has a "${ params.api.namespace }" property!` ); }
45
- if ( params.api.namespace in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ params.api.namespace }" property!` ); }
39
+ if ( config.api.namespace in window.document ) { throw new Error( `document already has a "${ config.api.namespace }" property!` ); }
40
+ if ( config.api.namespace in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.api.namespace }" property!` ); }
46
41
  // Definitions
47
- Object.defineProperty( window.document, params.api.namespace, { get: function() {
48
- return Observer.proxy( getNamespaceObject.call( window, window.document, params ) );
42
+ Object.defineProperty( window.document, config.api.namespace, { get: function() {
43
+ return Observer.proxy( getNamespaceObject.call( window, window.document, config ) );
49
44
  } });
50
- Object.defineProperty( window.Element.prototype, params.api.namespace, { get: function() {
51
- return Observer.proxy( getNamespaceObject.call( window, this, params ) );
45
+ Object.defineProperty( window.Element.prototype, config.api.namespace, { get: function() {
46
+ return Observer.proxy( getNamespaceObject.call( window, this, config ) );
52
47
  } } );
53
48
  }
54
49
 
@@ -59,15 +54,15 @@ function exposeNamespaceObjects( params ) {
59
54
  *
60
55
  * @return Object
61
56
  */
62
- function getNamespaceObject( node, params ) {
57
+ function getNamespaceObject( node, config ) {
63
58
  const window = this;
64
59
  if ( !_( node ).has( 'namespace' ) ) {
65
60
  const namespaceObj = Object.create( null );
66
61
  Observer.intercept( namespaceObj, 'get', ( event, receiver, next ) => {
67
- if ( Observer.has( namespaceObj, event.key ) || !params.eagermode ) return next();
68
- const selector = `[${ window.CSS.escape( params.attr.id ) }="${ event.key }"]`;
62
+ if ( Observer.has( namespaceObj, event.key ) || !config.eagermode ) return next();
63
+ const selector = `[${ window.CSS.escape( config.attr.id ) }="${ event.key }"]`;
69
64
  const resultNode = Array.from( node.querySelectorAll( selector ) ).filter( idNode => {
70
- const ownerRoot = idNode.parentNode.closest( params.namespaceSelector );
65
+ const ownerRoot = idNode.parentNode.closest( config.namespaceSelector );
71
66
  if ( node === window.document ) {
72
67
  // Only IDs without a scope actually belong to the document scope
73
68
  return !ownerRoot;
@@ -85,17 +80,17 @@ function getNamespaceObject( node, params ) {
85
80
  /**
86
81
  * Performs realtime capture of elements and builds their relationships.
87
82
  *
88
- * @param Object params
83
+ * @param Object config
89
84
  *
90
85
  * @return Void
91
86
  */
92
- function realtime( params ) {
93
- const window = this, { dom } = window.wq;
87
+ function realtime( config ) {
88
+ const window = this, { dom } = window.webqit;
94
89
  // ----------------
95
90
  const handle = ( target, entry, incoming ) => {
96
- const identifier = entry.getAttribute( params.attr.id );
97
- const ownerRoot = target.closest( params.namespaceSelector ) || _( entry ).get( 'ownerNamespace' ) || window.document;
98
- const namespaceObj = getNamespaceObject.call( window, ownerRoot, params );
91
+ const identifier = entry.getAttribute( config.attr.id );
92
+ const ownerRoot = target.closest( config.namespaceSelector ) || _( entry ).get( 'ownerNamespace' ) || window.document;
93
+ const namespaceObj = getNamespaceObject.call( window, ownerRoot, config );
99
94
  if ( incoming ) {
100
95
  if ( Observer.get( namespaceObj, identifier ) !== entry ) {
101
96
  _( entry ).set( 'ownerNamespace', ownerRoot );
@@ -106,17 +101,17 @@ function realtime( params ) {
106
101
  Observer.deleteProperty( namespaceObj, identifier );
107
102
  }
108
103
  };
109
- dom.realtime( window.document ).observe( params.idSelector, record => {
104
+ dom.realtime( window.document ).observe( config.idSelector, record => {
110
105
  record.entrants.forEach( entry => handle( record.target, entry, true ) );
111
106
  record.exits.forEach( entry => handle( record.target, entry, false ) );
112
- }, { subtree: true, timing: 'sync', staticSensitivity: params.staticsensitivity } );
107
+ }, { subtree: true, timing: 'sync', staticSensitivity: config.staticsensitivity } );
113
108
  // ----------------
114
- if ( params.staticsensitivity ) {
115
- dom.realtime( window.document, 'attr' ).observe( params.namespaceSelector, record => {
116
- const ownerRoot = record.target.parentNode?.closest( params.namespaceSelector ) || _( record.target ).get( 'ownerNamespace' ) || window.document;
117
- const ownerRootNamespaceObj = getNamespaceObject.call( window, ownerRoot, params );
118
- const namespaceObj = getNamespaceObject.call( window, record.target, params );
119
- if ( record.target.matches( params.namespaceSelector ) ) {
109
+ if ( config.staticsensitivity ) {
110
+ dom.realtime( window.document, 'attr' ).observe( config.namespaceSelector, record => {
111
+ const ownerRoot = record.target.parentNode?.closest( config.namespaceSelector ) || _( record.target ).get( 'ownerNamespace' ) || window.document;
112
+ const ownerRootNamespaceObj = getNamespaceObject.call( window, ownerRoot, config );
113
+ const namespaceObj = getNamespaceObject.call( window, record.target, config );
114
+ if ( record.target.matches( config.namespaceSelector ) ) {
120
115
  for ( const [ key, entry ] of Object.entries( ownerRootNamespaceObj ) ) {
121
116
  if ( !record.target.contains( entry.parentNode ) ) continue;
122
117
  Observer.deleteProperty( ownerRootNamespaceObj, key );
@@ -25,11 +25,11 @@ export default class Compiler {
25
25
  }
26
26
 
27
27
  // Set window property
28
- constructor( window, params, executeCallback ) {
28
+ constructor( window, config, executeCallback ) {
29
29
  this.window = window;
30
- this.params = params;
30
+ this.config = config;
31
31
  // This is a global function
32
- window.wq.oohtml.Script.run = ( execHash ) => {
32
+ window.webqit.oohtml.Script.run = ( execHash ) => {
33
33
  const exec = this.constructor.fromHash( execHash );
34
34
  if ( !exec ) throw new Error( `Argument must be a valid exec hash.` );
35
35
  const { script, compiledScript, thisContext } = exec;
@@ -37,7 +37,7 @@ export default class Compiler {
37
37
  if ( !thisContext.scripts ) { Object.defineProperty( thisContext, 'scripts', { value: new Set } ); }
38
38
  thisContext.scripts.add( script );
39
39
  }
40
- switch ( params.script.retention ) {
40
+ switch ( config.script.retention ) {
41
41
  case 'dispose':
42
42
  script.remove();
43
43
  break;
@@ -54,7 +54,7 @@ export default class Compiler {
54
54
  // Compile scipt
55
55
  compile( script, thisContext ) {
56
56
  const _static = this.constructor;
57
- const { wq: { oohtml, SubscriptFunction } } = this.window;
57
+ const { webqit: { oohtml, SubscriptFunction } } = this.window;
58
58
  const cache = oohtml.Script.compileCache[ script.contract ? 0 : 1 ];
59
59
  const sourceHash = _static.toHash( script.textContent );
60
60
  // Script instances are parsed only once
@@ -72,7 +72,7 @@ export default class Compiler {
72
72
  }
73
73
  }
74
74
  // Let's obtain a material functions
75
- let _Function, { parserParams, compilerParams, runtimeParams } = this.params.config;
75
+ let _Function, { parserParams, compilerParams, runtimeParams } = this.config.advanced;
76
76
  if ( script.contract ) {
77
77
  parserParams = { ...parserParams, allowAwaitOutsideFunction: script.type === 'module' };
78
78
  runtimeParams = { ...runtimeParams, async: script.type === 'module' };
@@ -93,7 +93,7 @@ export default class Compiler {
93
93
  cache.set( sourceHash, compiledScript );
94
94
  }
95
95
  const execHash = _static.toHash( { script, compiledScript, thisContext } );
96
- script.textContent = `wq.oohtml.Script.run('${ execHash }');`;
96
+ script.textContent = `webqit.oohtml.Script.run('${ execHash }');`;
97
97
  }
98
98
 
99
99
  // Match import statements
@@ -6,35 +6,30 @@ import { resolveParams } from '@webqit/subscript/src/params.js';
6
6
  import SubscriptFunction from '@webqit/subscript/src/SubscriptFunctionLite.js';
7
7
  import Observer from '@webqit/observer';
8
8
  import Compiler from './Compiler.js';
9
- import wqDom from '@webqit/dom';
9
+ import { _init } from '../util.js';
10
10
 
11
11
  /**
12
12
  * @init
13
13
  *
14
- * @param Object $params
14
+ * @param Object $config
15
15
  */
16
- export default function init( $params = {} ) {
17
- const window = this, dom = wqDom.call( window );
18
- if ( !window.wq ) { window.wq = {}; }
19
- if ( !window.wq.oohtml ) { window.wq.oohtml = {}; }
20
- window.wq.oohtml.Script = { compileCache: [ new Map, new Map, ] };
21
- window.wq.SubscriptFunction = $params.SubscriptFunction/* allow for injection, e.g. from test runner */ || SubscriptFunction;
22
- window.wq.Observer = Observer;
23
- // -------
24
- const params = dom.meta( 'oohtml' ).copyWithDefaults( $params, {
16
+ export default function init( { advanced = {}, ...$config } ) {
17
+ const { config, window } = _init.call( this, 'scoped-js', $config, {
25
18
  script: { retention: 'retain', mimeType: '' },
26
- config: resolveParams( {
27
- parserParams: { allowReturnOutsideFunction: false, allowSuperOutsideMethod: false, ...( $params.parserParams || {} ) },
28
- compilerParams: { globalsNoObserve: [ 'alert' ], ...( $params.compilerParams || {} ) },
29
- runtimeParams: { apiVersion: 2, ...( $params.runtimeParams || {} ) },
19
+ advanced: resolveParams( advanced, {
20
+ parserParams: { allowReturnOutsideFunction: false, allowSuperOutsideMethod: false },
21
+ compilerParams: { globalsNoObserve: [ 'alert' ] },
22
+ runtimeParams: { apiVersion: 2 },
30
23
  } ),
31
24
  } );
32
- params.scriptSelector = ( Array.isArray( params.script.mimeType ) ? params.script.mimeType : [ params.script.mimeType ] ).reduce( ( selector, mm ) => {
25
+ config.scriptSelector = ( Array.isArray( config.script.mimeType ) ? config.script.mimeType : [ config.script.mimeType ] ).reduce( ( selector, mm ) => {
33
26
  const qualifier = mm ? `[type=${ window.CSS.escape( mm ) }]` : '';
34
27
  return selector.concat( `script${ qualifier }[scoped],script${ qualifier }[contract]` );
35
28
  }, [] ).join( ',' );
36
- // -------
37
- realtime.call( this, params );
29
+ window.webqit.oohtml.Script = { compileCache: [ new Map, new Map, ] };
30
+ window.webqit.SubscriptFunction = $config.SubscriptFunction/* allow for injection, e.g. from test runner */ || SubscriptFunction;
31
+ window.webqit.Observer = Observer;
32
+ realtime.call( window, config );
38
33
  }
39
34
 
40
35
  export {
@@ -65,7 +60,7 @@ export function execute( compiledScript, thisContext, script ) {
65
60
  } );
66
61
  } );
67
62
  }
68
- const window = this, { dom } = window.wq;
63
+ const window = this, { dom } = window.webqit;
69
64
  dom.realtime( window.document ).observe( thisContext, () => {
70
65
  if ( script.contract ) {
71
66
  // Rerending processes,,,
@@ -82,14 +77,14 @@ export function execute( compiledScript, thisContext, script ) {
82
77
  /**
83
78
  * Performs realtime capture of elements and builds their relationships.
84
79
  *
85
- * @param Object params
80
+ * @param Object config
86
81
  *
87
82
  * @return Void
88
83
  */
89
- function realtime( params ) {
90
- const window = this, { dom } = window.wq;
91
- const compiler = new Compiler( window, params, execute ), handled = () => {};
92
- dom.realtime( window.document ).observe( params.scriptSelector, record => {
84
+ function realtime( config ) {
85
+ const window = this, { dom } = window.webqit;
86
+ const compiler = new Compiler( window, config, execute ), handled = () => {};
87
+ dom.realtime( window.document ).observe( config.scriptSelector, record => {
93
88
  record.entrants.forEach( script => {
94
89
  if ( 'contract' in script ) return handled( script );
95
90
  Object.defineProperty( script, 'contract', { value: script.hasAttribute( 'contract' ) } );
@@ -10,5 +10,5 @@ import init, { Observer } from './index.js';
10
10
  init.call( window );
11
11
 
12
12
  // As globals
13
- if ( !self.wq ) { self.wq = {}; }
14
- self.wq.Observer = Observer;
13
+ if ( !self.webqit ) { self.webqit = {}; }
14
+ self.webqit.Observer = Observer;
package/src/util.js CHANGED
@@ -2,11 +2,23 @@
2
2
  /**
3
3
  * @imports
4
4
  */
5
+ import webqitDom from '@webqit/dom';
5
6
  import { _internals } from '@webqit/util/js/index.js';
7
+ import { _inherit } from '@webqit/util/obj/index.js';
6
8
 
7
9
  export const _ = ( node, ...args ) => _internals( node, 'oohtml', ...args );
8
10
 
9
- export const _compare = ( a, b, depth = 1, objectSizing = false ) => {
11
+ export function _init( name, $config, $defaults ) {
12
+ const window = this, dom = webqitDom.call( window );
13
+ window.webqit || ( window.webqit = {} );
14
+ window.webqit.oohtml || ( window.webqit.oohtml = {} );
15
+ window.webqit.oohtml.configs || ( window.webqit.oohtml.configs = {} );
16
+ const config = _inherit( 1, dom.meta( name ).json(), $config, $defaults );
17
+ window.webqit.oohtml.configs[ name.toUpperCase().replace( '-', '_' ) ] = config;
18
+ return { config, dom, window };
19
+ }
20
+
21
+ export function _compare( a, b, depth = 1, objectSizing = false ) {
10
22
  if ( depth && typeof a === 'object' && a && typeof b === 'object' && b && ( !objectSizing || Object.keys( a ).length === Object.keys( b ).length ) ) {
11
23
  for ( let key in a ) {
12
24
  if ( !_compare( a[ key ], b[ key ], depth - 1, objectSizing ) ) return false;
@@ -0,0 +1,42 @@
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import { expect } from 'chai';
6
+ import { createDocument } from './index.js';
7
+ import Observer from '@webqit/observer';
8
+
9
+ describe(`Bindings API`, function() {
10
+
11
+ describe( `Basic...`, function() {
12
+
13
+ const head = ``;
14
+ const body = ``;
15
+ const { document } = createDocument( head, body );
16
+
17
+ it ( `The document object and elements should expose a "bindings" property each...`, async function() {
18
+ expect( document ).to.have.property( 'bindings' );
19
+ expect( document.body ).to.have.property( 'bindings' );
20
+ } );
21
+
22
+ it ( `Bindings objects should be observable...`, async function() {
23
+ let idReceived = null;
24
+ Observer.observe( document.bindings, records => {
25
+ idReceived = records[ 0 ].key;
26
+ } );
27
+ document.bindings.someKey = 'someValue'; // new
28
+ expect( idReceived ).to.eq( 'someKey' );
29
+ // -------------
30
+ let changes = [];
31
+ Observer.observe( document.bindings, records => {
32
+ changes.push( ...records );
33
+ } );
34
+ document.bindings.someKey2 = 'someValue2'; // new
35
+ document.bind( { someKey: 'someValue'/* update */, someKey3: 'someValue3'/* new */ } );
36
+ expect( changes ).to.an( 'array' ).with.length( 4 ); // (1) sets: someKey2, (2) deletes: someKey2, (3) updates: someKey, (4) sets: someKey3;
37
+ } );
38
+
39
+ } );
40
+
41
+ } );
42
+
package/test/index.js CHANGED
@@ -7,7 +7,7 @@ import { createContext, compileFunction, runInContext } from 'vm';
7
7
  import jsdom from 'jsdom';
8
8
  import init, { Observer } from '../src/index.js';
9
9
  import { SubscriptFunction } from '@webqit/subscript';
10
- import wqDom from '@webqit/dom';
10
+ import webqitDom from '@webqit/dom';
11
11
 
12
12
  /**
13
13
  * -------
@@ -35,7 +35,7 @@ export function createDocument( head = '', body = '', callback = null, ) {
35
35
  url: 'http://localhost',
36
36
  beforeParse( window ) {
37
37
  init.call( window );
38
- if ( callback ) callback( window, window.wq.dom );
38
+ if ( callback ) callback( window, window.webqit.dom );
39
39
  }
40
40
  } );
41
41
  return instance.window;
@@ -55,16 +55,18 @@ export function createDocumentForScopedJS( head = '', body = '', callback = null
55
55
  window.testRecords = [];
56
56
  createContext( window );
57
57
  // Running advanced scripts
58
- init.call( window, { ScopedJS: {
58
+ init.call( window, { SCOPED_JS: {
59
59
  SubscriptFunction,
60
- runtimeParams: {
61
- compileFunction: ( code, parameters ) => compileFunction( code, parameters, {
62
- parsingContext: window,
63
- } ),
60
+ advanced: {
61
+ runtimeParams: {
62
+ compileFunction: ( code, parameters ) => compileFunction( code, parameters, {
63
+ parsingContext: window,
64
+ } ),
65
+ }
64
66
  }
65
67
  } } );
66
68
  // Running basic scripts
67
- const dom = wqDom.call( window );
69
+ const dom = webqitDom.call( window );
68
70
  if ( params.runScripts !== 'dangerously' ) {
69
71
  dom.realtime( window.document ).observe( 'script', record => {
70
72
  record.entrants.forEach( script => {
@@ -74,7 +76,7 @@ export function createDocumentForScopedJS( head = '', body = '', callback = null
74
76
  }, { subtree: true } );
75
77
  }
76
78
  // Sync callback?
77
- if ( callback ) callback( window, window.wq.dom );
79
+ if ( callback ) callback( window, window.webqit.dom );
78
80
  }
79
81
  } );
80
82
  return instance.window;