@webqit/oohtml 3.1.18 → 3.1.19
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 +4 -4
- package/dist/main.js +18 -14
- package/dist/main.js.map +2 -2
- package/dist/main.lite.js +15 -11
- package/dist/main.lite.js.map +2 -2
- package/dist/namespaced-html.js +1 -1
- package/dist/namespaced-html.js.map +2 -2
- package/dist/scoped-css.js +5 -1
- package/dist/scoped-css.js.map +2 -2
- package/package.json +1 -1
- package/src/namespaced-html/index.js +100 -100
- package/src/scoped-css/index.js +3 -3
package/package.json
CHANGED
|
@@ -116,13 +116,11 @@ export function rewriteSelector( selectorText, namespaceUUID, scopeSelector = nu
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* Returns the "namespace" object associated with the given node.
|
|
120
|
-
*
|
|
121
119
|
* @param Element node
|
|
122
120
|
*
|
|
123
121
|
* @return Object
|
|
124
122
|
*/
|
|
125
|
-
export function
|
|
123
|
+
export function getOwnNamespaceObject( node ) {
|
|
126
124
|
if ( !_( node ).has( 'namespace' ) ) {
|
|
127
125
|
const namespaceObj = Object.create( null );
|
|
128
126
|
_( node ).set( 'namespace', namespaceObj );
|
|
@@ -132,12 +130,21 @@ export function getNamespaceObject( node ) {
|
|
|
132
130
|
|
|
133
131
|
/**
|
|
134
132
|
* @param Element node
|
|
133
|
+
* @param Bool forID
|
|
135
134
|
*
|
|
136
|
-
* @return
|
|
135
|
+
* @return Object
|
|
137
136
|
*/
|
|
138
|
-
export function
|
|
137
|
+
export function getOwnerNamespaceObject( node, forID = false ) {
|
|
139
138
|
const window = this, { webqit: { oohtml: { configs: { NAMESPACED_HTML: config } } } } = window;
|
|
140
|
-
|
|
139
|
+
return getOwnNamespaceObject( node instanceof window.Document ? node : ( ( forID ? node.parentNode : node )?.closest( `[${ config.attr.namespace }]` ) || node.ownerDocument ) );
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param Object namespaceObj
|
|
144
|
+
*
|
|
145
|
+
* @return String
|
|
146
|
+
*/
|
|
147
|
+
export function getNamespaceUUID( namespaceObj ) {
|
|
141
148
|
return _fromHash( namespaceObj ) || _toHash( namespaceObj );
|
|
142
149
|
}
|
|
143
150
|
|
|
@@ -155,10 +162,10 @@ function exposeAPIs( config ) {
|
|
|
155
162
|
if ( config.api.namespace in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.api.namespace }" property!` ); }
|
|
156
163
|
// Definitions
|
|
157
164
|
Object.defineProperty( window.document, config.api.namespace, { get: function() {
|
|
158
|
-
return Observer.proxy(
|
|
165
|
+
return Observer.proxy( getOwnNamespaceObject.call( window, window.document ) );
|
|
159
166
|
} });
|
|
160
167
|
Object.defineProperty( window.Element.prototype, config.api.namespace, { get: function() {
|
|
161
|
-
return Observer.proxy(
|
|
168
|
+
return Observer.proxy( getOwnNamespaceObject.call( window, this ) );
|
|
162
169
|
} } );
|
|
163
170
|
}
|
|
164
171
|
|
|
@@ -171,24 +178,6 @@ function exposeAPIs( config ) {
|
|
|
171
178
|
*/
|
|
172
179
|
function realtime( config ) {
|
|
173
180
|
const window = this, { webqit: { Observer, realdom, oohtml: { configs }, DOMNamingContext } } = window;
|
|
174
|
-
|
|
175
|
-
// ------------
|
|
176
|
-
// NAMESPACE
|
|
177
|
-
// ------------
|
|
178
|
-
window.document[ configs.CONTEXT_API.api.contexts ].attach( new DOMNamingContext );
|
|
179
|
-
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.namespaceSelector, record => {
|
|
180
|
-
record.exits.forEach( entry => {
|
|
181
|
-
const contextsApi = entry[ configs.CONTEXT_API.api.contexts ];
|
|
182
|
-
const ctx = contextsApi.find( DOMNamingContext.kind );
|
|
183
|
-
if ( ctx ) { contextsApi.detach( ctx ); }
|
|
184
|
-
} );
|
|
185
|
-
record.entrants.forEach( entry => {
|
|
186
|
-
const contextsApi = entry[ configs.CONTEXT_API.api.contexts ];
|
|
187
|
-
if ( !contextsApi.find( DOMNamingContext.kind ) ) {
|
|
188
|
-
contextsApi.attach( new DOMNamingContext );
|
|
189
|
-
}
|
|
190
|
-
} );
|
|
191
|
-
}, { live: true, timing: 'sync', staticSensitivity: true } );
|
|
192
181
|
|
|
193
182
|
// ------------
|
|
194
183
|
// APIS
|
|
@@ -205,7 +194,7 @@ function realtime( config ) {
|
|
|
205
194
|
const getAttributeDescr = Object.getOwnPropertyDescriptor( window.Element.prototype, 'getAttribute' );
|
|
206
195
|
Object.defineProperty( window.Element.prototype, 'getAttribute', { ...getAttributeDescr, value( attrName ) {
|
|
207
196
|
const value = getAttributeDescr.value.call( this, attrName );
|
|
208
|
-
return !_( this, 'lock' ).get( attrName ) && attrList.includes( attrName ) ? ( attrName === 'id' ? $lidUtil.uuidToLid : $lidUtil.uuidToLidref ).call( $lidUtil, value ) : value;
|
|
197
|
+
return value && !_( this, 'lock' ).get( attrName ) && attrList.includes( attrName ) ? ( attrName === 'id' ? $lidUtil.uuidToLid : $lidUtil.uuidToLidref ).call( $lidUtil, value ) : value;
|
|
209
198
|
} } );
|
|
210
199
|
// Intercept getElementById()
|
|
211
200
|
const getElementByIdDescr = Object.getOwnPropertyDescriptor( window.Document.prototype, 'getElementById' );
|
|
@@ -237,7 +226,7 @@ function realtime( config ) {
|
|
|
237
226
|
const propertyDescr = Object.getOwnPropertyDescriptor( window.Attr.prototype, 'value' );
|
|
238
227
|
Object.defineProperty( window.Attr.prototype, 'value', { ...propertyDescr, get() {
|
|
239
228
|
const value = propertyDescr.get.call( this );
|
|
240
|
-
return attrList.includes( this.name ) ? ( this.name === 'id' ? $lidUtil.uuidToLid : $lidUtil.uuidToLidref ).call( $lidUtil, value ) : value;
|
|
229
|
+
return value && attrList.includes( this.name ) ? ( this.name === 'id' ? $lidUtil.uuidToLid : $lidUtil.uuidToLidref ).call( $lidUtil, value ) : value;
|
|
241
230
|
} } );
|
|
242
231
|
if ( config.attr.lid !== 'id' ) {
|
|
243
232
|
// Reflect the custom [config.attr.lid] attribute
|
|
@@ -251,94 +240,105 @@ function realtime( config ) {
|
|
|
251
240
|
// ------------
|
|
252
241
|
// LOCAL IDS & IDREFS
|
|
253
242
|
// ------------
|
|
254
|
-
const
|
|
243
|
+
const attrChange = ( entry, attrName, value, callback ) => {
|
|
255
244
|
// Create or honour locking
|
|
256
245
|
if ( _( entry, 'lock' ).get( attrName ) ) return;
|
|
257
246
|
_( entry, 'lock' ).set( attrName, true );
|
|
258
|
-
// A function can be passed in to be called after having done the _( entry, 'lock' ).set( attrName, true ); flag
|
|
259
|
-
if ( typeof oldValue === 'function' ) oldValue = oldValue();
|
|
260
|
-
// Get down to work
|
|
261
|
-
const namespaceObj = _( entry ).get( 'ownerNamespace' );
|
|
262
|
-
if ( attrName === config.attr.lid ) {
|
|
263
|
-
const lid = $lidUtil.uuidToLid( oldValue );
|
|
264
|
-
if ( Observer.get( namespaceObj, lid ) === entry ) { Observer.deleteProperty( namespaceObj, lid ); }
|
|
265
|
-
} else {
|
|
266
|
-
const newAttrValue = oldValue.split( ' ' ).map( lid => ( lid = lid.trim() ) && $lidUtil.uuidToLidref( lid ) ).join( ' ' );
|
|
267
|
-
entry.setAttribute( attrName, newAttrValue );
|
|
268
|
-
}
|
|
269
|
-
// Release locking
|
|
270
|
-
_( entry, 'lock' ).delete( attrName );
|
|
271
|
-
};
|
|
272
|
-
const setupBinding = ( entry, attrName, value ) => {
|
|
273
|
-
// Create or honour locking
|
|
274
|
-
if ( _( entry, 'lock' ).get( attrName ) ) return;
|
|
275
|
-
_( entry, 'lock' ).set( attrName, true );
|
|
276
|
-
// A function can be passed in to be called after having done the _( entry, 'lock' ).set( attrName, true ); flag
|
|
277
247
|
if ( typeof value === 'function' ) value = value();
|
|
278
|
-
|
|
279
|
-
const namespaceObj = _( entry ).get( 'ownerNamespace' );
|
|
280
|
-
const namespaceUUID = _( entry ).get( 'namespaceUUID' );
|
|
281
|
-
if ( attrName === config.attr.lid ) {
|
|
282
|
-
const lid = $lidUtil.uuidToLid( value );
|
|
283
|
-
if ( Observer.get( namespaceObj, lid ) !== entry ) {
|
|
284
|
-
// Setup new namespace relationships
|
|
285
|
-
entry.setAttribute( 'id', $lidUtil.toUuid( namespaceUUID, lid ) );
|
|
286
|
-
Observer.set( namespaceObj, lid, entry );
|
|
287
|
-
}
|
|
288
|
-
} else {
|
|
289
|
-
const newAttrValue = value.split( ' ' ).map( lid => ( lid = lid.trim() ) && !$lidUtil.isLidref( lid ) ? lid : $lidUtil.toUuid( namespaceUUID, lid.replace( $lidUtil.lidrefPrefix(), '' ) ) ).join( ' ' );
|
|
290
|
-
entry.setAttribute( attrName, newAttrValue );
|
|
291
|
-
}
|
|
292
|
-
// Release locking
|
|
248
|
+
callback( value );
|
|
293
249
|
_( entry, 'lock' ).delete( attrName );
|
|
294
250
|
};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
251
|
+
const setupBinding = ( entry, attrName, value, newNamespaceObj = null ) => {
|
|
252
|
+
attrChange( entry, attrName, value, value => {
|
|
253
|
+
const isLidAttr = attrName === config.attr.lid;
|
|
254
|
+
const namespaceObj = newNamespaceObj || getOwnerNamespaceObject( entry, isLidAttr );
|
|
255
|
+
const namespaceUUID = getNamespaceUUID( namespaceObj );
|
|
256
|
+
if ( isLidAttr ) {
|
|
257
|
+
const lid = $lidUtil.uuidToLid( value );
|
|
258
|
+
if ( Observer.get( namespaceObj, lid ) !== entry ) {
|
|
259
|
+
entry.setAttribute( 'id', $lidUtil.toUuid( namespaceUUID, lid ) );
|
|
260
|
+
Observer.set( namespaceObj, lid, entry );
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
const newAttrValue = value.split( ' ' ).map( lid => ( lid = lid.trim() ) && !$lidUtil.isLidref( lid ) ? lid : $lidUtil.toUuid( namespaceUUID, lid.replace( $lidUtil.lidrefPrefix(), '' ) ) ).join( ' ' );
|
|
264
|
+
entry.setAttribute( attrName, newAttrValue );
|
|
265
|
+
_( namespaceObj ).set( 'idrefs', _( namespaceObj ).get( 'idrefs' ) || new Set );
|
|
266
|
+
_( namespaceObj ).get( 'idrefs' ).add( entry );
|
|
267
|
+
}
|
|
268
|
+
} );
|
|
307
269
|
};
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
270
|
+
const cleanupBinding = ( entry, attrName, oldValue, prevNamespaceObj = null ) => {
|
|
271
|
+
attrChange( entry, attrName, oldValue, oldValue => {
|
|
272
|
+
const isLidAttr = attrName === config.attr.lid;
|
|
273
|
+
const namespaceObj = prevNamespaceObj || getOwnerNamespaceObject( entry, isLidAttr );
|
|
274
|
+
if ( isLidAttr ) {
|
|
275
|
+
const lid = $lidUtil.uuidToLid( oldValue );
|
|
276
|
+
if ( Observer.get( namespaceObj, lid ) === entry ) {
|
|
277
|
+
Observer.deleteProperty( namespaceObj, lid );
|
|
315
278
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
for ( const attrName of attrList ) {
|
|
325
|
-
if ( !entry.hasAttribute( attrName ) ) continue;
|
|
326
|
-
setupBinding( entry, attrName, () => entry.getAttribute( attrName ) );
|
|
327
|
-
}
|
|
279
|
+
} else {
|
|
280
|
+
const newAttrValue = oldValue.split( ' ' ).map( lid => ( lid = lid.trim() ) && $lidUtil.uuidToLidref( lid ) ).join( ' ' );
|
|
281
|
+
entry.setAttribute( attrName, newAttrValue );
|
|
282
|
+
_( namespaceObj ).get( 'idrefs' ).delete( entry );
|
|
283
|
+
}
|
|
284
|
+
} );
|
|
328
285
|
};
|
|
329
286
|
|
|
287
|
+
// ------------
|
|
288
|
+
// NAMESPACE
|
|
289
|
+
// ------------
|
|
290
|
+
window.document[ configs.CONTEXT_API.api.contexts ].attach( new DOMNamingContext );
|
|
291
|
+
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.namespaceSelector, record => {
|
|
292
|
+
const reAssociate = ( entry, attrName, oldNamespaceObj, newNamespaceObj ) => {
|
|
293
|
+
if ( !entry.hasAttribute( attrName ) ) return;
|
|
294
|
+
const attrValue = () => entry.getAttribute( attrName );
|
|
295
|
+
cleanupBinding( entry, attrName, attrValue, oldNamespaceObj );
|
|
296
|
+
if ( entry.isConnected ) { setupBinding( entry, attrName, attrValue, newNamespaceObj ); }
|
|
297
|
+
};
|
|
298
|
+
record.exits.forEach( entry => {
|
|
299
|
+
const namespaceObj = getOwnNamespaceObject( entry );
|
|
300
|
+
// Detach ID and IDREF associations
|
|
301
|
+
for ( const node of new Set( [ ...Object.values( namespaceObj ), ..._( namespaceObj ).get( 'idrefs' ) ] ) ) {
|
|
302
|
+
for ( const attrName of attrList ) { reAssociate( node, attrName, namespaceObj ); }
|
|
303
|
+
}
|
|
304
|
+
// Detach ID associations
|
|
305
|
+
const contextsApi = entry[ configs.CONTEXT_API.api.contexts ];
|
|
306
|
+
const ctx = contextsApi.find( DOMNamingContext.kind );
|
|
307
|
+
// Detach namespace instance
|
|
308
|
+
if ( ctx ) { contextsApi.detach( ctx ); }
|
|
309
|
+
} );
|
|
310
|
+
record.entrants.forEach( entry => {
|
|
311
|
+
// Claim ID and IDREF associations
|
|
312
|
+
let newSuperNamespaceObj;
|
|
313
|
+
const superNamespaceObj = getOwnerNamespaceObject( entry, true );
|
|
314
|
+
for ( const node of new Set( [ ...Object.values( superNamespaceObj ), ...( _( superNamespaceObj ).get( 'idrefs' ) || [] ) ] ) ) {
|
|
315
|
+
if ( ( newSuperNamespaceObj = getOwnerNamespaceObject( node, true ) ) === superNamespaceObj ) continue;
|
|
316
|
+
for ( const attrName of attrList ) { reAssociate( node, attrName, superNamespaceObj, newSuperNamespaceObj ); }
|
|
317
|
+
}
|
|
318
|
+
// Attach namespace instance
|
|
319
|
+
const contextsApi = entry[ configs.CONTEXT_API.api.contexts ];
|
|
320
|
+
if ( !contextsApi.find( DOMNamingContext.kind ) ) { contextsApi.attach( new DOMNamingContext ); }
|
|
321
|
+
} );
|
|
322
|
+
}, { live: true, timing: 'sync', staticSensitivity: true } );
|
|
323
|
+
|
|
330
324
|
// DOM realtime
|
|
331
325
|
realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( `[${ attrList.map( attrName => window.CSS.escape( attrName ) ).join( '],[' ) }]`, record => {
|
|
332
|
-
|
|
333
|
-
|
|
326
|
+
for ( const attrName of attrList ) {
|
|
327
|
+
record.exits.forEach( entry => {
|
|
328
|
+
if ( !entry.hasAttribute( attrName ) ) return;
|
|
329
|
+
cleanupBinding( entry, attrName, () => entry.getAttribute( attrName ) );
|
|
330
|
+
} );
|
|
331
|
+
record.entrants.forEach( entry => {
|
|
332
|
+
if ( !entry.hasAttribute( attrName ) ) return;
|
|
333
|
+
setupBinding( entry, attrName, () => entry.getAttribute( attrName ) );
|
|
334
|
+
} );
|
|
335
|
+
}
|
|
334
336
|
}, { live: true, timing: 'sync' } );
|
|
335
337
|
// Attr realtime
|
|
336
338
|
realdom.realtime( window.document, 'attr' ).observe( attrList, records => {
|
|
337
339
|
for ( const record of records ) {
|
|
338
|
-
if ( record.oldValue ) {
|
|
339
|
-
|
|
340
|
-
if ( record.value ) { setupBinding( record.target, record.name, record.value ); }
|
|
341
|
-
} else { setupAllBindings( entry ); }
|
|
340
|
+
if ( record.oldValue ) { cleanupBinding( record.target, record.name, record.oldValue ); }
|
|
341
|
+
if ( record.value ) { setupBinding( record.target, record.name, record.value ); }
|
|
342
342
|
}
|
|
343
343
|
}, { subtree: true, timing: 'sync', newValue: true, oldValue: true } );
|
|
344
344
|
|
package/src/scoped-css/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @imports
|
|
4
4
|
*/
|
|
5
|
-
import { rewriteSelector, getNamespaceUUID } from '../namespaced-html/index.js';
|
|
5
|
+
import { rewriteSelector, getOwnerNamespaceObject, getNamespaceUUID } from '../namespaced-html/index.js';
|
|
6
6
|
import { _init, _toHash } from '../util.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -70,7 +70,7 @@ function realtime( config ) {
|
|
|
70
70
|
const scopeSelector = supportsHAS ? `:has(> style[rand-${ sourceHash }])` : `[rand-${ sourceHash }]`;
|
|
71
71
|
const supportsScope = window.CSSScopeRule && false/* Disabled for buggy behaviour: rewriting selectorText within an @scope block invalidates the scoping */;
|
|
72
72
|
( supportsHAS ? style : style.parentNode ).toggleAttribute( `rand-${ sourceHash }`, true );
|
|
73
|
-
if (
|
|
73
|
+
if ( style.hasAttribute( 'shared' ) ) {
|
|
74
74
|
let compiledSheet;
|
|
75
75
|
if ( !( compiledSheet = oohtml.Style.compileCache.get( sourceHash ) ) ) {
|
|
76
76
|
compiledSheet = createAdoptableStylesheet.call( window, style, null, supportsScope, scopeSelector );
|
|
@@ -80,7 +80,7 @@ function realtime( config ) {
|
|
|
80
80
|
Object.defineProperty( style, 'sheet', { value: compiledSheet, configurable: true } );
|
|
81
81
|
style.textContent = '\n/*[ Shared style sheet ]*/\n';
|
|
82
82
|
} else {
|
|
83
|
-
const namespaceUUID = getNamespaceUUID.call( window, style );
|
|
83
|
+
const namespaceUUID = getNamespaceUUID( getOwnerNamespaceObject.call( window, style ) );
|
|
84
84
|
upgradeSheet.call( this, style.sheet, namespaceUUID, !supportsScope && scopeSelector );
|
|
85
85
|
}
|
|
86
86
|
} );
|