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
    if (s.charAt(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.charAt(0) == "+") { // followed by multiple-digit indent
        return [s.slice(1)];
    } else if (s.charAt(0) == "°") {
    	return pr(s.slice(1)+"%0/.");
    } else if (s.charAt(0) == "§") {
    	return pr(s.slice(1)+"%01/.");
    } else if (s.length > 1) { // followed by normal
    	if (["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."].includes(s.charAt(0))) {
        	return [s.charAt(0)].concat(pr(s.slice(1)));
    	} else {
    		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 [s];
    }
}
function expand (l) { // expands #r ??? into #\n=r ???
	var res = [];
	for (var s of l) {
		if (s.slice (0,3) == "?R ") {
			res.push("?");
			res.push("+R "+s.slice(3));
		} else {
			res.push(s);
		}
	}
	return res;
}
function poemise() { // apply poem formatting
    var l = $('#wpTextbox1').val();
    l = expand(l.split("\n"));
    var t = [];
    var rhyme = ["0"];
    var ri = 0;
    var res = "";
    var theend = false;
    var inside = (l.includes("?")?false:true);
    var before = [];
    var after = [];
    var passed = inside;
    for (var i = 0; i < l.length; i++) {
    	var ll = l[i];
    	if (ll == "?") {
    		inside = true;
    		passed = true;
    	} else if (ll == "/" || ll == "/ ") {
    		inside = false;
    	} else if (ll == "£") {
    		theend = true;
    	} else if (inside) {
    		if (ll == "") {}
	        else if (ll.slice(0, 3) == "+R ") {
	            rhyme = pr(ll.slice(3)); 
	            console.log(ll, rhyme);
	        } else if (ll.slice (0, 3) == "+I ") {
	            ri = Number(ll.slice(3));
	        } else if (t.length > 0) {
	        	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 {
	    	if (passed) {
				after.push(ll);
	    	} else {
	    		before.push(ll);
	    	}
	    }
    }
    for (let i = 0; i < rhyme.length; i++) {
    	if (rhyme[i] != ".") {
    		rhyme[i] = Number(rhyme[i]);
    	}
    }
    for (var lb of before) {
    	res += lb + "\n";
    }
    var nobefore = !(l.includes("?"));
    var noafter = !(l.includes("/")) && !(l.includes("/ "));

    if (nobefore) {
    	res += "{{ppoem|\n";
    	if (rhyme[(ri < 1)?(rhyme.length+ri-1):(ri-1)] != ".") {
    		res += "start=follow|\n";
    	} else {
    		res += "start=stanza|\n";
		}
    }
    var li = 0;
    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 (noafter && !theend) {
    	if (rhyme[ri] != ".") {
    		res += "|end=follow";
    	} else {
    		res += "|end=stanza";
    	}
    }
    if (noafter) {
    	res += "\n}}";
    }
    for (var la of after) {
    	res += la + "\n";
    }
    $('#wpTextbox1').val(res);
}