MediaWiki:Common.js: различия между версиями

Материал из melioration.space
 
(не показаны 74 промежуточные версии этого же участника)
Строка 1: Строка 1:
/**
+
mw.hook( 've.activationComplete' ).add( function() {
* written by [[User:ערן]] basesd on [[de:MediaWiki:Gadget-Rechtschreibpruefung.js]]
+
if(typeof MathJax !== typeof undefined) { MathJax.typesetPromise(); }
**/
+
} );
function spellChecker() {
+
 
    'use strict'
+
mw.loader.using( [ 'ext.visualEditor.core', 'ext.visualEditor.mwtransclusion' ] ).then(function () {
+
 
    /*== CONFIGURATION ==*/
+
// --------- (start of ve.ui.CenterAction definition) -----------------------------------------------
    var wbSpellCheck = 'Q15098221'; // wikidata item of list of words
+
// This is based on [lib/ve/src/ui/actions/ve.ui.BlockquoteAction.js] from Extension:VisualEditor.
    var ignorePages = [];
+
 
    // language variants: the script looks for the keys of the dictionary below and if it finds them in article code it loads the specific variant instead of default
+
ve.ui.CenterAction = function VeUiCenterAction() {
    var langVariants = { }
+
ve.ui.CenterAction.super.apply( this, arguments );
    var errors = {
+
};
        installError: '<div>Please create a dictionary for spelling mistakes and link it to <a href="//www.wikidata.org/wiki/{0}>{0}</a> in Wikidata</div>',
+
OO.inheritClass( ve.ui.CenterAction, ve.ui.Action );
        spellListNotFound: 'Page not found: <a href="{0}">{1}</a>'
+
 
    }
+
ve.ui.CenterAction.static.name = 'center';
    /*== END OF CONFIGURATION ==*/
+
ve.ui.CenterAction.static.methods = [ 'wrap', 'unwrap', 'toggle' ];
+
 
    var mispellsList = localStorage.mispellsList || $.cookie( 'mispellsList' );
+
ve.ui.CenterAction.prototype.isWrapped = function () {
    var dictionary = {
+
var fragment = this.surface.getModel().getFragment();
        misspells: {},
+
return fragment.hasMatchingAncestor( 'center' );
        keys: []
+
};
    }
+
ve.ui.CenterAction.prototype.toggle = function () {
+
return this[ this.isWrapped() ? 'unwrap' : 'wrap' ]();
    /*
+
};
    Setups misspelling gadget - get the site-specific name of page with dictionary. returns $.Deferred
+
ve.ui.CenterAction.prototype.wrap = function () {
    */
+
var
    function setup() {
+
surfaceModel = this.surface.getModel(),
        var misspellInstall = new $.Deferred();
+
selection = surfaceModel.getSelection(),
        if ( mispellsList ) {
+
fragment = surfaceModel.getFragment( null, true ),
          misspellInstall.resolve();
+
leaves, leavesRange;
        } else {
+
 
            mw.loader.using(['wikibase.api.RepoApi', 'wikibase.client.getMwApiForRepo'], function(){
+
if ( !( selection instanceof ve.dm.LinearSelection ) ) {
                var repoApi = new wikibase.api.RepoApi(wikibase.client.getMwApiForRepo());
+
return false;
                repoApi.getEntities( wbSpellCheck, 'sitelinks').done( function( data ) {
+
}
                    var currSite = mw.config.get( 'wgDBname' );
+
 
                    if ( data.entities && data.entities.hasOwnProperty( wbSpellCheck ) && data.entities[wbSpellCheck].sitelinks && data.entities[wbSpellCheck].sitelinks.hasOwnProperty( currSite ) ) {
+
leaves = fragment.getSelectedLeafNodes();
                        mispellsList = data.entities[wbSpellCheck].sitelinks[currSite].title;
+
leavesRange = new ve.Range(
                        try {
+
leaves[ 0 ].getRange().start,
                            localStorage.mispellsList = mispellsList;
+
leaves[ leaves.length - 1 ].getRange().end
                        } catch(e) {
+
);
                            $.cookie( 'mispellsList', mispellsList );
+
fragment = surfaceModel.getLinearFragment( leavesRange, true );
                        }
+
 
                        misspellInstall.resolve();
+
fragment = fragment.expandLinearSelection( 'siblings' );
                    } else {
+
 
                        mw.notify( $( errors.installError.replace('{0}', wbSpellCheck) ) );
+
while (
                        misspellInstall.reject();
+
fragment.getCoveredNodes().some( function ( nodeInfo ) {
                    }
+
return !nodeInfo.node.isAllowedParentNodeType( 'center' ) || nodeInfo.node.isContent();
                } );
+
} )
            } );
+
) {
        }
+
fragment = fragment.expandLinearSelection( 'parent' );
        return misspellInstall;
+
}
    }
+
 
+
// Wrap everything in a <center> tag
    function runSpellCheck() {
+
fragment.wrapAllNodes( { type: 'center' } );
        if ( mw.config.get( 'wgPageName' ).replace('_', ' ') == mispellsList || $.inArray( mw.config.get( 'wgPageName' ).replace(/_/g, ' '), ignorePages) != -1 ) return;
+
 
        if ( dictionary.keys.length>0 ) {
+
return true;
            checkSpells( $( '.ve-ce-surface, #mw-content-text:visible' ) );
+
};
            return;
+
ve.ui.CenterAction.prototype.unwrap = function () {
        }
+
var
        var contextHTML = $( '.ve-ce-surface, #mw-content-text:visible' ).html();
+
surfaceModel = this.surface.getModel(),
        // load language variant dictionary instead of default dictionary
+
selection = surfaceModel.getSelection(),
        for (var variant in langVariants) {
+
fragment = surfaceModel.getFragment( null, true ),
            if (contextHTML.indexOf(variant) !== -1) {
+
leaves, leavesRange;
                mispellsList += '/' + langVariants[variant];
+
 
                break;
+
if ( !( selection instanceof ve.dm.LinearSelection ) ) {
            }
+
return false;
        }
+
}
        $.ajax({
+
 
            url: mw.config.get('wgServer') + mw.util.wikiScript('index') + '?title=' + mw.util.wikiUrlencode( mispellsList ) + '&action=raw&ctype=text/x-wiki',
+
if ( !this.isWrapped() ) {
            dataType: 'html'
+
return false;
        }).done( function( dictionaryPage ) {
+
}
    //remove intro and headers
+
 
    dictionaryPage = dictionaryPage.substr( dictionaryPage.indexOf('==') ).replace( /==.*==/g,'' )
+
leaves = fragment.getSelectedLeafNodes();
    parseDictionary( dictionaryPage );
+
leavesRange = new ve.Range(
            checkSpells( $( '.ve-ce-surface, #mw-content-text:visible' ) );
+
leaves[ 0 ].getRange().start,
    } );
+
leaves[ leaves.length - 1 ].getRange().end
    }
+
);
+
fragment = surfaceModel.getLinearFragment( leavesRange, true );
    function uniqueArr( listWords ) {
+
 
    var dictWords = {};
+
fragment
    var res = [];
+
// Expand to cover entire <center> tag
    for ( var i=0; i<listWords.length; i++ ) {
+
.expandLinearSelection( 'closest', ve.dm.CenterNode )
    dictWords[listWords[i]] = 1;
+
// Unwrap it
    }
+
.unwrapNodes( 0, 1 );
    for ( var k in dictWords ) {
+
 
    res.push( k );
+
return true;
    }
+
};
    return res;
+
ve.ui.actionFactory.register( ve.ui.CenterAction );
    }
+
 
+
// --------- (end of ve.ui.CenterAction definition) -------------------------------------------------
    /*
+
 
    Extract unique words from context. Removes words in citations.
+
ve.ui.CenterFormatTool = function VeUiCenterFormatTool() {
    */
+
ve.ui.CenterFormatTool.super.apply( this, arguments );
    function extractPageWords( context ) {
+
};
    var pageWords = {};//unique words in article
+
OO.inheritClass( ve.ui.CenterFormatTool, ve.ui.FormatTool );
    var wordList = [];
+
 
    // remove citations and all "sic" + one word before
+
ve.ui.CenterFormatTool.static.name = 'center';
    var splittedWords = context.text().replace(/\s[^\s]*[ \-]sic[ \-\!]/,' ').replace(/„.*?“/g,'').split(/\s/); //remove citations
+
ve.ui.CenterFormatTool.static.group = 'format';
    for (var i=0;i<splittedWords.length;i++){
+
ve.ui.CenterFormatTool.static.title = 'По центру';
    if ( splittedWords[i].length && !( /^[0-9]+$/.test( splittedWords[i] ) ) ) {
+
ve.ui.CenterFormatTool.static.format = { type: 'center' };
    var trimed = splittedWords[i].replace( /[\[\],\.\(\)]/g, '' ).toLowerCase();
+
ve.ui.CenterFormatTool.static.commandName = 'center';
    pageWords[trimed] = 1;
+
ve.ui.toolFactory.register( ve.ui.CenterFormatTool );
    }
+
 
    }
+
ve.ui.commandRegistry.register(
    for ( var word in pageWords ) {
+
new ve.ui.Command(
    wordList.push(word);
+
'center', 'center', 'toggle',
    }
+
{ supportedSelections: [ 'linear' ] }
    return wordList;
+
)
    }
+
);
+
} );
    function parseDictionary( dict ){
 
    //to dictioanry!
 
    var correcto = dict.split('\n');
 
    var keyWords = [];
 
 
    for ( var i=0; i<correcto.length; i++ ){
 
    var entry = correcto[i];
 
    if ( entry.length === 0 || (entry=entry.trim()).length === 0 ){
 
    continue;//skip empty lines
 
    }
 
    var fixTriple = entry.split( '|' );
 
    if ( fixTriple.length !==3 ){
 
    console.log('Bad entry:' +entry);
 
    continue;
 
    }
 
 
            //skip on words appear in title
 
            if (!(new RegExp( '(^|\\s)' + fixTriple[0] + '(?:$|\\s)','i').test(mw.config.get('wgTitle')))){
 
                dictionary.misspells[fixTriple[0].toLowerCase()] = {
 
                    hint: fixTriple[2],
 
                    cs: fixTriple[1] == 'cs', //case sensetive
 
                    word: fixTriple[0]
 
                }
 
        keyWords.push( fixTriple[0].toLowerCase() );
 
            }  
 
    }
 
        dictionary.keys = uniqueArr( keyWords );
 
    }
 
 
    function checkSpells( context ) {
 
    //extract article words for efficent search
 
    var artWords = extractPageWords( context );
 
 
    var words = dictionary.keys.concat( artWords );
 
    words.sort();
 
 
    var relevantWords = {};
 
    for (var i = 1; i<words.length; i++){
 
    if ( words[i] == words[i-1] ) {
 
    relevantWords[words[i]] = 1;
 
    }
 
    }
 
 
    for (var k in relevantWords) {
 
            // since \b isn't supported in unicode we use heuristic instead which should catch 99% of the cases :)
 
            markWordStart( context, new RegExp( '(^|[\\s\\(\\[-])(' + dictionary.misspells[k].word + ')(?=$|[-\\?\\!\\s\\.:,;\\)\\]])', dictionary.misspells[k].cs? '' : 'i' ), dictionary.misspells[k].hint );
 
    }
 
    }
 
 
    function markWordStart(context, text, hint)
 
    {
 
      var markedElement = context.get(0);
 
      if ( markedElement ){
 
        markWord( markedElement, text, hint);
 
      }
 
    }
 
 
    function markWord(node, text, hint)
 
    {
 
      var pos, len, newnodes = 0;
 
      var newnode, middlenode, endnode;
 
      var textmatch;
 
      // textnode - search for word
 
      if (node.nodeType == 3)
 
      {
 
        pos = node.data.search(text);
 
        if (pos >= 0 && text.test(node.data.replace(/[].*?[“]/g,'')))
 
        {
 
          textmatch = node.data.match( text );
 
          pos += textmatch[1].length; // skip prefix
 
          // create new span-element
 
          newnode = document.createElement("span");
 
          newnode.style.backgroundColor = "#FF9191";
 
          newnode.title = hint;
 
          newnode.className = 'spellError';
 
          // get length of the matching part
 
          len = textmatch[2].length;
 
          // splits content in three parts: begin, middle and end
 
          middlenode = node.splitText(pos);
 
          endnode = middlenode.splitText(len);
 
 
          // appends a copy of the middle to the new span-node
 
          newnode.appendChild(middlenode.cloneNode(true));
 
          // replace middlenode with the new span-node
 
          middlenode.parentNode.replaceChild(newnode, middlenode);
 
          newnodes = 1;
 
        }
 
      }
 
      else if ((node.nodeType == 1)  // element node
 
      && (node.hasChildNodes()) // with child nodes
 
      && !(/blockquote|^q$|cite|script|style|form/i.test(node.tagName))
 
  && !(/mw-userlink|mw-usertoollinks|mw-changeslist-(date|separator)/.test(node.className))) // no script, style and form and citations or mw classes
 
      {
 
        var this_child;
 
        for (this_child = 0; this_child < node.childNodes.length; this_child++)
 
        {
 
          this_child = this_child + markWord(node.childNodes[this_child], text, hint);
 
        }
 
      }
 
      return newnodes;
 
    }
 
 
    setup().then( runSpellCheck );
 
 
    mw.hook( 've.activationComplete' ).add( function() {
 
        setup().then( function(){
 
            // inital find misspells (for all document)
 
            runSpellCheck();
 
            var view =ve.init.target.getSurface().getView();
 
            var doc = view.getDocument();
 
            var model = ve.init.target.getSurface().getModel();
 
            //while editing - only on current node
 
            model.on( 'documentUpdate', function () {
 
                try
 
                {
 
                    var selection = model.getSelection().getRange(),
 
                    node = selection && doc.getBranchNodeFromOffset( selection.start ),
 
                    originalSelection;
 
                    if ( !( node instanceof ve.ce.ContentBranchNode ) ) {
 
                    return;
 
                    }
 
                    //remove spell errors from current node
 
                    $( node.$element[0] ).find('.spellError').contents().unwrap();
 
//view.surfaceObserver.disable();
 
                    checkSpells( $( node.$element[0] ) );
 
                    //reset selection
 
                    selection = model.getSelection().getRange();
 
                    originalSelection = view.getSelectionState( new ve.Range(selection.to, selection.to) );
 
 
setTimeout( function () {
 
view.showSelectionState( originalSelection );
 
} );
 
                } catch(err){
 
                    console.log('Error in Gadget-Rechtschreibpruefung.js:documentUpdate');
 
                    console.log(err);
 
                }
 
            } );
 
    } );
 
    });
 
}
 
 
$(function(){
 
    //run only on active tabs
 
    if ( typeof document.hidden === "undefined" || !document.hidden) spellChecker();
 
    else $(document).one('visibilitychange', spellChecker);
 
});
 

