หมายเหตุ: หลังเผยแพร่ คุณอาจต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง

  • ไฟร์ฟอกซ์ / ซาฟารี: กด Shift ค้างขณะคลิก Reload หรือกด Ctrl-F5 หรือ Ctrl-R (⌘-R บนแมค)
  • กูเกิล โครม: กด Ctrl-Shift-R (⌘-Shift-R บนแมค)
  • อินเทอร์เน็ตเอกซ์พลอเรอร์ และ Edge: กด Ctrl ค้างขณะคลิก Refresh หรือกด Ctrl-F5
  • โอเปร่า: กด Ctrl-F5
// <nowiki>

/*
 * อย่าลืมอ่าน [[ผู้ใช้:ZilentFyld/creat.js/documentation]]
 * หน้านี้กอปมาจาก [[:en:MediaWiki:Gadget-AcceleratedFormCreation.js]] แล้วเพิ่มข้อมูลแล้วเปลี่ยนเป็นภาษาไทย 
 * เอาไว้สร้างหน้าคำผันจากหน้าคำหลัก
 *
 * ข้อมูลการสร้างในแต่ละภาษาอยู่ที่ [[ผู้ใช้:ZilentFyld/creatrule.js]].
 */

/*
 * 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 = match[2];
			}
			
			return targetPagename;
		};
		
		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-" + get_part_of_speech(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 process_link = 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 +=
				"&accel_lang=" + encodeURIComponent($(link).closest("[lang]")[0].getAttribute("lang")) +
				"&accel_langname=" + encodeURIComponent(get_language_name(link)) +
				"&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;
				
				if (!$(link).hasClass("partlynew"))
					return;
				
				// Process
				process_link(link);
				
				observer.disconnect(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"))
				process_link(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 = {
					lang: mw.util.getParamValue("accel_lang"),
					langname: mw.util.getParamValue("accel_langname"),
					pos: null,
					form: null,
					gender: null,
					transliteration: null,
					origin: mw.util.getParamValue("accel_lemma"),
					origin_pagename: mw.util.getParamValue("accel_lemma"),
					origin_transliteration: null,
					target: mw.config.get("wgTitle"),
					target_pagename: 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;
		};
		
		jQuery.getScript("//th.wiktionary.org/w/index.php?action=raw&title=User:ZilentFyld/creatrule.js&ctype=text/javascript&smaxage=21600&maxage=86400", 
			function () {
				var textbox = document.getElementById("wpTextbox1");
				var summary = document.getElementById("wpSummary");
				var lang = mw.util.getParamValue("accel_lang");
				var langname = mw.util.getParamValue("accel_langname");
				var lemma = mw.util.getParamValue("accel_lemma");
				
				if (!textbox || !summary || !lang || !langname || !lemma)
					return;
				
				// Gather all the information that was given in the URL
				var accelParams = getAccelParams();
				
				if (!accelParams)
					return;
				
				// Generate entries from the information
				var entries = [];
				
				for (var i = 0; i < accelParams.length; ++i)
				{
					// Calls to creation rules
					var entry = generate_entry(accelParams[i]);
					
					if (entry)
						entries.push(entry);
				}
				
				if (!entries)
					return;
				
				// Put it all together into one language entry
				var newtext = entries_to_text(entries);
				
				if (!newtext)
					return;
				
				newtext = "== " + langname + " ==\n\n" + newtext;
				
				// Does the page already exist?
				if (textbox.value)
				{
					var langsection_regex = /^==([^=\n]+)==$/mg;
					var match;
					
					// 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;
					}
					
					if (match === null)
						// We found no language that our section should go before, so insert it at the end.
						textbox.value += "\n\n----\n\n" + 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);
				}
				else
				{
					textbox.value = newtext;
					summary.value = "สร้างหน้าคำผันจาก [[" + lemma + "]]";
				}
			}
		);
	}
});


// Exception class
function PreloadTextError(message)
{
	this.name = "PreloadTextError";
	this.message = message;
}

PreloadTextError.prototype = new Error();
PreloadTextError.prototype.constructor = PreloadTextError;


function get_language_name(link)
{
	var node = link;
	
	while (node)
	{
		if (node.nodeType == 1)
		{
			if (node.nodeName.match(/^[hH]2$/))
				return $(node).find(".mw-headline").text().replace(/^[1-9.]* /, "");
			else if (node.className == "languageContainer")  // TabbedLanguages support
				return node.id.replace(/container$/, "");
		}
		
		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?");
}


function get_part_of_speech(link)
{
	// Acceleration can be added to inflection tables too.
	// This tells the search script to skip headers with these names.
	var skipheaders = ["รูปแบบอื่น", "คำตรงข้าม", "การผันรูป", "การผันรูป", "ลูกคำ", 
		"inflection", "การกลายรูป", "คำที่เกี่ยวข้อง", "การผันรูป", "คำแปลภาษาอื่น", "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?");
}


function entries_to_text(entries)
{
	var entries_new = [];
	
	// Merge multiple entries into one if they differ only in the definition
	for (var i = 0; i < entries.length; ++i)
	{
		if (entries_new.length > 0 &&
			entries[i].pronunc == entries_new[entries_new.length-1].pronunc &&
			entries[i].pos_header == entries_new[entries_new.length-1].pos_header &&
			entries[i].head == entries_new[entries_new.length-1].head &&
			entries[i].inflection == entries_new[entries_new.length-1].inflection &&
			entries[i].declension == entries_new[entries_new.length-1].declension &&
			entries[i].conjugation == entries_new[entries_new.length-1].conjugation)
		{
			var params1 = entries_new[entries_new.length-1].def.match(/^{{inflection of\|([^{}]+)}}$/);
			var params2 = entries[i].def.match(/^{{inflection of\|([^{}]+)}}$/);
			
			entries_new[entries_new.length-1].def = entries_new[entries_new.length-1].def + "\n# " + entries[i].def;
			
			// Do some extra-special merging with "inflection of"
			if (params1 && params2)
			{
				// Find the last unnamed parameter of the first template
				params1 = params1[1].split("|");
				var lastNumberedIndex;
				
				for (var j = 0; j < params1.length; ++j)
				{
					if (params1[j].indexOf("=") === -1)
						lastNumberedIndex = j;
				}
				
				// Add grammar tags of the second template
				params2 = params2[1].split("|");
				var tags = [];
				var n = 0;
				
				for (var j = 0; j < params2.length; ++j)
				{
					if (params2[j].indexOf("=") === -1)
					{
						++n;
						
						// Skip the first two unnamed parameters,
						// which don't indicate grammar tags
						if (n < 3)
							continue;
						
						// Now append the tags
						tags.push(params2[j]);
						
					}
				}
				
				// Add the new parameters after the existing ones
				params1[lastNumberedIndex] += "|;|" + tags.join("|");
				entries_new[entries_new.length-1].def = "{{inflection of|" + params1.join("|") + "}}";
			}
		}
		else
		{
			entries_new.push(entries[i]);
		}
	}
	
	for (var i = 0; i < entries_new.length; ++i)
	{
		var entry = entries_new[i];
		
		entry =
			(entry.etym ? "=== รากศัพท์ ===\n" + entry.etym + "\n\n" : "") +
			(entry.pronunc ? "=== การออกเสียง ===\n" + entry.pronunc + "\n\n" : "") +
			"=== " + entry.pos_header + " ===\n" +
			entry.head + "\n\n" +
			"# " + entry.def +
			(entry.inflection ? "\n\n==== การผันรูป ====\n" + entry.inflection : "") +
			(entry.declension ? "\n\n==== การผันรูป ====\n" + entry.declension : "") +
			(entry.conjugation ? "\n\n==== การผันรูป ====\n" + entry.conjugation : "");
		
		entries_new[i] = entry;
	}
	
	return entries_new.join("\n\n");
}