45,333
edits
(Created page with "local export = {} local m_links = require("Module:links") local m_languages = require("Module:languages") local function format_list_items(items, lang) local result = {}...") |
No edit summary |
||
(4 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
local m_links = require("Module:links") | local m_links = require("Module:links") | ||
local m_languages = require("Module:languages") | local m_languages = require("Module:languages") | ||
local m_table = require("Module:table") | |||
local function format_list_items(items, lang) | local function format_list_items(items, lang, sc) | ||
local result = {} | local result = {} | ||
for | local function term_already_linked(term) | ||
if | -- FIXME: "<span" is an ugly hack to prevent double-linking of terms already run through {{l|...}}: | ||
item = m_links.full_link | -- [[Thread:User talk:CodeCat/MewBot adding lang to column templates]] | ||
return term:find("<span") | |||
end | |||
for _, item in ipairs(items) do | |||
if type(item) == "table" then | |||
local link = term_already_linked(item.term.term) and item.term.term or m_links.full_link(item.term) | |||
if item.q then | |||
link = require("Module:qualifier").format_qualifier(item.q) .. " " .. link | |||
end | |||
if item.qq then | |||
link = link .. " " .. require("Module:qualifier").format_qualifier(item.qq) | |||
end | |||
item = link | |||
elseif lang and not term_already_linked(item) then | |||
item = m_links.full_link {lang = lang, term = item, sc = sc} | |||
end | end | ||
result | table.insert(result, '\n* ' .. item) | ||
end | end | ||
return table.concat(result) | return table.concat(result) | ||
end | end | ||
Line 36: | Line 51: | ||
error("expected table, got " .. type(args)) | error("expected table, got " .. type(args)) | ||
end | end | ||
args.class = args.class or "derivedterms" | args.class = args.class or "derivedterms" | ||
args.column_count = args.column_count or 1 | args.column_count = args.column_count or 1 | ||
args.toggle_category = args.toggle_category or "derived terms" | args.toggle_category = args.toggle_category or "derived terms" | ||
local output = {} | local output = {} | ||
if args.header then | if args.header then | ||
if args.format_header then | if args.format_header then | ||
Line 53: | Line 68: | ||
end | end | ||
table.insert(output, (column_header:gsub('{{{(.-)}}}', args))) | table.insert(output, (column_header:gsub('{{{(.-)}}}', args))) | ||
if args.alphabetize then | if args.alphabetize then | ||
require("Module:collation").sort(args.content, args.lang) | local function keyfunc(item) | ||
if type(item) == "table" then | |||
item = item.term.term | |||
end | |||
return item | |||
end | |||
require("Module:collation").sort(args.content, args.lang, keyfunc) | |||
end | end | ||
table.insert(output, format_list_items(args.content, args.lang)) | table.insert(output, format_list_items(args.content, args.lang, args.sc)) | ||
table.insert(output, '</div>') | table.insert(output, '</div>') | ||
if args.collapse then | if args.collapse then | ||
table.insert(output, button .. '</div>') | table.insert(output, button .. '</div>') | ||
end | end | ||
return table.concat(output) | return table.concat(output) | ||
end | end | ||
Line 77: | Line 98: | ||
args.collapse, args.class, args.header, args.column_width, | args.collapse, args.class, args.header, args.column_width, | ||
args.line_start, args.lang = ... | args.line_start, args.lang = ... | ||
args.format_header = true | args.format_header = true | ||
return export.create_list(args) | return export.create_list(args) | ||
end | end | ||
function export. | local param_mods = {"t", "alt", "tr", "ts", "pos", "lit", "id", "sc", "g", "q", "qq"} | ||
local param_mod_set = m_table.listToSet(param_mods) | |||
function export.display_from(column_args, list_args) | |||
local iparams = { | local iparams = { | ||
["class"] = {}, | ["class"] = {}, | ||
Line 105: | Line 129: | ||
["toggle_category"] = {}, | ["toggle_category"] = {}, | ||
} | } | ||
local frame_args = require("Module:parameters").process( | local frame_args = require("Module:parameters").process(column_args, iparams, nil, "columns", "display_from") | ||
local compat = frame_args["lang"] or list_args["lang"] | |||
local compat = frame_args["lang"] or | |||
local lang_param = compat and "lang" or 1 | local lang_param = compat and "lang" or 1 | ||
local columns_param = compat and 1 or 2 | local columns_param = compat and 1 or 2 | ||
Line 118: | Line 141: | ||
[columns_param] = not frame_args["columns"] and {required = true, default = 2} or nil, | [columns_param] = not frame_args["columns"] and {required = true, default = 2} or nil, | ||
[first_content_param] = {list = true}, | [first_content_param] = {list = true}, | ||
["title"] = {}, | ["title"] = {}, | ||
["collapse"] = {type = "boolean"}, | ["collapse"] = {type = "boolean"}, | ||
["sort"] = {type = "boolean"}, | ["sort"] = {type = "boolean"}, | ||
["sc"] = {}, | |||
} | } | ||
local args = require("Module:parameters").process( | local args = require("Module:parameters").process(list_args, params, nil, "columns", "display_from") | ||
local lang = frame_args["lang"] or args[lang_param] | local lang = frame_args["lang"] or args[lang_param] | ||
lang = m_languages.getByCode(lang) | lang = m_languages.getByCode(lang, lang_param) | ||
local sc = args["sc"] and require("Module:scripts").getByCode(sc, "sc") or nil | |||
local sort = frame_args["sort"] | local sort = frame_args["sort"] | ||
if args["sort"] ~= nil then | if args["sort"] ~= nil then | ||
Line 137: | Line 163: | ||
collapse = args["collapse"] | collapse = args["collapse"] | ||
end | end | ||
local put | |||
for i, item in ipairs(args[first_content_param]) do | |||
-- Parse off an initial language code (e.g. 'la:minūtia' or 'grc:[[σκῶρ|σκατός]]'). Don't parse if there's a spac | |||
-- after the colon (happens e.g. if the user uses {{desc|...}} inside of {{col}}, grrr ...). | |||
local termlang, actual_term = item:match("^([A-Za-z._-]+):([^ ].*)$") | |||
-- Make sure that only real language codes are handled as language links, so as to not catch interwiki | |||
-- or namespaces links. | |||
if termlang and ( | |||
mw.loadData("Module:languages/code to canonical name")[termlang] or | |||
mw.loadData("Module:etymology languages/code to canonical name")[termlang] | |||
) then | |||
-- -1 since i is one-based | |||
termlang = m_languages.getByCode(termlang, first_content_param + i - 1, "allow etym") | |||
item = actual_term | |||
else | |||
termlang = lang | |||
end | |||
local termobj = {term = {lang = termlang, sc = sc}} | |||
-- Check for inline modifier, e.g. מרים<tr:Miryem>. But exclude HTML entry with <span ...>, <i ...>, <br/> or | |||
-- similar in it, caused by wrapping an argument in {{l|...}}, {{af|...}} or similar. Basically, all tags of | |||
-- the sort we parse here should consist of a less-than sign, plus letters, plus a colon, e.g. <tr:...>, so if | |||
-- we see a tag on the outer level that isn't in this format, we don't try to parse it. The restriction to the | |||
-- outer level is to allow generated HTML inside of e.g. qualifier tags, such as foo<q:similar to {{m|fr|bar}}>. | |||
if item:find("<") and not item:find("^[^<]*<[a-z]*[^a-z:]") then | |||
if not put then | |||
put = require("Module:parse utilities") | |||
end | |||
local run = put.parse_balanced_segment_run(item, "<", ">") | |||
local orig_param = first_content_param + i - 1 | |||
local function parse_err(msg) | |||
error(msg .. ": " .. orig_param .. "= " .. table.concat(run)) | |||
end | |||
termobj.term.term = run[1] | |||
for j = 2, #run - 1, 2 do | |||
if run[j + 1] ~= "" then | |||
parse_err("Extraneous text '" .. run[j + 1] .. "' after modifier") | |||
end | |||
local modtext = run[j]:match("^<(.*)>$") | |||
if not modtext then | |||
parse_err("Internal error: Modifier '" .. modtext .. "' isn't surrounded by angle brackets") | |||
end | |||
local prefix, arg = modtext:match("^([a-z]+):(.*)$") | |||
if not prefix then | |||
parse_err("Modifier " .. run[j] .. " lacks a prefix, should begin with one of '" .. | |||
table.concat(param_mods, ":', '") .. ":'") | |||
end | |||
if param_mod_set[prefix] then | |||
local obj_to_set | |||
if prefix == "q" or prefix == "qq" then | |||
obj_to_set = termobj | |||
else | |||
obj_to_set = termobj.term | |||
end | |||
if prefix == "t" then | |||
prefix = "gloss" | |||
elseif prefix == "g" then | |||
prefix = "genders" | |||
arg = mw.text.split(arg, ",") | |||
elseif prefix == "sc" then | |||
arg = require("Module:scripts").getByCode(arg, orig_param .. ":sc") | |||
end | |||
if obj_to_set[prefix] then | |||
parse_err("Modifier '" .. prefix .. "' occurs twice, second occurrence " .. run[j]) | |||
end | |||
obj_to_set[prefix] = arg | |||
else | |||
parse_err("Unrecognized prefix '" .. prefix .. "' in modifier " .. run[j]) | |||
end | |||
end | |||
else | |||
termobj.term.term = item | |||
end | |||
args[first_content_param][i] = termobj | |||
end | |||
return export.create_list { column_count = frame_args["columns"] or args[columns_param], | return export.create_list { column_count = frame_args["columns"] or args[columns_param], | ||
content = args[first_content_param], | content = args[first_content_param], | ||
Line 144: | Line 247: | ||
collapse = collapse, | collapse = collapse, | ||
toggle_category = frame_args["toggle_category"], | toggle_category = frame_args["toggle_category"], | ||
class = frame_args["class"], lang = lang, format_header = true } | class = frame_args["class"], lang = lang, sc = sc, format_header = true } | ||
end | end | ||
function export.display(frame) | |||
return export.display_from(frame.args, frame:getParent().args) | |||
end | |||
-- A version of col which substs any automatically generated forms in order to save memory (e.g. for Chinese). | |||
function export.generated_forms(frame) | |||
local column_args, list_args = frame.args, frame:getParent().args | |||
local iparams = { | |||
["columns"] = {type = "number"}, | |||
["name"] = {required = true}, | |||
["toggle_category"] = {}, | |||
} | |||
local frame_args = require("Module:parameters").process(column_args, iparams, nil, "columns", "generated_forms") | |||
local first_content_param = 2 + (frame_args["columns"] and 0 or 1) | |||
frame_args["name"] = frame_args["columns"] and frame_args["name"] .. frame_args["columns"] or frame_args["name"] | |||
local params = { | |||
[1] = {required = true, default = "und"}, | |||
[2] = not frame_args["columns"] and {required = true, default = 2} or nil, | |||
[first_content_param] = {list = true}, | |||
["title"] = {}, | |||
["collapse"] = {type = "boolean"}, | |||
["sort"] = {type = "boolean"}, | |||
["sc"] = {}, | |||
} | |||
local args = require("Module:parameters").process(list_args, params, nil, "columns", "generated_forms") | |||
local lang = args[1] | |||
lang = m_languages.getByCode(lang, lang_param) | |||
args["sc"] = args["sc"] or "" | |||
if sc and sc ~= "" then | |||
sc = require "Module:scripts".getByCode(sc) | |||
or error("|sc= does not contain a valid script code") | |||
end | |||
args[2] = args[2] or "" | |||
args["title"] = args["title"] or "" | |||
args["collapse"] = args["collapse"] or "" | |||
args["sort"] = args["sort"] or "" | |||
local items = {} | |||
for i, item in ipairs(args[first_content_param]) do | |||
if item:find("<") and not item:find("^[^<]*<[a-z]*[^a-z:]") then | |||
item = item:gsub("^([^<]*)(<[a-z]*[a-z:])", function(m1, m2) | |||
return table.concat(lang:generateForms(m1), "//") | |||
end) | |||
else | |||
item = table.concat(lang:generateForms(item), "//") | |||
end | |||
table.insert(items, item) | |||
end | |||
for k, arg in pairs(args) do | |||
if type(arg) == "string" then | |||
if arg ~= "" then | |||
if type(k) == "string" then | |||
args[k] = k .. "=" .. args[k] .. "|" | |||
else | |||
args[k] = args[k] .. "|" | |||
end | |||
end | |||
elseif type(arg) == "boolean" then | |||
args[k] = k .. "=1|" | |||
end | |||
end | |||
local prefix = "{{" .. frame_args["name"] .. "|" .. args[1] .. args["sc"] | |||
prefix = not frame_args["columns"] and prefix .. args[2] or prefix | |||
return prefix .. args["title"] .. args["collapse"] .. args["sort"] .. table.concat(items, "|") .. "}}" | |||
end | |||
return export | return export |