Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/extensions/VisualEditor/lib/ve/src/dm/ve.dm.ModelRegistry.js
Ðазад
/*! * VisualEditor ModelRegistry class. * * @copyright See AUTHORS.txt */ ( function () { /** * Registry for models. * * To register a new model type, call #register. * * @extends OO.Registry * @constructor */ ve.dm.ModelRegistry = function VeDmModelRegistry() { // Parent constructor OO.Registry.call( this ); // Map of func presence and tag names to model names // [ { tagName: [modelNamesWithoutFunc] }, { tagName: [modelNamesWithFunc] } ] this.modelsByTag = [ {}, {} ]; // Map of func presence and rdfaTypes to model names; only rdfaTypes specified as strings are in here // { matchFunctionPresence: { rdfaType: { tagName: [modelNames] } } } // [ { rdfaType: { tagName: [modelNamesWithoutFunc] } }, { rdfaType: { tagName: [modelNamesWithFunc] } ] this.modelsByTypeAndTag = []; // Map of func presence to array of model names with rdfaType regexps // [ [modelNamesWithoutFunc], [modelNamesWithFunc] ] this.modelsWithTypeRegExps = [ [], [] ]; // Map tracking registration order // { nameA: 0, nameB: 1, … } this.registrationOrder = {}; this.nextNumber = 0; this.extSpecificTypes = []; }; /* Inheritance */ OO.inheritClass( ve.dm.ModelRegistry, OO.Registry ); /* Private helper functions */ /** * Helper function for register(). Adds a value to the front of an array in a nested object. * Objects and arrays are created if needed. You can specify one or more keys and a value. * * Specifically: * * - `addType( obj, keyA, value )` does `obj[keyA].unshift( value );` * - `addType( obj, keyA, keyB, value )` does `obj[keyA][keyB].unshift( value )`; * - etc. * * @private * @param {Object} obj Object the array resides in * @param {...string} keys * @param {any} value */ function addType( obj, ...keys ) { const value = keys.pop(); let o = obj; let i, len; for ( i = 0, len = keys.length - 1; i < len; i++ ) { if ( o[ keys[ i ] ] === undefined ) { o[ keys[ i ] ] = {}; } o = o[ keys[ i ] ]; } o[ keys[ i ] ] = o[ keys[ i ] ] || []; o[ keys[ i ] ].unshift( value ); } /** * Helper function for unregister(). * * Same arguments as addType, except removes the type from the list. * * @private * @param {Object} obj Object the array resides in * @param {...string} keys * @param {any} value to remove */ function removeType( obj, ...keys ) { const value = keys.pop(), arr = ve.getProp( obj, ...keys ); if ( arr ) { const index = arr.indexOf( value ); if ( index !== -1 ) { arr.splice( index, 1 ); } // TODO: Prune empty array and empty containing objects } } /* Public methods */ /** * Register a model type. * * @param {ve.dm.Model} constructor Subclass of ve.dm.Model * @throws Model names must be strings and must not be empty * @throws Models must be subclasses of ve.dm.Model * @throws No factory associated with this ve.dm.Model subclass */ ve.dm.ModelRegistry.prototype.register = function ( constructor ) { const name = constructor.static && constructor.static.name; if ( typeof name !== 'string' || name === '' ) { throw new Error( 'Model names must be strings and must not be empty' ); } if ( !( constructor.prototype instanceof ve.dm.Model ) ) { throw new Error( 'Models must be subclasses of ve.dm.Model' ); } if ( this.lookup( name ) === constructor ) { // Don't allow double registration as it would create duplicate // entries in various caches. return; } // Register the model with the right factory if ( constructor.prototype instanceof ve.dm.Annotation ) { ve.dm.annotationFactory.register( constructor ); } else if ( constructor.prototype instanceof ve.dm.Node ) { ve.dm.nodeFactory.register( constructor ); } else { throw new Error( 'No factory associated with this ve.dm.Model subclass' ); } // Parent method ve.dm.ModelRegistry.super.prototype.register.call( this, name, constructor ); const tags = constructor.static.matchTagNames === null ? [ '' ] : constructor.static.matchTagNames; const types = constructor.static.getMatchRdfaTypes() === null ? [ '' ] : constructor.static.getMatchRdfaTypes(); for ( let i = 0; i < tags.length; i++ ) { // +!!foo is a shorter equivalent of Number( Boolean( foo ) ) or foo ? 1 : 0 addType( this.modelsByTag, +!!constructor.static.matchFunction, tags[ i ], name ); } for ( let i = 0; i < types.length; i++ ) { if ( types[ i ] instanceof RegExp ) { // TODO: Guard against running this again during subsequent // iterations of the for loop addType( this.modelsWithTypeRegExps, +!!constructor.static.matchFunction, name ); } else { for ( let j = 0; j < tags.length; j++ ) { addType( this.modelsByTypeAndTag, +!!constructor.static.matchFunction, types[ i ], tags[ j ], name ); } } } this.registrationOrder[ name ] = this.nextNumber++; }; /** * Unregister a model type. * * @param {ve.dm.Model} constructor Subclass of ve.dm.Model * @throws Model names must be strings and must not be empty * @throws Models must be subclasses of ve.dm.Model * @throws No factory associated with this ve.dm.Model subclass */ ve.dm.ModelRegistry.prototype.unregister = function ( constructor ) { const name = constructor.static && constructor.static.name; if ( typeof name !== 'string' || name === '' ) { throw new Error( 'Model names must be strings and must not be empty' ); } if ( !( constructor.prototype instanceof ve.dm.Model ) ) { throw new Error( 'Models must be subclasses of ve.dm.Model' ); } // Unregister the model from the right factory if ( constructor.prototype instanceof ve.dm.Annotation ) { ve.dm.annotationFactory.unregister( constructor ); } else if ( constructor.prototype instanceof ve.dm.Node ) { ve.dm.nodeFactory.unregister( constructor ); } else { throw new Error( 'No factory associated with this ve.dm.Model subclass' ); } // Parent method ve.dm.ModelRegistry.super.prototype.unregister.call( this, name ); const tags = constructor.static.matchTagNames === null ? [ '' ] : constructor.static.matchTagNames; const types = constructor.static.getMatchRdfaTypes() === null ? [ '' ] : constructor.static.getMatchRdfaTypes(); for ( let i = 0; i < tags.length; i++ ) { // +!!foo is a shorter equivalent of Number( Boolean( foo ) ) or foo ? 1 : 0 removeType( this.modelsByTag, +!!constructor.static.matchFunction, tags[ i ], name ); } for ( let i = 0; i < types.length; i++ ) { if ( types[ i ] instanceof RegExp ) { // TODO: Guard against running this again during subsequent // iterations of the for loop removeType( this.modelsWithTypeRegExps, +!!constructor.static.matchFunction, name ); } else { for ( let j = 0; j < tags.length; j++ ) { removeType( this.modelsByTypeAndTag, +!!constructor.static.matchFunction, types[ i ], tags[ j ], name ); } } } delete this.registrationOrder[ name ]; }; /** * Determine which model best matches the given node * * Model matching works as follows: * * Get all models whose tag and rdfaType rules match * * Rank them in order of specificity: * * - tag, rdfaType and func specified * - rdfaType and func specified * - tag and func specified * - func specified * - tag and rdfaType specified * - rdfaType specified * - tag specified * - nothing specified * * If there are multiple candidates with the same specificity, exact matches of strings take precedence over * matches of regular expressions. If there are still multiple candidates, they are ranked in reverse * order of registration (i.e. if A was registered before B, B will rank above A). * The highest-ranking model whose test function does not return false, wins. * * @param {Node} node Node to match (usually an HTMLElement but can also be a Comment node) * @param {boolean} [forceAboutGrouping] If true, only match models with about grouping enabled * @param {string[]} [excludeTypes] Model names to exclude when matching * @return {string|null} Model type, or null if none found */ ve.dm.ModelRegistry.prototype.matchElement = function ( node, forceAboutGrouping, excludeTypes ) { const nodeName = node.nodeName.toLowerCase(); const types = []; const byRegistrationOrderDesc = ( a, b ) => this.registrationOrder[ b ] - this.registrationOrder[ a ]; const matchTypeRegExps = ( type, tag, withFunc ) => { const matchedModels = [], models = this.modelsWithTypeRegExps[ +withFunc ]; for ( let j = 0; j < models.length; j++ ) { if ( excludeTypes && excludeTypes.indexOf( models[ j ] ) !== -1 ) { continue; } const matchTypes = this.registry[ models[ j ] ].static.getMatchRdfaTypes(); for ( let k = 0; k < matchTypes.length; k++ ) { if ( matchTypes[ k ] instanceof RegExp && matchTypes[ k ].test( type ) && ( ( tag === '' && this.registry[ models[ j ] ].static.matchTagNames === null ) || ( this.registry[ models[ j ] ].static.matchTagNames || [] ).indexOf( tag ) !== -1 ) ) { matchedModels.push( models[ j ] ); } } } return matchedModels; }; const allTypesAllowed = ( model ) => { let allowedTypes = model.static.getAllowedRdfaTypes(); const matchTypes = model.static.getMatchRdfaTypes(); // All types allowed if ( allowedTypes === null ) { return true; } if ( matchTypes !== null ) { // Don't modify allowedTypes as it is a pointer to the orignal array allowedTypes = allowedTypes.concat( matchTypes ); } function checkType( rule, type ) { return rule instanceof RegExp ? rule.test( type ) : rule === type; } for ( let j = 0; j < types.length; j++ ) { let typeAllowed = false; for ( let k = 0; k < allowedTypes.length; k++ ) { if ( checkType( allowedTypes[ k ], types[ j ] ) ) { typeAllowed = true; break; } } if ( !typeAllowed ) { return false; } } return true; }; const matchWithFunc = ( tag ) => { let queue = [], queue2 = []; for ( let j = 0; j < types.length; j++ ) { // Queue string matches and regexp matches separately ve.batchPush( queue, ve.getProp( this.modelsByTypeAndTag, 1, types[ j ], tag ) || [] ); if ( excludeTypes ) { queue = OO.simpleArrayDifference( queue, excludeTypes ); } ve.batchPush( queue2, matchTypeRegExps( types[ j ], tag, true ) ); } // Filter out matches which contain types which aren't allowed queue = queue.filter( ( name ) => allTypesAllowed( this.lookup( name ) ) ); queue2 = queue2.filter( ( name ) => allTypesAllowed( this.lookup( name ) ) ); if ( forceAboutGrouping ) { // Filter out matches that don't support about grouping queue = queue.filter( ( name ) => this.registry[ name ].static.enableAboutGrouping ); queue2 = queue2.filter( ( name ) => this.registry[ name ].static.enableAboutGrouping ); } // Try string matches first, then regexp matches queue.sort( byRegistrationOrderDesc ); queue2.sort( byRegistrationOrderDesc ); ve.batchPush( queue, queue2 ); for ( let j = 0; j < queue.length; j++ ) { if ( this.registry[ queue[ j ] ].static.matchFunction( node ) ) { return queue[ j ]; } } return null; }; const matchWithoutFunc = ( tag ) => { let queue = [], queue2 = [], winningName = null; for ( let j = 0; j < types.length; j++ ) { // Queue string and regexp matches separately ve.batchPush( queue, ve.getProp( this.modelsByTypeAndTag, 0, types[ j ], tag ) || [] ); if ( excludeTypes ) { queue = OO.simpleArrayDifference( queue, excludeTypes ); } ve.batchPush( queue2, matchTypeRegExps( types[ j ], tag, false ) ); } // Filter out matches which contain types which aren't allowed queue = queue.filter( ( name ) => allTypesAllowed( this.lookup( name ) ) ); queue2 = queue2.filter( ( name ) => allTypesAllowed( this.lookup( name ) ) ); if ( forceAboutGrouping ) { // Filter out matches that don't support about grouping queue = queue.filter( ( name ) => this.registry[ name ].static.enableAboutGrouping ); queue2 = queue2.filter( ( name ) => this.registry[ name ].static.enableAboutGrouping ); } // Only try regexp matches if there are no string matches queue = queue.length > 0 ? queue : queue2; // Find most recently registered for ( let j = 0; j < queue.length; j++ ) { if ( winningName === null || this.registrationOrder[ winningName ] < this.registrationOrder[ queue[ j ] ] ) { winningName = queue[ j ]; } } return winningName; }; if ( node.getAttribute ) { if ( node.getAttribute( 'rel' ) ) { types.push( ...node.getAttribute( 'rel' ).trim().split( /\s+/ ) ); } if ( node.getAttribute( 'typeof' ) ) { types.push( ...node.getAttribute( 'typeof' ).trim().split( /\s+/ ) ); } if ( node.getAttribute( 'property' ) ) { types.push( ...node.getAttribute( 'property' ).trim().split( /\s+/ ) ); } } let winner; if ( types.length ) { // func+tag+type match winner = matchWithFunc( nodeName ); if ( winner !== null ) { return winner; } // func+type match // Only look at rules with no tag specified; if a rule does specify a tag, we've // either already processed it above, or the tag doesn't match winner = matchWithFunc( '' ); if ( winner !== null ) { return winner; } } // func+tag match let matches = ve.getProp( this.modelsByTag, 1, nodeName ) || []; // No need to sort because individual arrays in modelsByTag are already sorted // correctly for ( let i = 0; i < matches.length; i++ ) { const m = this.registry[ matches[ i ] ]; // Only process this one if it doesn't specify types // If it does specify types, then we've either already processed it in the // func+tag+type step above, or its type rule doesn't match if ( m.static.getMatchRdfaTypes() === null && m.static.matchFunction( node ) && allTypesAllowed( m ) ) { return matches[ i ]; } } // func only // We only need to get the [''][''] array because the other arrays were either // already processed during the steps above, or have a type or tag rule that doesn't // match this node. // No need to sort because individual arrays in modelsByTypeAndTag are already sorted // correctly matches = ve.getProp( this.modelsByTypeAndTag, 1, '', '' ) || []; for ( let i = 0; i < matches.length; i++ ) { const m = this.registry[ matches[ i ] ]; if ( m.static.matchFunction( node ) && allTypesAllowed( m ) ) { return matches[ i ]; } } // tag+type winner = matchWithoutFunc( nodeName ); if ( winner !== null ) { return winner; } // type only // Only look at rules with no tag specified; if a rule does specify a tag, we've // either already processed it above, or the tag doesn't match winner = matchWithoutFunc( '' ); if ( winner !== null ) { return winner; } // tag only matches = ve.getProp( this.modelsByTag, 0, nodeName ) || []; // No need to track winningName because the individual arrays in modelsByTag are // already sorted correctly for ( let i = 0; i < matches.length; i++ ) { const m = this.registry[ matches[ i ] ]; // Only process this one if it doesn't specify types // If it does specify types, then we've either already processed it in the // tag+type step above, or its type rule doesn't match if ( m.static.getMatchRdfaTypes() === null && allTypesAllowed( m ) ) { return matches[ i ]; } } // Rules with no type or tag specified // These are the only rules that can still qualify at this point, the others we've either // already processed or have a type or tag rule that disqualifies them matches = ve.getProp( this.modelsByTypeAndTag, 0, '', '' ) || []; for ( let i = 0; i < matches.length; i++ ) { const m = this.registry[ matches[ i ] ]; if ( allTypesAllowed( m ) ) { return matches[ i ]; } } // We didn't find anything, give up return null; }; /** * Tests whether a node will be modelled as an annotation * * @param {Node} node The node * @return {boolean} Whether the element will be modelled as an annotation */ ve.dm.ModelRegistry.prototype.isAnnotation = function ( node ) { const modelClass = this.lookup( this.matchElement( node ) ); return ( modelClass && modelClass.prototype ) instanceof ve.dm.Annotation; }; /* Initialization */ ve.dm.modelRegistry = new ve.dm.ModelRegistry(); }() );
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка