Module:Sort definition list

Lua
CodeDiscussionLinksLink count SubpagesDocumentationTestsResultsSandboxLive code All modules

Module that defines a function used to sort alphabetically by defined term a Mediawiki definition list.

Useful especially in a translated page, when the terms are translated in different languages and the alphabetical order is not the same each time.


Example usage :

{{#invoke:Sort definition list|sort_definition_list|
;zzz : sample definition 1
;bbb : sample definition 2
;aaa : sample definition 3
;jjj : sample definition 4
;[[Special:Random|A random wikipage]] : an example of text within a link that should land at first item '''aaa'''
}}
A random wikipage
an example of text within a link that should land at first item aaa
aaa
sample definition 3
bbb
sample definition 2
jjj
sample definition 4
zzz
sample definition 1


Functions

edit
sort_definition_list
Main function, to be called from a template, see example above.

Utilities

edit
find_dl_colon
To be used on a list of string, supposed to be the splitting of a string at each colon. Returns the guess for the colon number who actually split the definition and the definee. All colon appearing as pagename in wikilinks are to be ignored.
strip_wikilink
removes the links keeping only their text, and some wikimarkup, to sort by the text the user actually see.
split_wikitext_dl
return a map with definee as keys and the corresponding definitions as values
("zzz", "bbb", "aaa", "jjj") are the keys in our example

Code

local p = {}

-- will not work if there is links on links



--=p.find_dl_colon(mw.text.split("[[plop:bidou]]:plop", ":"))
--2
--=p.find_dl_colon(mw.text.split("plop:bidou", ":"))
--1
--=p.find_dl_colon(mw.text.split("[[plop:bidou:zoz]] a [[plop:p]] :plop", ":"))
--4

function p.find_dl_colon(definee_def, index, internalindex)
	index = index or 1
	internalindex = internalindex or 1
	
	while internalindex do
		internalindex = mw.ustring.find(definee_def[index], "%[%[", search)
		if internalindex then
			local closeindex = mw.ustring.find(definee_def[index], "%]%]", internalindex)
			while not closeindex do 
				index = index + 1
				internalindex = 1
				if index > #definee_def then
					error("unclosed link in a definition of the definition list")
				end
				closeindex = mw.ustring.find(definee_def[index], "%]%]", internalindex)
			end
			internalindex = closeindex
		end
	end
	return index
end

function p.split_wikitext_dl(wikistring)
	local dlmap = {}
	mw.log("")
	for k, val in ipairs(mw.text.split(mw.text.trim(wikistring), "\n;")) do
		local definee_definition 
		if k == 1 then
			definee_definition = mw.text.split(mw.text.trim(val):sub(2), ":")
		else
			definee_definition = mw.text.split(val, ":")
		end

		local colon_dl = p.find_dl_colon(definee_definition)
		dlmap[mw.text.trim(table.concat(definee_definition, ":", 1, colon_dl))] = table.concat(definee_definition, ":", colon_dl + 1)
	end
	return dlmap
end

local function getKeysSorted(tbl, sortFunction)
  local keys = {}
  for key in pairs(tbl) do
    table.insert(keys, key)
  end

  table.sort(keys, function(a, b)
    return sortFunction(a, b)
  end)

  return keys
end

local function strip_tags(htmlstring)
	return mw.ustring.gsub(htmlstring, "<.*>", "")
end

local function strip_wikilink(wikistring)
	local str = mw.ustring.gsub(wikistring, "%[%[[^|]*|", "")
	str = mw.ustring.gsub(str, "%]%]", "")
	str = mw.ustring.gsub(str, "'''", "")
	return mw.text.killMarkers(str)
end

local function compare_defs(a, b)
	return strip_wikilink(a) < strip_wikilink(b)
end

p.sort_definition_list = function(frame)
	local defs = p.split_wikitext_dl(frame.args[1])
	local res = ""
	for k, key in pairs(getKeysSorted(defs, compare_defs)) do
		mw.log("%>" .. k)
		mw.log("%=>" .. key .. " (" .. strip_wikilink(key) .. ")") 
		res = res .. ";" .. key .. ":" .. defs[key] .. "\n"
	end
	return res .. "\n" 
end


local testwiki = ";plop : bidou\n;plop [[a:p|bé]] : bidou\n;plop [[a:p|bé]] [[a:p|bé]] : bidou 2\n"


function p.test()

	local frame = {}
	frame.args = {}
	frame.args[1] = testwiki
	mw.log(p.sort_definition_list(frame))
	
	mw.log("------------------------------------------------------------------------")
	mw.logObject(p.split_wikitext_dl(testwiki))
end



return p