Jump to content

User:LOL/citespacing.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <nowiki>
var citePrefix = ["{{cite ", "{{Citation", "{{citation"];

function citeSpacing(src) {
    src = src.replace(/\{\{\s*[Cc]ite /g, "{{cite ");
    src = citeSpacing_refCaps(src);
    // {{cite ...}} templates
    for (var l in citePrefix) {
        var i = -1;
        while ((i = src.indexOf(citePrefix[l], i + 1)) != -1) {
            var count = 1;
            // Must be synched after concat
            var limit = i + citePrefix[l].length - 1;
            var innerTemplate = [];
            while (count > 0) {
                limit++;
                var j = src.indexOf("{{", limit + 1);
                var k = src.indexOf("}}", limit + 1);
                if (j == -1 && k == -1) {
                    return src;
                } else if (j == -1) {
                    limit = k;
                } else if (k == -1) {
                    limit = j;
                } else {
                    limit = Math.min(j, k);
                }
                if (src.charAt(limit) == '{') {
                    if (count == 1) {
                        // Left side of inner template
                        innerTemplate.push(limit);
                    }
                    count++;
                } else {
                    count--;
                    if (count == 1) {
                        // Right side of inner template
                        innerTemplate.push(limit);
                    }
                }
            }
            var offset = 0;
            // Equal signs
            var j = i;
            while ((j = src.indexOf('=', j + 1)) < limit && j != -1) {
                if (citeSpacing_inInnerTemplate(j, innerTemplate, offset)) {
                    // Bypass inner template
                    continue;
                }
                // Skip if line starts with parameter
                var iBracket = src.lastIndexOf('|', j);
                if (src.substring(src.lastIndexOf('\n', iBracket) + 1,
                        iBracket).replace(/^\s+|\s+$/, '').length == 0) {
                    continue;
                }
                var k;
                for (k = j + 1; src.charAt(k) == ' '; k++) {
                }
                if (k > j + 1 && src.charAt(k) != '}') {
                    src = src.substring(0, j + 1) + src.substring(k);
                    var change = (j + 1) - k;
                    offset += change;
                    limit += change;
                }
                for (k = j - 1; src.charAt(k) == ' '; k--) {
                }
                if (k < j - 1) {
                    src = src.substring(0, k + 1) + src.substring(j);
                    var change = (k + 1) - j;
                    offset += change;
                    limit += change;
                    j = k + 1;
                }
            }
            // Pipes
            j = i;
            while ((j = src.indexOf('|', j + 1)) < limit && j != -1) {
                if (citeSpacing_inInnerTemplate(j, innerTemplate, offset)) {
                    // Bypass inner template
                    continue;
                }
                // Leave alone if '|' at start of line
                if (src.substring(src.lastIndexOf('\n', j) + 1, j).replace(/^\s+|\s+$/, '')
                        .length == 0) {
                    continue;
                }
                var k;
                for (k = j + 1; src.charAt(k) == ' '; k++) {
                }
                if (k > j + 1) {
                    src = src.substring(0, j + 1) + src.substring(k);
                    var change = (j + 1) - k;
                    offset += change;
                    limit += change;
                }
                for (k = j - 1; src.charAt(k) == ' '; k--) {
                }
                if (k == j - 1) {
                    // Needs one leading space
                    src = src.substring(0, j) + ' ' + src.substring(j);
                    var change = 1;
                    offset += change;
                    limit += change;
                    j++;
                } else if (k < j - 2) {
                    src = src.substring(0, k + 1) + src.substring(j - 1);
                    var change = k - j + 2;
                    offset += change;
                    limit += change;
                    j = k + 2;
                }
            }
        }
    }
    src = citeSpacing_refTags(src);
    document.getElementById('wpTextbox1').value = src;
}

function citeSpacing_inInnerTemplate(i, innerTemplate, offset) {
    for (var j = 0; j < innerTemplate.length; j += 2) {
        if (innerTemplate[j] + offset < i
                && i < innerTemplate[j + 1] + offset) {
            // Bypass inner template
            return true;
        }
    }
    return false;
}

function citeSpacing_refCaps(src) {
    // Fix capitalization (e.g. "<REF" -> "<ref")
    return src.replace(/(<\/?)[Rr][Ee][Ff](.*?) *>/g, "$1ref$2>");
    // e.g. {{ Reflist }} -> {{reflist}}
    // return src.replace(/\{\{ *Ref(s|list|begin|end) *(\||\})/g,
    // "{{ref$1$2");
}

function citeSpacing_refTags(src) {
    // <ref> tags
    var i = -1;
    while ((i = src.indexOf("<ref", i + 1)) != -1) {
        i += 4;
        if (src.substring(i, i + 7) == "erences") {
            // <references />
            i += 7;
            var j = src.indexOf('>', i);
            src = src.substring(0, i) + " /" + src.substring(j);
            continue;
        }
        var j = src.indexOf('>', i);
        var k = src.lastIndexOf('=', j);
        var slash = false;
        if (k > i) {
            var name = src.substring(k + 1, j).replace(/^\s+|\s+$/, '');
            if (name.length == 0) {
                alert(src.substring(i, j));
                continue;
            }
            var l = src.lastIndexOf('/', j);
            if (l > k) {
                slash = true;
                name = name.replace(/\//g, "").replace(/^\s+|\s+$/g, '');
            }
            var quote = ' ';
            if (name[0] == '"') {
                quote = '\"';
            } else if (name[0] == '\'') {
                quote = '\'';
            }
            if (quote != ' ') {
                name = name.substring(1);
                var m = name.length - 1;
                if (name.charAt(m) == quote) {
                    name = name.substring(0, m);
                }
            }
            name = name.replace(/^\s+|\s+$/, '');
            src = src.substring(0, i) + " name=\"" + name + "\""
                    + (slash ? " /" : "") + src.substring(j);
            j = src.indexOf('>', i);
        }
        if (!slash) {
            j++;
            k = src.indexOf("</ref>", j);
            if (k != -1) {
                // Trim space after "<ref>" or before </ref>"
                var ref = src.substring(j, k);

                var str = ref.replace(/^\s+|\s+$/, '');
                var l;
                for (l = 0; str.charAt(l) == ' '; l++) {
                    // "<ref> " -> "<ref>"
                }
                var m;
                for (m = str.length - 1; /\s/.test(str.charAt(m)); m--) {
                    // "\n </ref>" -> "</ref>"
                }

                if (l > 0 || m < str.length - 1) {
                    src = src.substring(0, j) + str.substring(l, m + 1)
                            + src.substring(k);
                }
            }
        }
    }
    return src;
}

$(function() {
    if (document.forms.editform) {
        mw.util.addPortletLink('p-tb', 'javascript:citeSpacing(document.getElementById("wpTextbox1").value)', 'Cite spacing', 't-citespacing', 'Change spacing in citation templates', '', '');
    }
});
// </nowiki>