Järjestelmäviesti:Gadget-Muokkauslinkit.js

Huomautus: Selaimen välimuisti pitää tyhjentää asetusten tallentamisen jälkeen, jotta muutokset tulisivat voimaan.

  • Firefox ja Safari: Napsauta Shift-näppäin pohjassa Päivitä, tai paina Ctrl-F5 tai Ctrl-R (⌘-R Macilla)
  • Google Chrome: Paina Ctrl-Shift-R (⌘-Shift-R Macilla)
  • Internet Explorer ja Edge: Napsauta Ctrl-näppäin pohjassa Päivitä tai paina Ctrl-F5
  • Opera: Paina Ctrl-F5.
(function(w){

    var OHJEURL = "Ohje:Gadget-Muokkauslinkit";

    var $textbox, $nayta_lnk, ohje_lnk, $linkki_lnk;

    /** 
     * Palauttaa taulukon, jossa on tekstin txt kaikki mallinekutsut. Taulukko on muotoa 
     * [a, l, t], jossa 
     *   a = alkuindeksi
     *   l = loppuindeksi
     *   t = {- ja }-merkkien määrä kutsussa. Mallineilla 2, parametreilla 3, mutta voi olla
     * myös suurempi arvo, jos kutuja on monta sisäkkäin.
     */
    function hae_mallinekutsut(txt) {
        /**
         * Usean {- tai }-merkin ryppäät. Rypäs on yhteinäinen jono {-, }-, [- tai ]-merkkejä.
         * Muotoa [a, l, t, p], jossa
         *   a = alkuindeksi
         *   l = loppuindeksi
         *   t = tyyppi ('{' tai '}')
         */
        var ryppaat = [];
        var result;
        var alku = 0;

        /*
         * Etsitään ryppäät tekstistä. Ohitetan yksittäiset {- ja }-merkit.
         */ 
        var pat = /(\{\{+|\}\}+|\[\[|\]\])/;
        while ( (result = pat.exec(txt.substring(alku))) !== null ) {
            var a = result.index;
            var l = a + result[0].length;
            ryppaat.push([alku+a, alku+l, result[0][0]]);
            alku += l;
        }

        /**
         * Luettelo löydetyistä mallinekutsuista.
         * Alkiot muotoa [a, l, t], jossa
         *   a = alkuindeksi (txt.substring(a, l) on esim. "{{malline|ja|sen|parametrit}}")
         *   l = loppuindeksi
         *   t = 2, 3, 4, jne. eli '{'- ja '}'-merkkien määrä 
         *     2 = malline
         *     3 = parametri
         *     muut numerot tarkoittavat että mallineita tai parametreja oli pinossa useita
         * eikä niitä välttämättä voi erottaa. Esim. 6 ( {{{{{{Repe}}}}}} ) voi olla 3 + 3 
         * tai 2 + 2 + 2.
         **/
        var mkutsut = [];

        /**
         * Ohitetut ryppäät. Vastaan tulevat '{'-merkkiset ryppäät siirretään pinoon, josta
         * niitä vähennetään vastaan tulevilla '}'-ryppäillä.
         **/
        var pino = [];

        var i = 0;

        var hataseis = 100;
        /*
         * Otetaan jonosta ryväs, jos se on {-merkkinen, siirretään pinoon. Jos }-merkkinen
         * vähennetään pinossa olevista {-merkeistä. 
         */

        ryppaat.first = function (v) {
            if ( v !== undefined ) {
                ryppaat[0] = v;
            }
            return ryppaat[0];
        };

        pino.top = function (v) {
            if ( v !== undefined ) {
                pino[pino.length-1] = v;
            }
            return pino[pino.length-1];
        };

        /**
         * Kutsutaan kun mallineen, parametrin tai linkin alku- ja loppukohta saadaan selville.
         * Parametri v on muotoa [a, l, p, t], jossa
         *   a = alkukohta
         *   l = loppukohta
         *   p = tyypin pituus (mallineilla 2, linkeillä 2, parametreilla 3), voi olla myös 
         *       suurempi kuin 3, jos päällekkäin on useita mallineita tai parametreja.
         *   t = tyyppi ('[' tai '{')
         *   Mallineella siis t = '{' ja p = 3; parametrilla t = '{' ja p = 2; wikilinkillä 
         *   t = '[' ja p = 2.
         */
        function tallenna(v) {
            mkutsut.push(v);
        }
        
        while ( ryppaat.first() !== undefined ) {
            if ( hataseis-- < 0 ) break;

            var k = ryppaat.first();
            ks = k[0];
            ke = k[1];
            km = k[2];
            var kl = ke - ks;

            if ( km == '{' || km == '[' ) {
                pino.push(ryppaat.shift());

            } else { /* km == '}' || km == ']' */
                if ( pino.top() === undefined ) { break; }
                var t = pino.top();
                var ts = t[0];
                var te = t[1];
                var tm = t[2];
                var tl = te - ts;

                if ( tm == "[" && km == "}" ) {
                    ryppaat.shift();                     // ohitetaan pariton '}'
                } else if ( tm == "{" && km == "]" ) {
                    pino.pop();                          // ohitetaan pariton '{'
                } else {                                 // joko {}- tai []-parit
                    if ( kl == tl ) {
                        tallenna([ts, ke, tl, tm]);
                        pino.pop();
                        ryppaat.shift();
                    } else if ( kl < tl ) {
                        tallenna([te - kl, ke, kl, tm]);
                        te = te - kl;
                        pino.top([ts, te, tm]);
                        ryppaat.shift();
                        if ( te - ts == 1 ) {            // ohitetaan yksittäiset jäljelle jääneet
                            pino.pop(); 
                        }
                    } else if ( tl < kl ) {
                        tallenna([ts, ks + tl, tl, tm]);
                        ks += tl; 
                        ryppaat.first([ks, ke, km]);
                        pino.pop();
                        if ( ke - ks == 1 ) {            // ohitetaan yksittäiset jäljelle jääneet
                            ryppaat.shift();
                        }
                    }
                }
            }
        }

        return mkutsut;
    }

    function hae_malline(txt, pos) {
        var mkutsut = hae_mallinekutsut(txt);
        var mkutsu = null;
        var i;

        /* Mallinekutsut on järjestyksessä sisin ennen ulompaa, joten ensimmäinen johon kursori 
           sopii on tarkin. */
        for ( i in mkutsut ) {
            if ( pos[0] > mkutsut[i][0] && pos[1] < mkutsut[i][1] ) {
                mkutsu = mkutsut[i];
                break;
            }
        }
        if ( mkutsu === null ) { return null; }


        var a = mkutsu[0];
        var l = mkutsu[1];
        var p = mkutsu[2];
        var t = mkutsu[3];
        var loyto = txt.substring(a, l);

        // Poistetaan {- ja }-merkit
        var re = new RegExp("^.{" + p + "}([\\s\\S]*?).{" + p + "}$");
        loyto = loyto.replace(re, "$1");
        loyto = loyto.replace(new RegExp("^subst" + ":"), "");

        // Tutkintaan onko |-merkkiä. (Löytynyt merkki voi kuulua myös sisäkkäiseen mallneeseen)
        var j = loyto.indexOf('|');
        if ( j != -1 ) {
            loyto = loyto.substring(0, j);
        }

        l = loyto.indexOf(":");
        if ( l != -1 && t == '{' ) {
            var pref = loyto.substring(0, l);
            switch ( pref ) {
            case '#invoke':
                t = 'm';
                loyto = loyto.substring(l+1);
                break;
            }
        }
        // Tutkitaan onko nimessä mallineita tai linkkejä
        if ( /(\{{2,}|\}{2,}\[\[|\]\])/.test(loyto) ) {
            return null;
        }
        
        if ( t == '{' && p == 2 ) {
            return "Malline:" + loyto;
        } else if ( t == '[' && p == 2 ) {
            return loyto;
        } else if ( t == 'm' ) {
            return "Moduuli:" + loyto;
        }

        return null;
    }

    function nayta_linkki(teksti, kohde, title) {
        $nayta_lnk.hide();
        $linkki_lnk.attr('href', kohde);
        $linkki_lnk.attr('title', title);
        $linkki_lnk.html(teksti);
        $linkki_lnk.show();
        $linkki_lnk.focus();
    }

    function run($) {
        var $sailio = $('<span/>');
        var $ohje_lnk = $('<a>?</a>');
        $textbox = $('#wpTextbox1');

        if ( $("#tyokalupakki").length == 0 ) {
            $textbox.before('<div id="tyokalupakki" />');
        }
        $("#tyokalupakki").append([ '<span class="tyokaluerotin" style="color: gray; ">'
                                    + ' | </span>', $sailio ]);

        $ohje_lnk.attr("href", mw.config.get("wgServer") 
                       + mw.config.get("wgArticlePath").replace("$1", OHJEURL));

        $nayta_lnk = $('<a href="#">Näytä linkki</a>');
        $nayta_lnk.attr("title", 
                        "Avaa kursorin alla oleva linkki tai näytä mallineen ohjesivu [ctrl+alt+m]");
        $nayta_lnk.css("font-size", "90%");

        $linkki_lnk = $('<a href="#" target="_blank" />');
        $linkki_lnk.hide();

        var $ohje_span = $('<span class="ohjenappi"/>');
        $ohje_span.html([ "[", $ohje_lnk, "]" ]);

        $sailio.append([ " [", $nayta_lnk, $linkki_lnk, "] ", " ", $ohje_span ]);

        $nayta_lnk.click(function () {
            var txt = $('#wpTextbox1').val();
            var pos = $('#wpTextbox1').textSelection('getCaretPosition', 
                                                     { 'startAndEnd' : true });
            if ( pos ) {
                var linkki = hae_malline(txt, pos);
                if ( linkki ) {
                    nayta_linkki(linkki, mw.config.get("wgServer")
                                 + mw.config.get("wgArticlePath").replace("$1", linkki), 
                                 'Avaa sivu ' + linkki + '');
                } else {
                    nayta_linkki("ei linkkiä", null, 'Linkkiä ei pystytty lukemaan');
                }
            }
            return false;
        });

        $textbox.on('focus', function () {
            $linkki_lnk.hide();
            $nayta_lnk.show();
        });

        $linkki_lnk.keyup(function(event) { 
            if ( event.keyCode == 27 ) /* ESC */ {
                $textbox.focus();
            }
        });

        $(document).keyup(function(event){
            if ( event.ctrlKey && event.altKey && event.keyCode == 77 ) { // 'm'
                $nayta_lnk.click();
            }
        });


    }
    if ( mw.config.get("wgAction") == "edit" || 
    	mw.config.get("wgAction") == "submit" ) {
        jQuery(document).ready(run);
    }

})(window);