User:Alien333/poemise.js

From Wikisource
Jump to navigation Jump to search
Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Cmd-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (Cmd-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Clear the cache in Tools → Preferences

For details and instructions about other browsers, see Wikipedia:Bypass your cache.

/* global mw,$ */
"use strict";
// documentation: [[User:Alien333/Poemise]]
mw.loader.using(['mediawiki.util'], () => {

  $(() => { 
  	
    if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) < 0) { // if not editing
        return;
    }
    if (mw.config.get('wgCanonicalNamespace') == 'Page' && mw.config.get('wgPageContentModel') == 'proofread-page') { // text-cleaning and other functions in Page:
    	var poemisebtn = mw.util.addPortletLink(
	      'p-tb', '#', 'Poemise', 'poemise', // not sure what this last string does
	      'Do a little bit of formatting and apply indent pattern.'
	    ); 
	    $(poemisebtn).click(event => {
	      event.preventDefault();
	      poemise();
	    });
    }
    });
});
function opsplit(s, o) { // splits by op if op is not in parentheses
    var r = [];
    var i = 0;
    var par = 0;
    for (let j = 0; j < s.length; j++) {
        if (s.charAt(j) == "(") {
            par += 1;
        } else if (s.charAt(j) == ")") {
            par -= 1;
        } if (par == 0 && s.charAt(j) == o) {
            r.push(s.slice(i, j));
            i = j+1;
        }
    }
    r.push(s.slice(i, s.length));
    return r;
}
function op(s, o) { // checks there is an op not in parentheses
    var par = 0;
    for (let i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if (c == "(") {
            par += 1;
        } else if (c == ")") {
            par -= 1;
        } if (par == 0 && c == o) {
            return true;
        }
    }
    return false;
}
function concat(ll) { // concat array array
    var r = [];
    for (var l of ll) {
        r = r.concat(l);
    }
    return r;
}
var multiplyArray = (arr, length) =>
  Array.from({ length }, () => arr).flat();
function pr(s) { // calculate indent pattern. don't remember what pr stood for. 
    if (s[0] == "(" && s.slice(-1) == ")") { // grouping has 1st priority
        return pr(s.slice(1, -1));
    } else if (op(s, ";")) { // followed by separator
        return concat(opsplit(s, ";").map(pr));
    } else if (op(s, "*")) { // followed by mult
        var l = opsplit(s,  "*");
        return multiplyArray(pr(l.slice(1).join("*")), Number(l[0]));
    } else if (s[0] == "!") { // followed by multiple-digit indent
        return [Number(s.slice(1))];
    } else if (s[0] == ",") {
    	return pr(s.slice(1)+"*0;.");
    } else if (s[0] == ":") {
    	return pr(s.slice(1)+"*01;.");
    } else if (s.length > 0) { // followed by normal
    	if (["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(s[0])) {
        	return [Number(s[0])].concat(pr(s.slice(1)));
    	} else if (s[0] == ".") {
    		return ["."].concat(pr(s.slice(1)));
    	} else if (s[0] == " ") {
    		return pr(s.slice(1)); // Number(" ") behaves perfectly normally so it adds a 0 at the end of the pattern if there is a " " at the end, which is not what we want
    	} else {
    		return ["!"]; // trigger error later
    	}
    } else {
        return [];
    }
}
function poemise() { // apply poem formatting
    var l = $('#wpTextbox1').val();
    l = l.split("\n"); // list (of lines)
    var t = []; // text
    var rhyme = ["0"];
    var ri = 0; // rhyme index
    var res = ""; // result
    var theend = false; // of the poem
    var before = l.some((ll) => ll[0] == "+");
    var inside = !before;
    var err = false;
    for (var i = 0; i < l.length; i++) { // parse the text
    	var ll = l[i];
    	if (ll[0] == "+") { // enter poem
    		inside = true;
    		ll = ll.slice(1);
    	}
    	if (ll[0] == "-") { // exit poem
    		inside = false;
    		di();
    		ll = ll.slice(1);
    	}
    	if (ll[0] == "$") { // no |end=
    		theend = true;
    		ll = ll.slice(1);
    	}
    	if (inside) {
    		if (ll == "") {}
	        else if (ll[0] == "*") { // rhyme pattern
	        	ll = ll.slice(1);
	            rhyme = pr(ll);
	            console.log(ll, rhyme);
	        } else if (ll[0] == "/") { // index to start
	            ri = Number(ll.slice(1));
	        } else if (t.length > 0) { // some de-wrapping, needs last line to exist
	        	if (ll.length < 4) {
		        	t.push(t.pop().slice(0,-1)+ll); // for misplaced punctuation, appends before but slices the last space away
		        } else if (ll.length > 0 && ll[0] >= 'a' && ll[0] <= 'z') {
		        	t.push(t.pop()+ll); // append to line before if it starts by a lowercase letter (as this is for poetry, I assume it is a hard wrap)
		        } else {
	            	t.push(ll);
		        }
	        } else {
	        	t.push(ll);
	        }
    	} else {
	    	res += ll + "\n";
	    }
    }
    if (inside) { // no -, must end manually
    	di();
    }
	function di () { // do it
	    // make some checks to avoid infinite loop || added 0 || ignored char
	    var nonempty = false;
	    for (let i = 0; i < rhyme.length; i++) {
	    	if (rhyme[i] != ".") {
	    		rhyme[i] = Number(rhyme[i]);
	    		nonempty = true;
	    	} else if (rhyme[i] == "!") {
	    		alert("Poemise: Invalid input: unrecognized characters in indent pattern");
	    		err = true;
	    	}
	    }
	    if (!nonempty) { // would go into infinite loop else, which is a bit annoying
	    	alert("Poemise: Invalid input: the indent pattern is only composed of stanza breaks");
	    	err = true;
	    }
	    
	    if (!before) { // finding start
	    	res += "{{ppoem|\n";
	    	if (rhyme[(ri < 1)?(rhyme.length+ri-1):(ri-1)] != ".") { // if char before in rhym is a .
	    		res += "start=follow|\n";
	    	} else {
	    		res += "start=stanza|\n";
			}
	    }
	    var li = 0; // doing the main loop, adding :'s
	    while (li < t.length) {
	        while (rhyme[ri] == ".") {
	            res += "\n";
	            ri = (ri+1)%rhyme.length;
	        }
	        if (t[li].slice(0, 5) == "{{di|" && rhyme[ri] > 0) {
	            res += "{{idi|" + ":".repeat(rhyme[ri])+"|"+t[li].slice(5)+"\n";
	        } else {
	        	res += ":".repeat(rhyme[ri])+t[li]+"\n";
	        }
	        li += 1;
	        ri = (ri+1) % rhyme.length;
	    }
	    if (inside && !theend) {
	    	if (rhyme[ri] != ".") {
	    		res += "|end=follow";
	    	} else {
	    		res += "|end=stanza";
	    	}
	    }
	    if (inside) {
	    	res += "\n}}";
	    }
	}
    if (!err) {
    	$('#wpTextbox1').val(res);
    }
}