@webqit/oohtml 3.2.0 → 4.0.1
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 +189 -78
- package/dist/bindings-api.js +1 -1
- package/dist/bindings-api.js.map +3 -3
- package/dist/context-api.js +1 -1
- package/dist/context-api.js.map +3 -3
- package/dist/data-binding.js +15 -15
- package/dist/data-binding.js.map +3 -3
- package/dist/html-imports.js +1 -1
- package/dist/html-imports.js.map +3 -3
- package/dist/main.js +24 -24
- package/dist/main.js.map +3 -3
- package/dist/main.lite.js +25 -31
- 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 +4 -4
- 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 +5 -5
- package/src/data-binding/index.js +4 -4
- package/src/index.js +3 -21
- package/src/{api.global.lite.js → index.lite.js} +1 -1
- package/src/init.js +28 -0
- package/src/namespaced-html/index.js +204 -141
- package/src/scoped-css/index.js +43 -32
- package/src/scoped-js/index.js +20 -15
- package/src/util.js +11 -0
- package/src/api.global.js +0 -11
package/src/scoped-css/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @imports
|
|
4
4
|
*/
|
|
5
|
-
import { rewriteSelector } from '../namespaced-html/index.js';
|
|
6
|
-
import { _init, _toHash
|
|
5
|
+
import { rewriteSelector, getOwnerNamespaceObject, getNamespaceUUID } from '../namespaced-html/index.js';
|
|
6
|
+
import { _init, _toHash } from '../util.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @init
|
|
@@ -13,11 +13,11 @@ import { _init, _toHash, _splitOuter } from '../util.js';
|
|
|
13
13
|
export default function init({ advanced = {}, ...$config }) {
|
|
14
14
|
const { config, window } = _init.call( this, 'scoped-css', $config, {
|
|
15
15
|
api: { styleSheets: 'styleSheets' },
|
|
16
|
-
style: { retention: 'retain',
|
|
16
|
+
style: { retention: 'retain', mimeTypes: 'text/css', strategy: null },
|
|
17
17
|
} );
|
|
18
|
-
config.styleSelector = (Array.isArray( config.style.
|
|
19
|
-
const qualifier = mm ? `[type
|
|
20
|
-
return selector.concat( `style${ qualifier }
|
|
18
|
+
config.styleSelector = (Array.isArray( config.style.mimeTypes ) ? config.style.mimeTypes : config.style.mimeTypes.split( '|' ) ).concat( '' ).reduce( ( selector, mm ) => {
|
|
19
|
+
const qualifier = mm ? `[type="${ window.CSS.escape( mm ) }"]` : ':not([type])';
|
|
20
|
+
return selector.concat( `style${ qualifier }` );
|
|
21
21
|
}, [] ).join( ',' );
|
|
22
22
|
window.webqit.oohtml.Style = {
|
|
23
23
|
compileCache: new Map,
|
|
@@ -62,80 +62,91 @@ function realtime( config ) {
|
|
|
62
62
|
record.entrants.forEach( style => {
|
|
63
63
|
if ( handled.has( style ) ) return;
|
|
64
64
|
handled.add( style );
|
|
65
|
-
if ( !style.scoped ) return;
|
|
66
65
|
// Do compilation
|
|
67
66
|
const sourceHash = _toHash( style.textContent );
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
const supportsHAS = CSS.supports( 'selector(:has(a,b))' );
|
|
68
|
+
const scopeSelector = style.scoped && ( supportsHAS ? `:has(> style[rand-${ sourceHash }])` : `[rand-${ sourceHash }]` );
|
|
69
|
+
const supportsScope = style.scoped && window.CSSScopeRule && false/* Disabled for buggy behaviour: rewriting selectorText within an @scope block invalidates the scoping */;
|
|
70
|
+
if ( style.scoped ) {
|
|
71
|
+
style.parentNode[ config.api.styleSheets ].push( style );
|
|
72
|
+
( supportsHAS ? style : style.parentNode ).toggleAttribute( `rand-${ sourceHash }`, true );
|
|
73
|
+
}
|
|
74
|
+
if ( style.scoped && style.hasAttribute( 'shared' ) ) {
|
|
75
|
+
let compiledSheet;
|
|
76
|
+
if ( !( compiledSheet = oohtml.Style.compileCache.get( sourceHash ) ) ) {
|
|
77
|
+
compiledSheet = createAdoptableStylesheet.call( window, style, null, supportsScope, scopeSelector );
|
|
78
|
+
oohtml.Style.compileCache.set( sourceHash, compiledSheet );
|
|
79
|
+
}
|
|
80
|
+
// Run now!!!
|
|
81
|
+
Object.defineProperty( style, 'sheet', { value: compiledSheet, configurable: true } );
|
|
82
|
+
style.textContent = '\n/*[ Shared style sheet ]*/\n';
|
|
83
|
+
} else {
|
|
84
|
+
const transform = () => {
|
|
85
|
+
const namespaceUUID = getNamespaceUUID( getOwnerNamespaceObject.call( window, style.scoped ? style : window.document ) );
|
|
86
|
+
upgradeSheet.call( this, style.sheet, namespaceUUID, !supportsScope && scopeSelector );
|
|
87
|
+
};
|
|
88
|
+
if ( style.isConnected ) { transform(); }
|
|
89
|
+
else { setTimeout( () => { transform(); }, 0 ); }
|
|
74
90
|
}
|
|
75
|
-
// Run now!!!
|
|
76
|
-
style.parentNode[ config.api.styleSheets ].push( style );
|
|
77
|
-
Object.defineProperty( style, 'sheet', { value: compiledSheet, configurable: true } );
|
|
78
|
-
( supportsHAS ? style : style.parentNode ).toggleAttribute( `rand-${ sourceHash }`, true );
|
|
79
|
-
style.textContent = '\n/*[ Shared style sheet ]*/\n';
|
|
80
91
|
} );
|
|
81
92
|
}, { live: true, timing: 'intercept', generation: 'entrants' } );
|
|
82
93
|
// ---
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
function createAdoptableStylesheet( style, scopeSelector ) {
|
|
86
|
-
const window = this, textContent = style.textContent
|
|
87
|
-
let styleSheet, cssText = supportsScope ? `@scope (${ scopeSelector }) {\n${ textContent.trim() }\n}` : textContent.trim();
|
|
96
|
+
function createAdoptableStylesheet( style, namespaceUUID, supportsScope, scopeSelector ) {
|
|
97
|
+
const window = this, textContent = style.textContent;
|
|
98
|
+
let styleSheet, cssText = supportsScope && scopeSelector ? `@scope (${ scopeSelector }) {\n${ textContent.trim() }\n}` : textContent.trim();
|
|
88
99
|
try {
|
|
89
100
|
styleSheet = new window.CSSStyleSheet;
|
|
90
101
|
styleSheet.replaceSync( cssText );
|
|
91
|
-
upgradeSheet( styleSheet, !supportsScope && scopeSelector );
|
|
102
|
+
upgradeSheet.call( this, styleSheet, namespaceUUID, !supportsScope && scopeSelector );
|
|
92
103
|
document.adoptedStyleSheets.push( styleSheet );
|
|
93
104
|
} catch( e ) {
|
|
94
105
|
const style = window.document.createElement( 'style' );
|
|
95
106
|
window.document.body.appendChild( style );
|
|
96
107
|
style.textContent = cssText;
|
|
97
108
|
styleSheet = style.sheet;
|
|
98
|
-
upgradeSheet( styleSheet, !supportsScope && scopeSelector );
|
|
109
|
+
upgradeSheet.call( this, styleSheet, namespaceUUID, !supportsScope && scopeSelector );
|
|
99
110
|
}
|
|
100
111
|
return styleSheet;
|
|
101
112
|
}
|
|
102
113
|
|
|
103
|
-
function upgradeSheet( styleSheet, scopeSelector = null ) {
|
|
114
|
+
function upgradeSheet( styleSheet, namespaceUUID, scopeSelector = null ) {
|
|
104
115
|
const l = styleSheet?.cssRules.length || -1;
|
|
105
116
|
for ( let i = 0; i < l; ++i ) {
|
|
106
117
|
const cssRule = styleSheet.cssRules[ i ];
|
|
107
118
|
if ( cssRule instanceof CSSImportRule ) {
|
|
108
119
|
// Handle imported stylesheets
|
|
109
|
-
//upgradeSheet( cssRule.styleSheet, scopeSelector );
|
|
120
|
+
//upgradeSheet( cssRule.styleSheet, namespaceUUID, scopeSelector );
|
|
110
121
|
continue;
|
|
111
122
|
}
|
|
112
|
-
upgradeRule( cssRule, scopeSelector );
|
|
123
|
+
upgradeRule.call( this, cssRule, namespaceUUID, scopeSelector );
|
|
113
124
|
}
|
|
114
125
|
}
|
|
115
126
|
|
|
116
|
-
function upgradeRule( cssRule, scopeSelector = null ) {
|
|
127
|
+
function upgradeRule( cssRule, namespaceUUID, scopeSelector = null ) {
|
|
117
128
|
if ( cssRule instanceof CSSStyleRule ) {
|
|
118
129
|
// Resolve relative IDs and scoping (for non-@scope browsers)
|
|
119
|
-
upgradeSelector( cssRule, scopeSelector );
|
|
130
|
+
upgradeSelector.call( this, cssRule, namespaceUUID, scopeSelector );
|
|
120
131
|
return;
|
|
121
132
|
}
|
|
122
133
|
if ( [ window.CSSScopeRule, window.CSSMediaRule, window.CSSContainerRule, window.CSSSupportsRule, window.CSSLayerBlockRule ].some( type => type && cssRule instanceof type ) ) {
|
|
123
134
|
// Parse @rule blocks
|
|
124
135
|
const l = cssRule.cssRules.length;
|
|
125
136
|
for ( let i = 0; i < l; ++i ) {
|
|
126
|
-
upgradeRule( cssRule.cssRules[ i ], scopeSelector );
|
|
137
|
+
upgradeRule.call( this, cssRule.cssRules[ i ], namespaceUUID, scopeSelector );
|
|
127
138
|
}
|
|
128
139
|
}
|
|
129
140
|
}
|
|
130
141
|
|
|
131
|
-
function upgradeSelector( cssRule, scopeSelector = null ) {
|
|
132
|
-
const newSelectorText = rewriteSelector( cssRule.selectorText, scopeSelector,
|
|
142
|
+
function upgradeSelector( cssRule, namespaceUUID, scopeSelector = null ) {
|
|
143
|
+
const newSelectorText = rewriteSelector.call( this, cssRule.selectorText, namespaceUUID, scopeSelector, 1 );
|
|
133
144
|
cssRule.selectorText = newSelectorText;
|
|
134
145
|
// Parse nested blocks. (CSS nesting)
|
|
135
146
|
if ( cssRule.cssRules ) {
|
|
136
147
|
const l = cssRule.cssRules.length;
|
|
137
148
|
for ( let i = 0; i < l; ++i ) {
|
|
138
|
-
upgradeSelector( cssRule.cssRules[ i ], /* Nesting has nothing to do with scopeSelector */ );
|
|
149
|
+
upgradeSelector.call( this, cssRule.cssRules[ i ], namespaceUUID, /* Nesting has nothing to do with scopeSelector */ );
|
|
139
150
|
}
|
|
140
151
|
}
|
|
141
152
|
}
|
package/src/scoped-js/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @imports
|
|
4
4
|
*/
|
|
5
5
|
import { resolveParams } from '@webqit/quantum-js/params';
|
|
6
|
-
import { _init, _toHash, _fromHash } from '../util.js';
|
|
6
|
+
import { _, _init, _toHash, _fromHash } from '../util.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @init
|
|
@@ -12,13 +12,13 @@ import { _init, _toHash, _fromHash } from '../util.js';
|
|
|
12
12
|
*/
|
|
13
13
|
export default function init({ advanced = {}, ...$config }) {
|
|
14
14
|
const { config, window } = _init.call( this, 'scoped-js', $config, {
|
|
15
|
-
script: { retention: 'retain',
|
|
15
|
+
script: { retention: 'retain', mimeTypes: 'module|text/javascript|application/javascript' },
|
|
16
16
|
api: { scripts: 'scripts' },
|
|
17
17
|
advanced: resolveParams(advanced),
|
|
18
18
|
} );
|
|
19
|
-
config.scriptSelector = ( Array.isArray( config.script.
|
|
20
|
-
const qualifier = mm ? `[type
|
|
21
|
-
return selector.concat( `script${ qualifier }
|
|
19
|
+
config.scriptSelector = ( Array.isArray( config.script.mimeTypes ) ? config.script.mimeTypes : config.script.mimeTypes.split( '|' ) ).concat( '' ).reduce( ( selector, mm ) => {
|
|
20
|
+
const qualifier = mm ? `[type="${ window.CSS.escape( mm ) }"]` : ':not([type])';
|
|
21
|
+
return selector.concat( `script${ qualifier }` );
|
|
22
22
|
}, [] ).join( ',' );
|
|
23
23
|
window.webqit.oohtml.Script = {
|
|
24
24
|
compileCache: [ new Map, new Map, ],
|
|
@@ -71,9 +71,13 @@ async function execute( config, execHash ) {
|
|
|
71
71
|
script.textContent = await compiledScript.toString();
|
|
72
72
|
}
|
|
73
73
|
// Execute and save state
|
|
74
|
-
const
|
|
74
|
+
const documentRoot = script.getRootNode();
|
|
75
|
+
if ( !_( documentRoot ).has( 'scriptEnv' ) ) {
|
|
76
|
+
_( documentRoot ).set( 'scriptEnv', Object.create( null ) );
|
|
77
|
+
}
|
|
78
|
+
const state = ( await compiledScript.bind( thisContext, _( documentRoot ).get( 'scriptEnv' ) ) ).execute();
|
|
75
79
|
if ( script.quantum ) { Object.defineProperty( script, 'state', { value: state } ); }
|
|
76
|
-
realdom.realtime(
|
|
80
|
+
realdom.realtime( documentRoot ).observe( script, () => {
|
|
77
81
|
if ( script.quantum ) { state.dispose(); }
|
|
78
82
|
if ( script.scoped ) { thisContext[ config.api.scripts ].splice( thisContext[ config.api.scripts ].indexOf( script, 1 ) ); }
|
|
79
83
|
}, { subtree: true, timing: 'sync', generation: 'exits' } );
|
|
@@ -87,25 +91,26 @@ async function execute( config, execHash ) {
|
|
|
87
91
|
* @return Void
|
|
88
92
|
*/
|
|
89
93
|
function realtime( config ) {
|
|
90
|
-
const window = this, { webqit: { oohtml, realdom, QuantumScript,
|
|
91
|
-
if ( !window.HTMLScriptElement.supports ) { window.HTMLScriptElement.supports =
|
|
92
|
-
const
|
|
94
|
+
const window = this, { webqit: { oohtml, realdom, QuantumScript, AsyncQuantumScript, QuantumModule } } = window;
|
|
95
|
+
if ( !window.HTMLScriptElement.supports ) { window.HTMLScriptElement.supports = type => [ 'text/javascript', 'application/javascript' ].includes( type ); }
|
|
96
|
+
const handled = new WeakSet;
|
|
93
97
|
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.scriptSelector, record => {
|
|
94
98
|
record.entrants.forEach( script => {
|
|
95
99
|
if ( handled.has( script ) ) return;
|
|
100
|
+
const textContent = ( script._ = script.textContent.trim() ) && script._.startsWith( '/*@oohtml*/if(false){' ) && script._.endsWith( '}/*@oohtml*/' ) ? script._.slice( 21, -12 ) : script.textContent;
|
|
101
|
+
if ( !script.scoped && !script.quantum && !textContent.includes( 'quantum' ) ) return;
|
|
96
102
|
handled.add( script );
|
|
97
103
|
// Do compilation
|
|
98
|
-
const textContent = ( script._ = script.textContent.trim() ) && script._.startsWith( '/*@oohtml*/if(false){' ) && script._.endsWith( '}/*@oohtml*/' ) ? script._.slice( 21, -12 ) : script.textContent;
|
|
99
104
|
const sourceHash = _toHash( textContent );
|
|
100
105
|
const compileCache = oohtml.Script.compileCache[ script.quantum ? 0 : 1 ];
|
|
101
106
|
let compiledScript;
|
|
102
107
|
if ( !( compiledScript = compileCache.get( sourceHash ) ) ) {
|
|
103
108
|
const { parserParams, compilerParams, runtimeParams } = config.advanced;
|
|
104
|
-
compiledScript = new ( script.type === 'module' ? QuantumModule : (QuantumScript ||
|
|
109
|
+
compiledScript = new ( script.type === 'module' ? QuantumModule : ( QuantumScript || AsyncQuantumScript ) )( textContent, {
|
|
105
110
|
exportNamespace: `#${ script.id }`,
|
|
106
111
|
fileName: `${ window.document.url?.split( '#' )?.[ 0 ] || '' }#${ script.id }`,
|
|
107
|
-
parserParams,
|
|
108
|
-
compilerParams
|
|
112
|
+
parserParams: { ...parserParams, quantumMode: script.quantum },
|
|
113
|
+
compilerParams,
|
|
109
114
|
runtimeParams,
|
|
110
115
|
} );
|
|
111
116
|
compileCache.set( sourceHash, compiledScript );
|
|
@@ -114,7 +119,7 @@ function realtime( config ) {
|
|
|
114
119
|
const thisContext = script.scoped ? script.parentNode || record.target : ( script.type === 'module' ? undefined : window );
|
|
115
120
|
if ( script.scoped ) { thisContext[ config.api.scripts ].push( script ); }
|
|
116
121
|
const execHash = _toHash( { script, compiledScript, thisContext } );
|
|
117
|
-
const manualHandling = record.type === 'query' || (
|
|
122
|
+
const manualHandling = record.type === 'query' || ( script.type && !window.HTMLScriptElement.supports( script.type ) );
|
|
118
123
|
if ( manualHandling ) { oohtml.Script.execute( execHash ); } else {
|
|
119
124
|
script.textContent = `webqit.oohtml.Script.execute( '${ execHash }' );`;
|
|
120
125
|
}
|
package/src/util.js
CHANGED
|
@@ -42,6 +42,17 @@ export function _init( name, $config, $defaults ) {
|
|
|
42
42
|
return { config: window.webqit.oohtml.configs[ configKey ], realdom, window };
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export function getInternalAttrInteraction( node, attrName ) {
|
|
46
|
+
return _internals( node, 'internalAttrInteractions' ).get( attrName );
|
|
47
|
+
}
|
|
48
|
+
export function internalAttrInteraction( node, attrName, callback ) {
|
|
49
|
+
const savedAttrLocking = _internals( node, 'internalAttrInteractions' ).get( attrName );
|
|
50
|
+
_internals( node, 'internalAttrInteractions' ).set( attrName, true );
|
|
51
|
+
const value = callback();
|
|
52
|
+
_internals( node, 'internalAttrInteractions' ).set( attrName, savedAttrLocking );
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
export function _compare( a, b, depth = 1, objectSizing = false ) {
|
|
46
57
|
if ( depth && typeof a === 'object' && a && typeof b === 'object' && b && ( !objectSizing || Object.keys( a ).length === Object.keys( b ).length ) ) {
|
|
47
58
|
for ( let key in a ) {
|