Текущая версия на 16:38, 27 марта 2021

mw.hook( 've.activationComplete' ).add( function() {
	if(typeof MathJax !== typeof undefined) { MathJax.typesetPromise(); }
} );

mw.loader.using( [ 'ext.visualEditor.core', 'ext.visualEditor.mwtransclusion' ] ).then(function () {

// --------- (start of ve.ui.CenterAction definition) -----------------------------------------------
// This is based on [lib/ve/src/ui/actions/ve.ui.BlockquoteAction.js] from Extension:VisualEditor.

	ve.ui.CenterAction = function VeUiCenterAction() {
		ve.ui.CenterAction.super.apply( this, arguments );
	};
	OO.inheritClass( ve.ui.CenterAction, ve.ui.Action );

	ve.ui.CenterAction.static.name = 'center';
	ve.ui.CenterAction.static.methods = [ 'wrap', 'unwrap', 'toggle' ];

	ve.ui.CenterAction.prototype.isWrapped = function () {
		var fragment = this.surface.getModel().getFragment();
		return fragment.hasMatchingAncestor( 'center' );
	};
	ve.ui.CenterAction.prototype.toggle = function () {
		return this[ this.isWrapped() ? 'unwrap' : 'wrap' ]();
	};
	ve.ui.CenterAction.prototype.wrap = function () {
		var
			surfaceModel = this.surface.getModel(),
			selection = surfaceModel.getSelection(),
			fragment = surfaceModel.getFragment( null, true ),
			leaves, leavesRange;

		if ( !( selection instanceof ve.dm.LinearSelection ) ) {
			return false;
		}

		leaves = fragment.getSelectedLeafNodes();
		leavesRange = new ve.Range(
			leaves[ 0 ].getRange().start,
			leaves[ leaves.length - 1 ].getRange().end
		);
		fragment = surfaceModel.getLinearFragment( leavesRange, true );

		fragment = fragment.expandLinearSelection( 'siblings' );

		while (
			fragment.getCoveredNodes().some( function ( nodeInfo ) {
				return !nodeInfo.node.isAllowedParentNodeType( 'center' ) || nodeInfo.node.isContent();
			} )
		) {
			fragment = fragment.expandLinearSelection( 'parent' );
		}

		// Wrap everything in a <center> tag
		fragment.wrapAllNodes( { type: 'center' } );

		return true;
	};
	ve.ui.CenterAction.prototype.unwrap = function () {
		var
			surfaceModel = this.surface.getModel(),
			selection = surfaceModel.getSelection(),
			fragment = surfaceModel.getFragment( null, true ),
			leaves, leavesRange;

		if ( !( selection instanceof ve.dm.LinearSelection ) ) {
			return false;
		}

		if ( !this.isWrapped() ) {
			return false;
		}

		leaves = fragment.getSelectedLeafNodes();
		leavesRange = new ve.Range(
			leaves[ 0 ].getRange().start,
			leaves[ leaves.length - 1 ].getRange().end
		);
		fragment = surfaceModel.getLinearFragment( leavesRange, true );

		fragment
			// Expand to cover entire <center> tag
			.expandLinearSelection( 'closest', ve.dm.CenterNode )
			// Unwrap it
			.unwrapNodes( 0, 1 );

		return true;
	};
	ve.ui.actionFactory.register( ve.ui.CenterAction );

// --------- (end of ve.ui.CenterAction definition) -------------------------------------------------

	ve.ui.CenterFormatTool = function VeUiCenterFormatTool() {
		ve.ui.CenterFormatTool.super.apply( this, arguments );
	};
	OO.inheritClass( ve.ui.CenterFormatTool, ve.ui.FormatTool );

	ve.ui.CenterFormatTool.static.name = 'center';
	ve.ui.CenterFormatTool.static.group = 'format';
	ve.ui.CenterFormatTool.static.title = 'По центру';
	ve.ui.CenterFormatTool.static.format = { type: 'center' };
	ve.ui.CenterFormatTool.static.commandName = 'center';
	ve.ui.toolFactory.register( ve.ui.CenterFormatTool );

	ve.ui.commandRegistry.register(
		new ve.ui.Command(
			'center', 'center', 'toggle',
			{ supportedSelections: [ 'linear' ] }
		)
	);
} );