User:Erutuon/scripts/accel.js: difference between revisions
< User:Erutuon | scripts
Content deleted Content added
update from WT:ACCEL |
reorganize to deal with extra promise |
||
Line 284: | Line 284: | ||
// Generates entries from the information |
// Generates entries from the information |
||
var |
var printArgs = function(accelParams) { |
||
var args = [ |
var args = [ |
||
"lang=" + mw.util.getParamValue("accel_lang"), |
"lang=" + mw.util.getParamValue("accel_lang"), |
||
Line 300: | Line 300: | ||
} |
} |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
}; |
}; |
||
Line 333: | Line 322: | ||
}; |
}; |
||
receiveModuleResponse = function(response) { |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
generateEntries(accelParams).done(function(response) { |
|||
var newtext; |
var newtext; |
||
Line 414: | Line 386: | ||
summary.value = "Creating forms of [[" + lemma + "]] ([[WT:ACCEL|Accelerated]])"; |
summary.value = "Creating forms of [[" + lemma + "]] ([[WT:ACCEL|Accelerated]])"; |
||
} |
} |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
}).done(receiveModuleResponse); |
|||
⚫ | |||
}); |
}); |
||
} |
} |
Revision as of 06:51, 20 September 2018
// <nowiki>
// jshint maxerr:500
/*
* The starting point of the whole script.
*
* This adds a hook to the page load event so that the script runs
* adds the generated text to the edit window once the page is done loading.
*/
mw.loader.using(["mediawiki.util"]).done(function() {
// Don't do anything unless the current page is in the main namespace.
if (mw.config.get("wgAction") === "view" && (mw.config.get("wgNamespaceNumber") === 0 || mw.config.get("wgPageName") == "Wiktionary:Sandbox")) {
// Stores all accelerated data, by language, by target pagename.
// Sub-arrays are in HTML order.
var accelParamsByPagename = {};
var getTargetPagename = function(link) {
var targetPagename = mw.util.getParamValue("title", link.href);
if (targetPagename === null) {
var match = link.href.match(/^(.*)\/wiki\/([^#]+)(?:#.+)?$/);
if (match) {
targetPagename = decodeURIComponent(match[2]);
}
}
return targetPagename;
};
var getPartOfSpeech = function(link) {
// Acceleration can be added to inflection tables too.
// This tells the search script to skip headers with these names.
var skipheaders = [
"alternative forms",
"antonyms",
"conjugation",
"declension",
"derived terms",
"inflection",
"mutation",
"related terms",
"synonyms",
"translations",
"usage notes"
];
var node = link;
while (node) {
if (node.nodeType == 1 && node.nodeName.match(/^[hH][3456]$/)) {
var header = $(node).find(".mw-headline").text().replace(/^[1-9.]* /, "").toLowerCase();
if (skipheaders.indexOf(header) == -1) {
return header;
}
}
node = node.previousSibling || node.parentNode;
}
throw new Error("This entry seems to be formatted incorrectly. Does it have a language and part-of-speech header?");
};
var createAccelParam = function(link) {
var classnames = $(link).closest(".form-of")[0].className.split(" ");
for (var i = 0; i < classnames.length; ++i) {
// Filter out anything that doesn't belong
if (!(/^(gender|origin|origin_transliteration|pos|target|transliteration)-(.+)$/.test(classnames[i]) || /^(.+)-form-of$/.test(classnames[i]))) {
classnames[i] = "";
}
}
var accelParam = classnames.join(" ").replace(/ +/g, " ").trim();
var targetPagename = getTargetPagename(link);
var targetHead = (link.innerText || link.textContent).replace(" ", "_");
if (targetPagename != targetHead) {
accelParam = "target-" + targetHead + " " + accelParam;
}
return "pos-" + getPartOfSpeech(link).replace(" ", "_") + " " + accelParam;
};
var storeAccelParam = function(link) {
// Extract the targeted pagename from the URL,
// and language code from the nearest element with a lang attribute
var lang = $(link).closest("[lang]")[0].getAttribute("lang");
var targetPagename = getTargetPagename(link);
// Add page name to the list
if (accelParamsByPagename[lang] === undefined) {
accelParamsByPagename[lang] = {};
}
if (accelParamsByPagename[lang][targetPagename] === undefined) {
accelParamsByPagename[lang][targetPagename] = [];
}
var accelParam = createAccelParam(link);
if (accelParamsByPagename[lang][targetPagename].indexOf(accelParam) === -1) {
accelParamsByPagename[lang][targetPagename].push(accelParam);
}
};
var processLink = function(link) {
// Extract the targeted pagename from the URL,
// and language code from the nearest element with a lang attribute
var lang = $(link).closest("[lang]")[0].getAttribute("lang");
var targetPagename = getTargetPagename(link);
// Fetch the acceleration parameters from the store
var accelParam = accelParamsByPagename[lang][targetPagename].slice(0);
for (var i = 0; i < accelParam.length; ++i) {
accelParam[i] = "accel" + (i + 1).toString() + "=" + encodeURIComponent(accelParam[i]);
}
accelParam = accelParam.join("&");
// Convert an orange link into an edit link
if ($(link).hasClass("partlynew")) {
link.href = link.href.replace(/^(.*)\/wiki\/([^#]+)(?:#.+)?$/, "$1/w/index.php?title=$2&action=edit");
}
// Now build a new "green link" URL to replace the original red link with
link.href +=
"&editintro=User:Conrad.Irwin/creation.js/intro" +
"&accel_lang=" + encodeURIComponent($(link).closest("[lang]")[0].getAttribute("lang")) +
"&accel_lemma=" + encodeURIComponent(mw.config.get("wgTitle")) +
"&" + accelParam;
link.style.color = "#22CC00";
};
// Mutation observer to respond when OrangeLinks modifies links
var mutobs = new MutationObserver(function(mutations, observer) {
mutations.forEach(function(mutation) {
if (mutation.attributeName != "class") {
return;
}
var link = mutation.target;
// Don't process a link we've already been to
if (link.style.color == "#22CC00") {
return;
}
if (!$(link).hasClass("partlynew")) {
return;
}
// Process
processLink(link);
});
});
// First generate and store all the parameters
var oldtable = null; // Were we previously inside a table?
var columns = [];
$(".form-of a").each(function() {
// Are we currently inside a table?
var table = $(this).closest("table");
if (table.length > 0) {
table = table[0];
} else {
table = null;
}
// Was a column number specified on the current table cell?
var col = $(this).closest("td[data-accel-col]");
if (col.length > 0) {
col = parseInt(col[0].getAttribute("data-accel-col"));
} else {
col = null;
}
// If we were in a table, and we changed to another table or are no longer in one,
// or if there is no column number attribute, flush the column lists.
if (oldtable && (oldtable !== table || col === null)) {
for (var i = 0; i < columns.length; ++i) {
for (var j = 0; j < columns[i].length; ++j) {
storeAccelParam(columns[i][j]);
}
}
columns = [];
}
oldtable = table;
// The nostore parameter causes the link to not be stored,
// but it is processed later. The effect is that this link has no
// effect on the ordering of forms.
if ($($(this).closest(".form-of")[0]).hasClass("form-of-nostore")) {
return;
}
// If there is a column number attribute, defer storing the link,
// put it in the columns array instead.
if (col !== null) {
--col; // Column attributes are 1-based, JS arrays are 0-based
// Expand the columns list to fit the number of columns
while (columns.length <= col) {
columns.push([]);
}
// Save the link in the columns list
columns[col].push(this);
} else {
// Store the link directly
storeAccelParam(this);
}
});
// Flush column lists
for (var i = 0; i < columns.length; ++i) {
for (var j = 0; j < columns[i].length; ++j) {
storeAccelParam(columns[i][j]);
}
}
// Then add them onto the links, or add a mutation observer
$(".form-of a").each(function() {
if ($(this).hasClass("new") || $(this).hasClass("partlynew")) {
processLink(this);
} else {
// FIXME: There's a small window for a race condition here.
// If the "partlynew" class is added by OrangeLinks after the above if-statement is evaluated,
// but before the observer is added, then the link won't be processed.
mutobs.observe(this, {attributes : true});
}
});
} else if (mw.config.get("wgAction") === "edit") {
// Get the parameters from the URL
var getAccelParams = function() {
var accelParams = [];
var i = 1;
while (true) {
var acceldata = mw.util.getParamValue("accel" + i.toString());
if (!acceldata) {
break;
}
// Default values
var params = {
pos: null,
form: null,
gender: null,
transliteration: null,
origin: mw.util.getParamValue("accel_lemma"),
origin_transliteration: null,
target: mw.config.get("wgTitle"),
};
// Go over each part and add it
var parts = acceldata.split(" ");
for (var j = 0; j < parts.length; ++j) {
var part = parts[j];
if (part.match(/^(gender|origin|origin_transliteration|pos|target|transliteration)-(.+)$/)) {
params[RegExp.$1] = RegExp.$2.replace("_", " ");
} else if (part.match(/^(.+)-form-of$/)) {
params.form = RegExp.$1.replace("_", " ");
}
}
accelParams.push(params);
++i;
}
return accelParams;
};
// Generates entries from the information
var printArgs = function(accelParams) {
var args = [
"lang=" + mw.util.getParamValue("accel_lang"),
"origin_pagename=" + mw.util.getParamValue("accel_lemma"),
"target_pagename=" + mw.config.get("wgTitle"),
"num=" + accelParams.length,
];
for (var i = 0; i < accelParams.length; ++i) {
for (var key in accelParams[i]) {
if (accelParams[i][key] !== null) {
args.push(key + (i + 1) + "=" + accelParams[i][key].replace(/\|/g, "|"));
}
}
}
return args.join("|");
};
var showModuleError = function(errorText) {
// Because we're not actually on the page the error appeared on, there's no link.
// Make an attempt here to restore the link.
var match = errorText.match(/Lua error(?: in|:) (Module:[^#<>\[\]|{}_]+)(?: at line |:)(\d+): /);
if (match) {
var url = mw.util.getUrl(match[1], {action: "edit"}) + "#mw-ce-l" + match[2];
errorText = "<a href=\"" + url + "\">" + errorText + "</a>";
}
errorText =
"<div id=\"accel-error\">" +
"<p><big>An error occurred while generating the entry:</big></p>" +
"<p>" + errorText + "</p>" +
"</div>";
wikipreview.insertAdjacentHTML("beforebegin", errorText);
};
receiveModuleResponse = function(response) {
var newtext;
try {
newtext = JSON.parse(response.expandtemplates.wikitext);
} catch (err) {
showModuleError(response.expandtemplates.wikitext);
return;
}
if (!newtext) {
return;
}
// Does the page already exist?
if (textbox.value) {
var langsection_regex = /^==([^=\n]+)==$/mg;
var match = langsection_regex.exec(newtext);
if (!match) {
showModuleError("No language section was found in the returned text.");
}
var langname = match[1];
// Go over language sections to find where to insert our new one
while ((match = langsection_regex.exec(textbox.value)) !== null) {
if (match[1] == langname) {
// There already exists a section for our language, abort.
return;
} else if (match[1] == "Translingual" || match[1] == "English" || (langname != "English" && match[1] < langname)) {
// Skip past English and Translingual, or if the language sorts higher
continue;
} else {
// We found the first match that sorts lower than our language, great.
break;
}
}
var scrollIndex;
if (match === null) {
// We found no language that our section should go before, so insert it at the end.
textbox.value = textbox.value.trimEnd() + "\n\n----\n\n";
scrollIndex = textbox.value.length;
textbox.value = textbox.value + newtext;
} else {
// We found a language to insert before, so do that.
textbox.value = textbox.value.substring(0, match.index) + newtext + "\n\n----\n\n" + textbox.value.substring(match.index, textbox.value.length);
scrollIndex = match.index;
}
// Scroll the textbox to the newly added section. First scroll all the way down,
// then set the cursor to the start of the new section, which scrolls back up
// to the new section's language header.
textbox.scrollTop = textbox.scrollHeight;
textbox.selectionStart = scrollIndex;
textbox.selectionEnd = scrollIndex;
summary.value = "Adding forms of [[" + lemma + "]] ([[WT:ACCEL|Accelerated]])";
} else {
textbox.value = newtext;
summary.value = "Creating forms of [[" + lemma + "]] ([[WT:ACCEL|Accelerated]])";
}
};
var wikipreview = document.getElementById("wikiPreview");
var textbox = document.getElementById("wpTextbox1");
var summary = document.getElementById("wpSummary");
var lang = mw.util.getParamValue("accel_lang");
var lemma = mw.util.getParamValue("accel_lemma");
if (!(wikipreview && textbox && summary && lang && lemma)) {
return;
}
// Gather all the information that was given in the URL
var accelParams = getAccelParams();
if (!accelParams) {
return;
}
mw.loader.using("mediawiki.api", function() {
new mw.Api().get({
"action": "expandtemplates",
"format": "json",
"text": "{{#invoke:accel|generate|" + printArgs(accelParams) + "}}",
"prop": "wikitext"
}).done(receiveModuleResponse);
});
}
});
// </nowiki>