/**
* Javascript-luokka wikitekstin muokkaamiseen.
*/
function Osio(vanhempi, taso, nimi, tekstiosa) {
if ( tekstiosa ) {
tekstiosa = tekstiosa.trim();
this._tekstiosa = (tekstiosa !== "" ? tekstiosa + "\n" : "");
} else { this._tekstiosa = ""; }
this.osiot = ; // alaosiot
this.vanhempi = vanhempi; // juurisolmulla null
this.taso = taso; // otsikon taso, esim. ==Suomi== -> 2
this.nimi = nimi;
this.teksti = null; // vain juurisolmulla
this.alku = -1;
this.loppu = -1;
this.toal = -1;
/*
* Palauttaa aliosiot joiden otsikko on 'nimi'.
* \return
*/
this.aliosiot = function(nimi) {
var loydot = ;
for ( var i = 0; i < this.osiot.length; i++ ) {
if ( typeof nimi == "undefined" || this.osiot.nimi == nimi ) {
loydot.push(this.osiot);
}
}
return loydot;
};
/*
* Palauttaa kaikki tason 'taso' osiot.
*/
this.kaikki_osiot = function(taso, loydot) {
var _loydot = ;
if ( loydot !== ) { _loydot = loydot; }
for ( var i = 0; i < this.osiot.length; i++ ) {
if ( this.osiot.taso == taso ) {
_loydot.push(this.osiot);
} else if ( this.osiot.taso < taso ) {
this.osiot.kaikki_osiot(taso, _loydot);
}
}
return _loydot;
};
/*
* Luo Osio-olion tekstistä.
*/
this.tee_tekstista = function(vanhempi, alku, loppu, teksti, taso, nimi, toal) {
var os = new Osio(vanhempi, taso, nimi, null);
os.alku = alku;
os.toal = toal;
os.loppu = loppu;
os.teksti = null;
os.indeksoi();
return os;
};
// HUOM. Olettaa, että myös ensimmäisen otsikon edessä on rivinvaihto
this.indeksoi = function() {
var taso = this.taso+1;
var re_s = new RegExp("\n={" + taso + "}+={" + taso + "}\s*\n");
var re_m = new RegExp("^\n={" + taso + "}(+)={" + taso + "}\s*\n");
// Osion koko teksti otsikosta seuraavaan saman tai ylemmän tason otsikkoon tai loppuun.
var oteksti = this.hae_teksti().substring(this.alku, this.loppu);
// aliotsikot muodossa { ota: /otsikon alku (- 1)/ , osa: /tekstiosan alku/,
// nimi: /otsikon teksti/ }
var aliotsikot = ;
// etsitään aliotsikoiden paikat
var a = 0;
var s;
do {
s = a + oteksti.substr(a).search(re_s);
if ( s !== a + -1 ) {
//////console.log("mätsätään: " + oteksti.substr(s));
var m = oteksti.substr(s).match(re_m);
//////console.log("mäts: " + m);
var oa = s;
var ol = s + m.length-1;
aliotsikot.push({ ota: oa, osa: ol, nimi: m });
//////console.log(" +" + oa + ", " + ol + ": " + m);
a = ol - 1;
//////console.log("jäljellä: " + oteksti.substr(a));
}
} while ( s !== a + -1 );
aliotsikot.push({ ota: oteksti.length, osa: oteksti.length, nimi: "" });
var tolo;
if ( aliotsikot.length > 1 ) {
tolo = aliotsikot.ota;
////console.log("on ali");
}
else {
tolo = oteksti.length;
}
////console.log("tolo: " + tolo);
this.tekstiosa(oteksti.substring(this.toal - this.alku, tolo));
// luodaan aliotsikoista aliosioita ja muutetaan suhteelliset positiot absoluuttisiksi
for ( var i = 0; i < aliotsikot.length-1; i++ ) {
var alku = this.alku + aliotsikot.ota;
var toal = this.alku + aliotsikot.osa;
//////console.log("this.alku + aliotsikot.osa: " + (this.hae_teksti().substr(toal)));
var lopp = this.alku + aliotsikot.ota;
var nimi = aliotsikot.nimi;
////console.log("" + this.nimi + ": " + nimi + "(alku: " + alku + ", toal: " + toal + ", loppu: " + lopp + ")");
this.osiot.push(this.tee_tekstista(this, alku, lopp, oteksti, this.taso+1, nimi, toal));
}
};
/*
* lp = lisäyspiste
* ero = lisättyjen (+) tai poistettujen (-) merkkien määrä vanhaan nähden
*/
this.paivita_pos = function(lp, ero) {
if ( this.alku >= lp ) {
this.alku += ero;
}
if ( this.loppu >= lp ) {
this.loppu += ero;
for ( var i = 0; i < this.osiot.length; i++ ) {
this.osiot.paivita_pos(lp, ero);
}
}
};
/*
* Palauttaa sivun koko tekstin.
*/
this.hae_teksti = function() {
////console.log("hae_teksti(): this.nimi: " + this.nimi);
if ( this.vanhempi !== null ) {
return this.vanhempi.hae_teksti();
}
return this.teksti;
};
this.tee_teksti = function() {
var to = this.tekstiosa();
//console.log("tee_teksti(): nimi: " + this.nimi + "; tekstiosio: " + to + "; taso: " + this.taso);
var a = ;
if ( this.taso == 1 ) {
a.push(typeof to !== "undefined" && to !== "" ? to + "" : "");
} else {
a.push("\n" + "=".repeat(this.taso) + this.nimi + "=".repeat(this.taso) + "" + (typeof to !== "undefined" && to !== "" ? "\n" + to : ""));
}
for (var i = 0; i < this.osiot.length; i++ ) {
a.push(this.osiot.tee_teksti());
}
return a.join("");
};
/*
* Korvaa tekstin 'alun' ja 'lopun' välillä tekstillä 'uusi'.
*/
this.muuta_kohta = function(alku, loppu, uusi) {
////console.log("muuta_kohta: " + alku + ", " + loppu + ": " + uusi.substring(0, 10) + "...");
if ( this.vanhempi !== null ) {
this.vanhempi.muuta_kohta(alku, loppu, uusi);
} else {
var ero = uusi.length - (loppu - alku);
this.teksti = this.teksti.substring(0, alku).concat(uusi, this.teksti.substring(loppu));
////console.log("päviiteteään");
this.paivita_pos(alku, ero);
}
};
function tee_osio(ot, to, taso) {
return "\n" + "=".repeat(taso) + ot + "=".repeat(taso) + "\n" + (typeof to !== "undefined" && to !== "" ? to + "\n" : "");
}
/*
* Luo uuden osion, jonka otsikko on 'ot' ja tekstiosa on 'to'. Lsää osion osion 'this'
* perään.
* \param String ot osion otsikko
* \param String to osion tekstiosio
*/
this.lisaa_peraan = function(ot, to) {
var pa = this.vanhempi.osiot;
var uusi = new Osio(this.vanhempi, this.taso, ot, to);
pa.splice(pa.indexOf(this)+1, 0, uusi);
return uusi;
};
/*
* Luo uuden osion, jonka otsikko on 'ot' ja tekstiosa on 'to'. Lisää osion ennen 'thisiä'.
* \param String ot osion otsikko
* \param String to osion tekstiosio
*/
this.lisaa_eteen = function(ot, to) {
var pa = this.vanhempi.osiot;
var uusi = new Osio(this.vanhempi, this.taso, ot, to);
pa.splice(pa.indexOf(this), 0, uusi);
return uusi;
};
/*
* Lisää uuden alioson tämän osion viimeiseksi.
*/
this.lisaa_aliosio = function(ot, to) {
var uusi = new Osio(this.vanhempi, this.taso + 1, ot, to);
this.osiot.push(uusi);
return uusi;
};
/*
* Poistaa tämän Osion osoittaman alueen.
*/
this.poista = function() {
var pa = this.vanhempi.osiot;
pa.splice(pa.indexOf(this), 1);
};
/*
* Jos 'uutta' ei ole annettu:
* palauttaa osion tekstiosan ts. otsikon ja ensimmäisen aliotsikon välisen tekstin.
* muuten:
* asettaa osion tekstiosan.
*/
this.tekstiosa = function(uusi) {
if ( typeof uusi == "undefined" ) {
return this._tekstiosa;
} else {
// Normalisoidaan tyhjät alusta ja lopusta.
uusi = uusi.trim();
this._tekstiosa = (uusi !== "" ? uusi + "\n" : "");
}
return this._tekstiosa;
};
this.osioteksti = function(uusi) {
function hae_osioteksti(self) {
var teksti = self.hae_teksti();
return teksti.substring(self.toal, self.loppu+1);
}
function aseta_osioteksti(self, uusi) {
self.muuta_kohta(self.toal, self.loppu, uusi);
self.indeksoi();
}
if ( uusi === undefined ) {
return hae_osioteksti(this);
} else {
return aseta_osioteksti(this, uusi);
}
};
/*
* Palauttaa tai asettaa koko osion tekstin, mukaan lukien sen otsikon.
* \param String uusi uusi teksti
*/
this.osio = function(uusi) {
function hae_osio(self) {
var teksti = self.hae_teksti();
return teksti.substring(self.alku, self.loppu);
}
function aseta_osio(self, uusi) {
self.muuta_kohta(self.alku, self.loppu, uusi);
self.indeksoi();
}
if ( uusi === undefined ) {
return hae_osio(this);
} else {
return aseta_osio(this, uusi);
}
};
return this;
}
function Wikitext(teksti) {
this.kielilinkit = "";
this.juuri = null;
/*
* Jakaa tekstin 'pageText' kahteen osaan joista jälkimmäinen sisältää kielilinkit ja ensimmäinen
* muun tekstin.
*/
function erota_kielilinkit(self) {
var p = teksti.search(/\n(\+:]+\]\]\s*\n*)+$/);
if ( p !== -1 ) {
// poistetaan mahdolliset luokkalinkit alusta
var up = teksti.substr(p).match(/^\n(\]+\]\]\s*\n*)+/);
if ( up !== null ) { p += up.length; }
}
else {
p = teksti.length;
}
self.kielilinkit = teksti.substring(p);
console.log("loppu: ");
teksti = teksti.substring(0, p);
}
/*
* Tulkkaa tekstin Osio-oliopuuksi.
*/
function indeksoi(teksti) {
var juuri = new Osio(null, 1, "", null);
juuri.alku = 0;
juuri.toal = 0;
juuri.loppu = teksti.length;
juuri.teksti = teksti;
juuri.indeksoi();
////console.log("johdanto: " + juuri._tekstiosa);
return juuri;
}
/*
* Palauttaa osion, jota ennen osio nimeltä 'otsikko' kuuluu.
*/
function hae_osio(osio, otsikko, comp_f) {
var lista = osio.aliosiot();
for (var i = 0; i < lista.length; i++ ) {
if ( comp_f(lista.nimi, otsikko) > 0 ) {
return lista;
}
}
return null;
}
// Muuttaa oliopuun tekstiksi.
this.tee_teksti = function() {
console.log("tee_teksti, kielilinkit: " + this.kielilinkit);
return this.juuri.tee_teksti() + this.kielilinkit;
};
/*
* Lisää uuden käännöslaatikon `suomiosion` alaiseen Käännökset-osioon. Jos Käännökset-osiota ei ole
* luodaan sellainen.
* suomiosio (Osio): osio, johon lisätään täytyy olla Sanaluokkatason Osio-olio
* numero (numero): käännöslaatikkoon tuleva numero
* selite (merkkijono): käännöslaatikkoon tuleva selite
*/
this.lisaa_kaannoslaatikko = function(suomiosio, numero, selite) {
var taulukko = "\n{" + "{kohta|" + numero + "|{{su" + "bst:linkittömänä|" + selite + "}}|\n\n|loppu}}\n";
var osiot = suomiosio.aliosiot("Käännökset");
// Käännökset-osio on
if ( osiot.length > 0 ) {
////console.log("osiot: " + osiot.length);
osiot.tekstiosa(osiot.tekstiosa() + taulukko);
return;
}
// Jos Käännökset-osiota ei ole, lisätään se.
else {
// Käännökset-otsikko tulee Etymologia-, Taivutus- ja Ääntäminen-otsikoiden jälkeen, mutta
// ennen muita 4:n tason otsikoita
osiot = suomiosio.aliosiot("Etymologia");
if ( osiot.length === 0 ) {
osiot = suomiosio.aliosiot("Taivutus");
}
if ( osiot.length === 0 ) {
osiot = suomiosio.aliosiot("Ääntäminen");
}
if ( osiot.length > 0 ) {
osiot.lisaa_peraan("Käännökset", taulukko);
}
else {
osiot = suomiosio.aliosiot();
if ( osiot.length > 0 ) {
osiot.lisaa_eteen("Käännökset", taulukko);
} else {
suomiosio.lisaa_aliosio("Käännökset", taulukko);
}
}
}
};
/*
* TODO monipuolisemmaksi.
*/
this.lisaa_maaritelma = function(osio, rivi) {
function kasittele_maaritelmalista(tekstiosa) {
var vika = tekstiosa.lastIndexOf("\n#");
if ( vika == -1 ) { return null; }
// siirrytään seuraavan rivin alkuun
var kohta = tekstiosa.indexOf("\n", vika + 1) + 1;
// lisätään viimeisen määritelmän perään
tekstiosa = tekstiosa.substring(0, kohta) + "# " + rivi + tekstiosa.substring(kohta);
return tekstiosa;
}
osio.tekstiosa(kasittele_maaritelmalista(osio.tekstiosa()));
};
this.lisaa_sanalkosio = function(kieli, sanalk, muotoile, data) {
// etsitään oikea kieliotsikko
var slkosio = this.juuri.aliosiot(kieli.isolla());
if ( slkosio === null ) {
alert("virhe: kieltä (" + kieli + ") ei löydykään!");
return sivuteksti; // virhe
}
////console.log("löyty kieli: " + kieli.isolla());
// haetaan sanaluokkaosio, jonka perään uusi osio lisätään
var kohta = hae_osio(slkosio, sanalk.isolla(), function (a, b) { return a.localeCompare(b); });
var uusi = null;
if ( kohta === null ) { // osiolla ei ole aliosioita
////console.log("lisätään osion " + slkosio.nimi + " loppuun");
uusi = slkosio.lisaa_aliosio(sanalk.isolla(), muotoile(data));
} else {
////console.log("lisätään osion " + kohta.nimi + " eteen");
uusi = kohta.lisaa_eteen(sanalk.isolla(), muotoile(data));
}
if ( kieli.toLowerCase() == "suomi" ) {
// TODO ei tänne
this.lisaa_kaannoslaatikko(uusi, data.uuden_num, data.maaritelma);
}
return this;
};
/**
* Lisää kieliosion `kieli` ja sille sanaluokkaosion `sanalk`, joka muotoillaan callback-funktiolla `muotoile`.
* Funktiolle välitetään parametriksi `data`.
* kieli (merkkijono): kieliosion otsikko (muutetaan isolla kirjaimella alkavaksi)
* sanalk (merkkijono): sanaluokkaosion otsikko (muutetaan isolla kirjaimella alkavaksi)
* muotoile (funktio(data) -> merkkjono): sanaluokkaosion muotoilufunktio
* data (*): funktiolle välitettävä data
**/
this.lisaa_kieliosio = function(kieli, sanalk, muotoile, data) {
/*
* Palauttaa
* -1, jos s1 tulee ennen s2:ta;
* +1, jos s2 tulee ennen s1:tä ja
* 0, jos s1 == s2.
*/
function vertaa_h2(s1, s2) {
////console.log("s1: " + s1 + ", s2: " + s2);
if ( s1 == s2 ) {
return 0; }
if ( s1 == "Kansainvälinen" ) {
return -1; }
if ( s2 == "Kansainvälinen" ) {
return 1; }
if ( s1 == "Suomi" ) {
return -1; }
if ( s2 == "Suomi" ) {
return 1; }
if ( s1 == "Lähteet" ) {
return 1; }
if ( s2 == "Lähteet" ) {
return -1; }
if ( s1 == "Viitteet" ) {
return 1; }
if ( s2 == "Viitteet" ) {
return -1; }
return s1.localeCompare(s2); // TODO riippumaton lokaalista
}
// haetaan sanaluokkaosio, jonka perään uusi osio lisätään
var kohta = hae_osio(this.juuri, kieli.isolla(), vertaa_h2);
var lisatty = null;
if ( kohta === null ) { // sivulla ei ole aliosioita
lisatty = this.juuri.lisaa_aliosio(kieli.isolla(), "");
} else {
lisatty = kohta.lisaa_eteen(kieli.isolla(), "");
}
lisatty.lisaa_aliosio(sanalk.isolla(), muotoile(data));
return this;
};
// Alustus
erota_kielilinkit(this);
// Juuriosio.
this.juuri = indeksoi(teksti);
} // Wikitext
window.wikiedit = {
indeksoi_teksti: function(teksti) {
return new Wikitext(teksti);
}
};