@webqit/oohtml 3.2.0 → 4.0.0
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 +161 -68
- 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 +16 -16
- 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 +23 -23
- package/dist/main.js.map +3 -3
- package/dist/main.lite.js +24 -30
- 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 +4 -4
- package/src/data-binding/index.js +3 -3
- package/src/namespaced-html/index.js +204 -141
- package/src/scoped-css/index.js +43 -32
- package/src/scoped-js/index.js +12 -11
- package/src/util.js +11 -0
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
|
@@ -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, ],
|
|
@@ -88,24 +88,25 @@ async function execute( config, execHash ) {
|
|
|
88
88
|
*/
|
|
89
89
|
function realtime( config ) {
|
|
90
90
|
const window = this, { webqit: { oohtml, realdom, QuantumScript, QuantumAsyncScript, QuantumModule } } = window;
|
|
91
|
-
if ( !window.HTMLScriptElement.supports ) { window.HTMLScriptElement.supports =
|
|
92
|
-
const
|
|
91
|
+
if ( !window.HTMLScriptElement.supports ) { window.HTMLScriptElement.supports = type => [ 'text/javascript', 'application/javascript' ].includes( type ); }
|
|
92
|
+
const handled = new WeakSet;
|
|
93
93
|
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.scriptSelector, record => {
|
|
94
94
|
record.entrants.forEach( script => {
|
|
95
95
|
if ( handled.has( script ) ) return;
|
|
96
|
+
const textContent = ( script._ = script.textContent.trim() ) && script._.startsWith( '/*@oohtml*/if(false){' ) && script._.endsWith( '}/*@oohtml*/' ) ? script._.slice( 21, -12 ) : script.textContent;
|
|
97
|
+
if ( !script.scoped && !script.quantum && !textContent.includes( 'quantum' ) ) return;
|
|
96
98
|
handled.add( script );
|
|
97
99
|
// Do compilation
|
|
98
|
-
const textContent = ( script._ = script.textContent.trim() ) && script._.startsWith( '/*@oohtml*/if(false){' ) && script._.endsWith( '}/*@oohtml*/' ) ? script._.slice( 21, -12 ) : script.textContent;
|
|
99
100
|
const sourceHash = _toHash( textContent );
|
|
100
101
|
const compileCache = oohtml.Script.compileCache[ script.quantum ? 0 : 1 ];
|
|
101
102
|
let compiledScript;
|
|
102
103
|
if ( !( compiledScript = compileCache.get( sourceHash ) ) ) {
|
|
103
104
|
const { parserParams, compilerParams, runtimeParams } = config.advanced;
|
|
104
|
-
compiledScript = new ( script.type === 'module' ? QuantumModule : (QuantumScript || QuantumAsyncScript) )( textContent, {
|
|
105
|
+
compiledScript = new ( script.type === 'module' ? QuantumModule : ( QuantumScript || QuantumAsyncScript ) )( textContent, {
|
|
105
106
|
exportNamespace: `#${ script.id }`,
|
|
106
107
|
fileName: `${ window.document.url?.split( '#' )?.[ 0 ] || '' }#${ script.id }`,
|
|
107
|
-
parserParams,
|
|
108
|
-
compilerParams
|
|
108
|
+
parserParams: { ...parserParams, quantumMode: script.quantum },
|
|
109
|
+
compilerParams,
|
|
109
110
|
runtimeParams,
|
|
110
111
|
} );
|
|
111
112
|
compileCache.set( sourceHash, compiledScript );
|
|
@@ -114,7 +115,7 @@ function realtime( config ) {
|
|
|
114
115
|
const thisContext = script.scoped ? script.parentNode || record.target : ( script.type === 'module' ? undefined : window );
|
|
115
116
|
if ( script.scoped ) { thisContext[ config.api.scripts ].push( script ); }
|
|
116
117
|
const execHash = _toHash( { script, compiledScript, thisContext } );
|
|
117
|
-
const manualHandling = record.type === 'query' || (
|
|
118
|
+
const manualHandling = record.type === 'query' || ( script.type && !window.HTMLScriptElement.supports( script.type ) );
|
|
118
119
|
if ( manualHandling ) { oohtml.Script.execute( execHash ); } else {
|
|
119
120
|
script.textContent = `webqit.oohtml.Script.execute( '${ execHash }' );`;
|
|
120
121
|
}
|
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 ) {
|