User:Surjection/Gadget-RhymesAdder.js
Appearance
Note: You may have to bypass your browser’s cache to see the changes. In addition, after saving a sitewide CSS file such as MediaWiki:Common.css, it will take 5-10 minutes before the changes take effect, even if you clear your cache.
- Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
- Konqueror and Chrome: click Reload or press F5;
- Opera: clear the cache in Tools → Preferences;
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.
- This user script lacks a documentation subpage. Please create it.
- Useful links: root page • root page’s subpages • links • redirects • your own
/* {{documentation}}<nowiki>
Author: Yair rand
Dependencies: ext.gadget.Editor,ext.gadget.LanguageUtils,mediawiki.util,mediawiki.Uri
To do:
* Make less ugly
* Ability to remove/edit rhymes
* Put rhyme template at the bottom of pronunciation section?
* Fix jillion bugs (none of which I'm aware of yet, but I'll find them...)
* Add qualifier button
* Sorting (almost done)
*/
/*jshint maxerr:1048576, strict:true, undef:true, latedef:true, es5:true */
/*global mw, WikiXml, importScript, importScriptURI, $ */
var numberOfRhymesAdded = 0;
// Derived from [[User:Erutuon/scripts/templateParser.js]].
function parseTemplate(templateText) {
var parameters = new Object(null),
parameterRegex = /\|(?:([^=|}]+)=([^|}]+)|([^|}]+))/g,
template = new Object(null);
template.parameters = parameters;
var match,
index = 1,
name = templateText.match(/^{{([^|}]+)/);
if (name === null)
throw new Error("Invalid template: no name.");
template.name = name[1];
while ((match = parameterRegex.exec(templateText)) !== null) {
if (match[1]) {
parameters[match[1]] = match[2];
} else {
parameters[index++] = match[3];
}
}
return template;
}
function hasRhymeTemplate(wikitext, languageCode, rhyme) {
// [[Template:Rhymes]] and [[Template:rhyme]] redirect to [[Template:rhymes]].
// Simple regex is sufficient because there are no cases of {{rhymes}} with
// nested templates in the dump.
var match, rhymeTemplate = /{{[Rr]hymes?\|.+?}}/g;
while ((match = rhymeTemplate.exec(wikitext)) !== null) {
var template = parseTemplate(match[0]);
var templateLanguageCode = template.parameters.lang || template.parameters[1];
if (templateLanguageCode == languageCode) {
for (var i = template.parameters.lang ? 1 : 2; template.parameters[i]; ++i) {
if (template.parameters[i].trim() === rhyme)
return true;
}
}
}
// special case for {{fi-p}}
var fipTemplate = /{{fi-p(?:ronunciation)?\|.+?}}/g;
while ((match = rhymeTemplate.exec(wikitext)) !== null) {
template = parseTemplate(match[0]);
if (template.parameters.r || template.parameters.rhymes)
return true;
}
return false;
}
function setUpRhymeAdderFor(h3, ii) {
var findNumberOfHeaders = parseInt(new mw.Uri(h3.find("a").get(0).href).query.section);
var addNewRhymeForm;
editor = new Editor();
new AdderWrapper(editor, {
'createForm': function() {
return addNewRhymeForm =
$('<form>')
.append(
$('<label>+Add new rhyme: </label>')
.append($('<input>').attr("name", 'rhyme'))
)
.append($('<input>').attr('type', 'submit').val('Add'))[0];
},
'fields': {
'rhyme': function(txt, error) {
return txt || error('Please specify a rhyme.');
}
},
'onsubmit': function(values, render) {
var langname = mw.config.get("wgTitle").split('/')[0];
var lutils = new LanguageUtilsAsync();
lutils.GetWiktionaryCodeByCanonicalName(langname).then(function(langcode) {
$(addNewRhymeForm).find('input')[0].value = "";
var newItem = '{{l|' + langcode + '|' + values.rhyme + '}}';
render(newItem, function(newhtml) {
var addedRhymeNode = $("<li>").html(newhtml),
collator = window.Intl && new Intl.Collator( langcode, { "case": false } ),
sortFunction = collator ?
collator.compare :
function compare( a, b ) {
return a.toUpperCase() < b.toUpperCase() ? -1 : 1;
};
editor.addEdit({
'edit': function(wikitext) {
var wikixml = WikiXml.parseWikitext(wikitext);
var hdr = $(wikixml.find("section").get(findNumberOfHeaders - 1));
var headerData = $.trim(hdr.find("data").get(0).textContent);
var rhymes = headerData.split(/\r?\n/),
lead = "\n" + ( /^<!--.+-->$/.test( rhymes[ 0 ] ) ? rhymes.shift() + "\n" : "" );
rhymes.push("* " + newItem);
var canRearrange = true;
var terms = rhymes.map(function(line) {
var m;
m = line.match(/^\* ?{{l\|[a-zA-Z]{2,3}\|(.+)}}$/);
if (m && m[1]) return m[1];
m = line.match(/^\* ?\[\[(.+)]\]$/);
if (m && m[1]) return m[1];
canRearrange = false;
return null;
});
if (canRearrange) {
terms.sort( sortFunction );
terms = terms.map(function(el) {
return "* {{l|" + langcode + "|" + el + "}}";
});
$(hdr.find("data").get(0)).text(lead + terms.join("\n") + "\n\n");
} else {
$(hdr.find("data").get(0)).text(lead + rhymes.join("\n") + "\n\n");
}
return WikiXml.toWikitext(wikixml);;
},
'redo': function() {
ii.append(addedRhymeNode);
ii.find("li").sort(function(a, b) {
return sortFunction( $(a).text(), $(b).text() );
}).appendTo(ii);
},
'undo': function() {
addedRhymeNode.remove();
},
'summary': "+rhyme [[" + values.rhyme + "]]",
'after_save': function() {
numberOfRhymesAdded++;
document.body.style.cursor = 'wait';
new mw.Api().edit(values.rhyme, function(text) {
text = text.content;
var rhymehome = mw.config.get("wgTitle").split("/")[1];
if (hasRhymeTemplate(text, langcode, rhymehome)) {
document.body.style.cursor = --numberOfRhymesAdded ? 'wait' : '';
return $.Deferred().reject('rhyme already on page');
}
if (text.match('==' + langname + '==') && text.match("\\{\\{fi-p(?:ronunciation)?[^}]*\\}\\}")) { // special case for {{fi-p}}
text = text.replace(
RegExp('\{\{(fi-p(?:ronunciation)?[^}]*)\}\}'),
'{{$1|r=' + rhymehome + '}}'
);
}
else if (text.match('==' + langname + '==') && !text.match("\\{\\{rhymes(\\|lang=" + langcode + "\\|" + mw.util.escapeRegExp(rhymehome) + "|\\|" + mw.util.escapeRegExp(rhymehome) + "\\|lang=" + langcode + "|\\|" + mw.util.escapeRegExp(rhymehome) + ")\\}\\}")) {
if (!String(text.match("==" + langname + "==[\\s\\S]*?(----|$)")).match("=Pronunciation=")) {
text = text.replace(RegExp("(==" + langname + "==[\\s\\S]*?(?=\n=+(?=[^=])(?!(Etymology=|Alternative))))"), "$1\n===Pronunciation===\n");
}
text = text.replace(
RegExp('(==' + langname + '==[\\s\\S]*?=+Pronunciation=+[\\s\\S]*?\n(?![\:\*]))'),
'$1* {{rhymes|' + langcode + "|" + rhymehome + '}}\n'
);
}
if (text) return {
text: text,
summary: "+rhyme [[" + mw.config.get("wgPageName") + "|" + "-" + rhymehome + "]]"
};
else {
document.body.style.cursor = --numberOfRhymesAdded ? 'wait' : '';
return $.Deferred().reject('problem text is false');
}
}).then(function() {
document.body.style.cursor = --numberOfRhymesAdded ? 'wait' : '';
});
}
}, addedRhymeNode[ 0 ]);
});
});
}
}, h3.parent()[0], ii.next()[0]);
}
function setUpRhymeAdder() {
$('h3').each(function() {
var h3 = $(this);
if (h3.text().indexOf("syllable") != -1) {
var ii = h3.next()[0];
while (ii && (!ii.nodeName || !(ii.nodeName == "UL" || ii.nodeName == "DIV" || ii.nodeName == "H3"))) {
ii = ii.nextSibling;
}
if (!ii || !ii.nodeName) {
h3.parent().append(ii = $('<ul>').append($('<li>').css("display", "none")));
}
if (ii.nodeName == "H3") {
$(ii).before(ii = $('<ul>').append($('<li>').css("display", "none")));
}
try {
setUpRhymeAdderFor(h3, $(ii));
} catch (e) {
console.log(e);
}
}
});
}
if (mw.config.get('wgNamespaceNumber') === 106 && mw.config.get("wgAction") == "view")
$.getScript("//en.wiktionary.org/w/index.php?title=User:Dixtosa/XMLize.js&action=raw", function() {
$(setUpRhymeAdder);
});
// </nowiki>