User:Erutuon/scripts/todo-lists.js

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Note – after saving, you may have to bypass your browser’s cache to see the changes.

  • 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.

{const pageName = mw.config.get("wgPageName");

const templateToWikitext = function(name, parameters) {
	const printed = [name];
	let i = 1;
	for (const [k, v] of parameters) {
		const kNumber = parseInt(k);
		if (kNumber && kNumber == i) {
			printed.push(v);
			i++;
		} else {
			printed.push(k + "=" + v);
		}
	}
	return "{{" + printed.join("|") + "}}";
};

const applyChanges = function(parameters, changes) {
	const added = [];
	const additions = changes.filter(({action: [action]}) => action === "add").map(({action: [action, ...args]}) => args);
	const newParameters = parameters.filter(([k, v]) => {
		for (const {action: [action, ...args]} of changes) {
			if (action === "remove" && k === args[0]) {
				return false;
			}
		}
		return true;
	}).map(([k, v]) => {
		for (const [kAdded, vAdded] of additions) {
			if (k === kAdded) {
				added.push(k);
				return [k, vAdded];
			}
		}
		return [k, v];
	});
	for (const [kAdded, vAdded] of additions) {
		if (!added.includes(kAdded)) {
			newParameters.push([kAdded, vAdded]);
		}
	}
	return newParameters;
};

const templateClass = "tlx";
mw.loader.using(["mediawiki.util", "mediawiki.api"], function() {
	mw.util.addCSS("." + templateClass + " { display: inline-grid; margin: 0.2em 0; }");
});

mw.loader.using("mediawiki.api", function() { $(function() {
	const dl = document.createElement("dl");
	const pre = document.querySelector(".mw-parser-output pre.title-and-templates");
	if (!pre) { return; }
	const articlePath = mw.config.get("wgArticlePath");
	pre.textContent
	.split("\n")
	.filter(line => line !== "")
	.map(JSON.parse)
	.forEach(item => {
		const dt = document.createElement("dt");
		const viewLink = document.createElement("a");
		viewLink.textContent = item.title;
		viewLink.href = articlePath.replace("$1", item.title);
		dt.appendChild(viewLink);
		const sup = document.createElement("sup");
		const editLink = document.createElement("a");
		editLink.textContent = "edit";
		editLink.href = articlePath.replace("$1", "Special:Edit/" + item.title);
		sup.appendChild(editLink);
		dt.appendChild(sup);
		
		const ul = document.createElement("ul");
		for (const template of item.templates) {
			const li = document.createElement("li");
			const innerPre = document.createElement("pre");
			innerPre.classList.add(templateClass);
			innerPre.textContent = template;
			li.appendChild(innerPre);
			ul.appendChild(li);
		}
		const dd = document.createElement("dd");
		dd.appendChild(ul);
		
		dl.appendChild(dt);
		dl.appendChild(dd);
	});
	pre.insertAdjacentElement('beforeBegin', dl);
}); if (pageName === "User:Erutuon/lists/best_script_not_matching_sc_parameter") $(function() {
	const dl = document.createElement("dl");
	const preList = document.querySelectorAll(".mw-parser-output pre");
	if (preList.length === 0) { return; }
	const pre = preList[preList.length - 1];
	const articlePath = mw.config.get("wgArticlePath");
	pre.textContent
	.split("\n")
	.filter(line => line !== "")
	.map(JSON.parse)
	.forEach(item => {
		const dt = document.createElement("dt");
		const viewLink = document.createElement("a");
		viewLink.textContent = item.title;
		viewLink.href = articlePath.replace("$1", item.title);
		dt.appendChild(viewLink);
		const sup = document.createElement("sup");
		const editLink = document.createElement("a");
		editLink.textContent = "edit";
		editLink.href = articlePath.replace("$1", "Special:Edit/" + item.title);
		sup.appendChild(editLink);
		dt.appendChild(sup);
		
		const ul = document.createElement("ul");
		for (const {template, link} of item.links) {
			const li = document.createElement("li");
			const templateElement = document.createElement("code");
			templateElement.classList.add(templateClass);
			templateElement.textContent = templateToWikitext(template.name, template.parameters);
			li.appendChild(templateElement);
			for (const name of ["lang", "best_script", "best_script_without_lang"]) {
				let item = link[name];
				if (item) {
					if (item instanceof Array) item = item[1];
					const code = document.createElement("code");
					code.textContent = item;
					li.append("; " + name.replace(/_/g, " ") + " = ");
					li.appendChild(code);
				}
			}
			ul.appendChild(li);
		}
		const dd = document.createElement("dd");
		dd.appendChild(ul);
		
		dl.appendChild(dt);
		dl.appendChild(dd);
	});
	pre.insertAdjacentElement('beforeBegin', dl);
}); if (pageName === "User:Erutuon/lists/best_script_not_matching_sc_parameter/fixes" || pageName === "User:Erutuon/lists/bad_transliteration/Cyrillic_and_Latin/fixes") $(function() {
	const dl = document.createElement("dl");
	const preList = document.querySelectorAll(".mw-parser-output pre");
	const pre = preList[preList.length - 1];
	const articlePath = mw.config.get("wgArticlePath");
	const data = JSON.parse(pre.textContent);
	const summaries = Array.from(new Set(data.flatMap(page => {
		if (!page.templates[0].changes.summary) {
			return [page.summary];
		}
		return page.templates.flatMap(template => template.changes.flatMap(change => change.summary));
	})));
	const separator = "\uE000";
	new mw.Api().post({
		action: "parse",
		summary: summaries.join(separator),
		prop: "text",
		formatversion: "2",
	}).fail(console.error).then(response => response.parse.parsedsummary.split(separator)).then(parsedSummaries => {
		const summaryMap = new Map(parsedSummaries.map((parsedSummary, i) => [summaries[i], parsedSummary]));
		data.forEach(item => {
			const dt = document.createElement("dt");
			const viewLink = document.createElement("a");
			viewLink.textContent = item.title;
			viewLink.href = articlePath.replace("$1", item.title);
			dt.appendChild(viewLink);
			const sup = document.createElement("sup");
			const editLink = document.createElement("a");
			editLink.textContent = "edit";
			editLink.href = articlePath.replace("$1", "Special:Edit/" + item.title);
			sup.appendChild(editLink);
			dt.appendChild(sup);
		
			const pageSummary = item.summary;
			if (pageSummary) {
				const parsedPageSummary = summaryMap.get(pageSummary);
				if (parsedPageSummary) {
					const summaryNoteElement = document.createElement("span");
					const summaryElement = document.createElement("span");
					summaryElement.innerHTML = parsedPageSummary;
					summaryNoteElement.append(" (", summaryElement, ")");
					summaryNoteElement.style.fontWeight = "normal";
					dt.append(summaryNoteElement);
				} else {
					console.error("Failed to parse summary " + pageSummary);
				}
			}
		
			const ul = document.createElement("ul");
			for (const {
					template,
					changes,
				} of item.templates) {
				const li = document.createElement("li");
				li.dataset.template = JSON.stringify(template);
				li.dataset.changes = JSON.stringify(changes);
				const templateElement = document.createElement("code");
				templateElement.classList.add(templateClass);
				templateElement.textContent = templateToWikitext(template.name, template.parameters);
				li.appendChild(templateElement);
				li.append(" → ");
				const newTemplateElement = document.createElement("code");
				newTemplateElement.textContent = templateToWikitext(template.name, applyChanges(template.parameters, changes));
				li.appendChild(newTemplateElement);
				const changeSummaries = changes.map(change => change.summary);
				li.dataset.summary = changeSummaries.join("; ");
				const parsedChangeSummaries = changeSummaries.map(s => summaryMap.get(s));
				if (parsedChangeSummaries.length > 0 && parsedChangeSummaries.every(s => s != undefined)) {
					const summaryElement = document.createElement("span");
					summaryElement.innerHTML = parsedChangeSummaries.join("; ");
					li.append(" (");
					li.appendChild(summaryElement);
					li.append(")");
				} else if (changes[0].summary) {
					const unparsedChangeSummaries = changeSummaries.filter(s => !summaryMap.get(s));
					console.error("Failed to parse summaries " + JSON.stringify(unparsedChangeSummaries));
				}
				ul.appendChild(li);
			}
			const dd = document.createElement("dd");
			dd.appendChild(ul);

			dl.appendChild(dt);
			dl.appendChild(dd);
		});
		pre.insertAdjacentElement('beforeBegin', dl);
		
		function* chunks(arr, n) {
			arr = Array.from(arr);
			for (let i = 0; i < arr.length; i += n) {
				yield arr.slice(i, i + n);
			}
		}
		
		window.filterChangeItems = function (filter) {
			Array.from(chunks(document.querySelector("dl").childNodes, 2)).forEach(([t, d]) => {
				const lis = Array.from(d.querySelector("ul").children);
				const remaining = lis.filter(li => {
					const summary = li.dataset.summary;
					const match = summary.match(/\((?<from>[^→]+) → (?<to>[^\)]+)\)[^\(]+\((?<lang>[^\)]+)\) text/).groups;
					return filter(match.lang, match.from, match.to, summary);
				});
				lis.forEach(li => {
					li.style.display = remaining.includes(li) ? "" : "none";
				});
				if (remaining.length === 0) {
					t.style.display = "none";
					d.style.display = "none";
				} else {
					t.style.display = "";
					d.style.display = "";
				}
			});
		}
	});
})});
}