48,403
edits
No edit summary |
No edit summary |
||
| Line 10: | Line 10: | ||
[[Module:scripts]] | [[Module:scripts]] | ||
[[Module:languages]] and its submodules | [[Module:languages]] and its submodules | ||
[[Module: | [[Module:gender and number]] | ||
[[Module:debug/track]] | |||
]=] | ]=] | ||
local anchors_module = "Module:anchors" | local anchors_module = "Module:anchors" | ||
local gender_and_number_module = "Module: | local debug_track_module = "Module:debug/track" | ||
local gender_and_number_module = "Module:gender and number" | |||
local languages_module = "Module:languages" | local languages_module = "Module:languages" | ||
local load_module = "Module:load" | local load_module = "Module:load" | ||
| Line 47: | Line 49: | ||
anchor_encode = require(memoize_module)(mw.uri.anchorEncode, true) | anchor_encode = require(memoize_module)(mw.uri.anchorEncode, true) | ||
return anchor_encode(...) | return anchor_encode(...) | ||
end | |||
local function debug_track(...) | |||
debug_track = require(debug_track_module) | |||
return debug_track(...) | |||
end | end | ||
| Line 158: | Line 165: | ||
umatch = require(string_utilities_module).match | umatch = require(string_utilities_module).match | ||
return umatch(...) | return umatch(...) | ||
end | |||
local m_headword_data | |||
local function get_headword_data() | |||
m_headword_data = load_data("Module:headword/data") | |||
return m_headword_data | |||
end | |||
local function track(page, code) | |||
local tracking_page = "links/" .. page | |||
debug_track(tracking_page) | |||
if code then | |||
debug_track(tracking_page .. "/" .. code) | |||
end | |||
end | end | ||
| Line 215: | Line 236: | ||
--[==[Takes an input and splits on a double slash (taking account of escaping backslashes).]==] | --[==[Takes an input and splits on a double slash (taking account of escaping backslashes).]==] | ||
function export.split_on_slashes(text) | function export.split_on_slashes(text) | ||
if text:find("\\", nil, true) then | |||
track("escaped", "split_on_slashes") | |||
end | |||
text = split(escape(text, "//"), "//", true) or {} | text = split(escape(text, "//"), "//", true) or {} | ||
for i, v in ipairs(text) do | for i, v in ipairs(text) do | ||
| Line 278: | Line 302: | ||
--[==[Takes a link target and outputs the actual target and the fragment (if any).]==] | --[==[Takes a link target and outputs the actual target and the fragment (if any).]==] | ||
function export.get_fragment(text) | function export.get_fragment(text) | ||
if text:find("\\", nil, true) then | |||
track("escaped", "get_fragment") | |||
end | |||
-- If there are no embedded links, process input. | -- If there are no embedded links, process input. | ||
local open = find(text, "[[", nil, true) | local open = find(text, "[[", nil, true) | ||
| Line 294: | Line 321: | ||
end | end | ||
--[==[ | --[==[ | ||
Given a link target as passed to `full_link()`, get the actual page that the target refers to. This removes | Given a link target as passed to `full_link()`, get the actual page that the target refers to. This removes | ||
bold, italics, strip markets and HTML; calls `makeEntryName()` for the language in question; converts targets | bold, italics, strip markets and HTML; calls `makeEntryName()` for the language in question; converts targets | ||
beginning with `*` to the Reconstruction namespace; and converts appendix-constructed languages to the Appendix | beginning with `*` to the Reconstruction namespace; and converts appendix-constructed languages to the Appendix | ||
namespace. Returns up to three values: the page, the original target minus any anti-asterisk !! | namespace. Returns up to three values: | ||
value `true` if the target had a backslash-escaped * in it. | # the actual page to link to, or {nil} to not link to anything; | ||
# how the target should be displayed as, if the user didn't explicitly specify any display text; generally the | |||
same as the original target, but minus any anti-asterisk !!; | |||
# the value `true` if the target had a backslash-escaped * in it (FIXME: explain this more clearly). | |||
]==] | ]==] | ||
function export.get_link_page_with_auto_display(target, lang, sc, plain) | function export.get_link_page_with_auto_display(target, lang, sc, plain) | ||
| Line 307: | Line 336: | ||
if not target then | if not target then | ||
return nil | return nil | ||
elseif target:find("\\", nil, true) then | |||
track("escaped", "get_link_page") | |||
end | end | ||
| Line 312: | Line 343: | ||
if target:sub(1, 1) == ":" then | if target:sub(1, 1) == ":" then | ||
track("initial colon") | |||
-- FIXME, the auto_display (second return value) should probably remove the colon | -- FIXME, the auto_display (second return value) should probably remove the colon | ||
return target:sub(2), orig_target | return target:sub(2), orig_target | ||
| Line 363: | Line 395: | ||
-- If the link contains unexpanded template parameters, then don't create a link. | -- If the link contains unexpanded template parameters, then don't create a link. | ||
if target:match("{{{.-}}}") then | if target:match("{{{.-}}}") then | ||
-- FIXME: Should we return the original target as the default display value (second return value)? | |||
return nil | return nil | ||
end | end | ||
-- Link to appendix for reconstructed terms and terms in appendix-only languages. Plain links interpret * literally, however. | -- Link to appendix for reconstructed terms and terms in appendix-only languages. Plain links interpret * | ||
-- literally, however. | |||
if reconstructed == 1 then | if reconstructed == 1 then | ||
if lang:getFullCode() == "und" then | if lang:getFullCode() == "und" then | ||
-- Return the original target as default display value. If we don't do this, we wrongly get | |||
-- [Term?] displayed instead. | |||
return nil, orig_target | |||
end | end | ||
target = "Reconstruction:" .. lang:getFullName() .. "/" .. target | |||
-- Reconstructed languages and substrates require an initial *. | -- Reconstructed languages and substrates require an initial *. | ||
elseif anti_asterisk ~= 1 and (lang:hasType("reconstructed") or lang:getFamilyCode() == "qfa-sub") then | elseif anti_asterisk ~= 1 and (lang:hasType("reconstructed") or lang:getFamilyCode() == "qfa-sub") then | ||
| Line 384: | Line 417: | ||
target = target | target = target | ||
end | end | ||
return target, orig_target, escaped > 0 | return target, orig_target, escaped > 0 | ||
end | end | ||
| Line 415: | Line 446: | ||
-- If the target is "" then it's a link like [[#English]], which refers to the current page. | -- If the target is "" then it's a link like [[#English]], which refers to the current page. | ||
if auto_display == "" then | if auto_display == "" then | ||
auto_display = | auto_display = (m_headword_data or get_headword_data()).pagename | ||
end | end | ||
| Line 479: | Line 510: | ||
if prefix ~= "category" and not (prefix and load_data("Module:data/interwikis")[prefix]) then | if prefix ~= "category" and not (prefix and load_data("Module:data/interwikis")[prefix]) then | ||
if (link.fragment or link.target:sub(-1) == "#") and not plain then | if (link.fragment or link.target:sub(-1) == "#") and not plain then | ||
track("fragment", lang:getFullCode()) | |||
if cats then | if cats then | ||
insert(cats, lang:getFullName() .. " links with manual fragments") | insert(cats, lang:getFullName() .. " links with manual fragments") | ||
| Line 539: | Line 571: | ||
local function check_params_ignored_when_embedded(alt, lang, id, cats) | local function check_params_ignored_when_embedded(alt, lang, id, cats) | ||
if alt then | if alt then | ||
track("alt-ignored") | |||
if cats then | if cats then | ||
insert(cats, lang:getFullName() .. " links with ignored alt parameters") | insert(cats, lang:getFullName() .. " links with ignored alt parameters") | ||
| Line 544: | Line 577: | ||
end | end | ||
if id then | if id then | ||
track("id-ignored") | |||
if cats then | if cats then | ||
insert(cats, lang:getFullName() .. " links with ignored id parameters") | insert(cats, lang:getFullName() .. " links with ignored id parameters") | ||
| Line 684: | Line 718: | ||
term = selective_trim(term) | term = selective_trim(term) | ||
end | end | ||
-- If not, make a link using the parameters. | -- If not, make a link using the parameters. | ||
return make_link({ | return make_link({ | ||
| Line 721: | Line 755: | ||
if type(data) ~= "table" then | if type(data) ~= "table" then | ||
error("The first argument to the function language_link must be a table. See Module:links/documentation for more information.") | error("The first argument to the function language_link must be a table. See Module:links/documentation for more information.") | ||
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then | |||
track("escaped", "language_link") | |||
end | end | ||
| Line 745: | Line 781: | ||
if type(data) ~= "table" then | if type(data) ~= "table" then | ||
error("The first argument to the function plain_link must be a table. See Module:links/documentation for more information.") | error("The first argument to the function plain_link must be a table. See Module:links/documentation for more information.") | ||
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then | |||
track("escaped", "plain_link") | |||
end | end | ||
| Line 764: | Line 802: | ||
if type(data) ~= "table" then | if type(data) ~= "table" then | ||
error("The first argument to the function embedded_language_links must be a table. See Module:links/documentation for more information.") | error("The first argument to the function embedded_language_links must be a table. See Module:links/documentation for more information.") | ||
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then | |||
track("escaped", "embedded_language_links") | |||
end | end | ||
| Line 792: | Line 832: | ||
tag = { '<span class="mention-gloss-double-quote">“</span><span class="mention-gloss">', | tag = { '<span class="mention-gloss-double-quote">“</span><span class="mention-gloss">', | ||
'</span><span class="mention-gloss-double-quote">”</span>' } | '</span><span class="mention-gloss-double-quote">”</span>' } | ||
if type(text) == "string" and text:match("^''[^'].*''$") then | |||
-- Temporary tracking for mention glosses that are entirely italicized or bolded, which is probably | |||
-- wrong. (Note that this will also find bolded mention glosses since they use triple apostrophes.) | |||
track("italicized-mention-gloss", lang and lang:getFullCode() or nil) | |||
end | |||
elseif item_type == "tr" then | elseif item_type == "tr" then | ||
if face == "term" then | if face == "term" then | ||
| Line 804: | Line 849: | ||
elseif item_type == "pos" then | elseif item_type == "pos" then | ||
tag = { '<span class="ann-pos">', '</span>' } | tag = { '<span class="ann-pos">', '</span>' } | ||
elseif item_type == "non-gloss" then | |||
tag = { '<span class="ann-non-gloss">', '</span>' } | |||
elseif item_type == "annotations" then | elseif item_type == "annotations" then | ||
tag = { '<span class="mention-gloss-paren annotation-paren">(</span>', | tag = { '<span class="mention-gloss-paren annotation-paren">(</span>', | ||
| Line 815: | Line 862: | ||
end | end | ||
end | end | ||
local pos_tags | |||
--[==[Formats the annotations that are displayed with a link created by {{code|lua|full_link}}. Annotations are the extra bits of information that are displayed following the linked term, and include things such as gender, transliteration, gloss and so on. | --[==[Formats the annotations that are displayed with a link created by {{code|lua|full_link}}. Annotations are the extra bits of information that are displayed following the linked term, and include things such as gender, transliteration, gloss and so on. | ||
| Line 825: | Line 874: | ||
*:: Gloss that translates the term in the link, or gives some other descriptive information. | *:: Gloss that translates the term in the link, or gives some other descriptive information. | ||
*:; <code class="n">pos</code> | *:; <code class="n">pos</code> | ||
*:: Part of speech of the linked term. If the given argument matches one of the | *:: Part of speech of the linked term. If the given argument matches one of the aliases in `pos_aliases` in [[Module:headword/data]], or consists of a part of speech or alias followed by `f` (for a non-lemma form), expand it appropriately. Otherwise, just show the given text as it is. | ||
*:; <code class="n">ng</code> | |||
*:: Arbitrary non-gloss descriptive text for the link. This should be used in preference to putting descriptive text in `gloss` or `pos`. | |||
*:; <code class="n">lit</code> | *:; <code class="n">lit</code> | ||
*:: Literal meaning of the term, if the usual meaning is figurative or idiomatic. | *:: Literal meaning of the term, if the usual meaning is figurative or idiomatic. | ||
| Line 886: | Line 937: | ||
end | end | ||
pos_tags = pos_tags or | -- Canonicalize part of speech aliases as well as non-lemma aliases like 'nf' or 'nounf' for "noun form". | ||
insert(annotations, export.mark( | pos_tags = pos_tags or (m_headword_data or get_headword_data()).pos_aliases | ||
local pos = pos_tags[data.pos] | |||
if not pos and data.pos:find("f$") then | |||
local pos_form = data.pos:sub(1, -2) | |||
-- We only expand something ending in 'f' if the result is a recognized non-lemma POS. | |||
pos_form = (pos_tags[pos_form] or pos_form) .. " form" | |||
if (m_headword_data or get_headword_data()).nonlemmas[pos_form .. "s"] then | |||
pos = pos_form | |||
end | |||
end | |||
insert(annotations, export.mark(pos or data.pos, "pos")) | |||
end | |||
-- Non-gloss text | |||
if data.ng then | |||
insert(annotations, export.mark(data.ng, "non-gloss")) | |||
end | end | ||
| Line 893: | Line 959: | ||
if data.lit then | if data.lit then | ||
insert(annotations, "literally " .. export.mark(data.lit, "gloss")) | insert(annotations, "literally " .. export.mark(data.lit, "gloss")) | ||
end | |||
-- Provide a hook to insert additional annotations such as nested inflections. | |||
if data.postprocess_annotations then | |||
data.postprocess_annotations { | |||
data = data, | |||
annotations = annotations | |||
} | |||
end | end | ||
| Line 1,015: | Line 1,089: | ||
track_sc = boolean, | track_sc = boolean, | ||
no_nonstandard_sc_cat = boolean, | no_nonstandard_sc_cat = boolean, | ||
fragment = link_fragment | fragment = link_fragment, | ||
id = sense_id, | id = sense_id, | ||
genders = { "gender1", "gender2", ... }, | genders = { "gender1", "gender2", ... }, | ||
| Line 1,022: | Line 1,096: | ||
gloss = gloss, | gloss = gloss, | ||
pos = part_of_speech_tag, | pos = part_of_speech_tag, | ||
ng = non-gloss text, | |||
lit = literal_translation, | lit = literal_translation, | ||
no_alt_ast = boolean, | no_alt_ast = boolean, | ||
accel = {accelerated_creation_tags}, | accel = {accelerated_creation_tags}, | ||
interwiki = interwiki, | interwiki = interwiki, | ||
pretext = "text_at_beginning" or nil, | |||
posttext = "text_at_end" or nil, | |||
q = { "left_qualifier1", "left_qualifier2", ...} or "left_qualifier", | q = { "left_qualifier1", "left_qualifier2", ...} or "left_qualifier", | ||
qq = { "right_qualifier1", "right_qualifier2", ...} or "right_qualifier", | qq = { "right_qualifier1", "right_qualifier2", ...} or "right_qualifier", | ||
l = { "left_label1", "left_label2", ...}, | |||
ll = { "right_label1", "right_label2", ...}, | |||
a = { "left_accent_qualifier1", "left_accent_qualifier2", ...}, | |||
aa = { "right_accent_qualifier1", "right_accent_qualifier2", ...}, | |||
refs = { "formatted_ref1", "formatted_ref2", ...} or { {text = "text", name = "name", group = "group"}, ... }, | refs = { "formatted_ref1", "formatted_ref2", ...} or { {text = "text", name = "name", group = "group"}, ... }, | ||
show_qualifiers = boolean, | |||
} } | } } | ||
Any one of the items in the <code class="n">data</code> table may be {{code|lua|nil}}, but an error will be shown if neither <code class="n">term</code> nor <code class="n">alt</code> nor <code class="n">tr</code> is present. | Any one of the items in the <code class="n">data</code> table may be {{code|lua|nil}}, but an error will be shown if neither <code class="n">term</code> nor <code class="n">alt</code> nor <code class="n">tr</code> is present. | ||
| Line 1,037: | Line 1,119: | ||
* Call <code class="n">[[Module:script utilities#tag_text]]</code> to add the appropriate language and script tags to the term, and to italicize terms written in the Latin script if necessary. Accelerated creation tags, as used by [[WT:ACCEL]], are included. | * Call <code class="n">[[Module:script utilities#tag_text]]</code> to add the appropriate language and script tags to the term, and to italicize terms written in the Latin script if necessary. Accelerated creation tags, as used by [[WT:ACCEL]], are included. | ||
* Generate a transliteration, based on the alt or term arguments, if the script is not Latin and no transliteration was provided. | * Generate a transliteration, based on the alt or term arguments, if the script is not Latin and no transliteration was provided. | ||
* Add the annotations (transliteration, gender, gloss etc.) after the link. | * Add the annotations (transliteration, gender, gloss, etc.) after the link. | ||
* If <code class="n">no_alt_ast</code> is specified, then the alt text does not need to contain an asterisk if the language is reconstructed. This should only be used by modules which really need to allow links to reconstructions that don't display asterisks (e.g. number boxes). | * If <code class="n">no_alt_ast</code> is specified, then the alt text does not need to contain an asterisk if the language is reconstructed. This should only be used by modules which really need to allow links to reconstructions that don't display asterisks (e.g. number boxes). | ||
* If <code class="n">show_qualifiers</code> is specified, left and right qualifiers and references will be displayed. (This is | * If <code class="n">pretext</code> or <code class="n">posttext</code> is specified, this is text to (respectively) prepend or append to the output, directly before processing qualifiers, labels and references. This can be used to add arbitrary extra text inside of the qualifiers, labels and references. | ||
* If <code class="n">show_qualifiers</code> is specified or the `show_qualifiers` field is set, left and right qualifiers, accent qualifiers, labels and references will be displayed, otherwise they will be ignored. (This is because a fair amount of code stores qualifiers, labels and/or references in these fields and displays them itself, rather than expecting {{code|lua|full_link()}} to display them.)]==] | |||
function export.full_link(data, face, allow_self_link, show_qualifiers) | function export.full_link(data, face, allow_self_link, show_qualifiers) | ||
if data.cats ~= nil then | |||
track("cats") | |||
end | |||
-- Prevent data from being destructively modified. | -- Prevent data from being destructively modified. | ||
local data = shallow_copy(data) | local data = shallow_copy(data) | ||
| Line 1,047: | Line 1,133: | ||
error("The first argument to the function full_link must be a table. " | error("The first argument to the function full_link must be a table. " | ||
.. "See Module:links/documentation for more information.") | .. "See Module:links/documentation for more information.") | ||
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then | |||
track("escaped", "full_link") | |||
end | end | ||
| Line 1,171: | Line 1,259: | ||
elseif (data.term[1] or data.alt[1]) and data.sc[1]:isTransliterated() then | elseif (data.term[1] or data.alt[1]) and data.sc[1]:isTransliterated() then | ||
-- Track whenever there is manual translit. The categories below like 'terms with redundant transliterations' | |||
-- aren't sufficient because they only work with reference to automatic translit and won't operate at all in | |||
-- languages without any automatic translit, like Persian and Hebrew. | |||
if data.tr[1] then | |||
local full_code = lang:getFullCode() | |||
track("manual-tr", full_code) | |||
end | |||
if not nevercalltr then | if not nevercalltr then | ||
| Line 1,228: | Line 1,323: | ||
insert(output, export.format_link_annotations(data, face)) | insert(output, export.format_link_annotations(data, face)) | ||
local categories = | if data.pretext then | ||
insert(output, 1, data.pretext) | |||
end | |||
if data.posttext then | |||
insert(output, data.posttext) | |||
end | |||
local categories = cats[1] and format_categories(cats, lang, "-", nil, nil, data.sc) or "" | |||
output = concat(output) | output = concat(output) | ||
if show_qualifiers then | if show_qualifiers or data.show_qualifiers then | ||
output = add_qualifiers_and_refs_to_term(data, output) | output = add_qualifiers_and_refs_to_term(data, output) | ||
end | end | ||
| Line 1,286: | Line 1,388: | ||
if type(link) ~= "string" then | if type(link) ~= "string" then | ||
error("The first argument to section_link was a " .. type(link) .. ", but it should be a string.") | error("The first argument to section_link was a " .. type(link) .. ", but it should be a string.") | ||
elseif link:find("\\", nil, true) then | |||
track("escaped", "section_link") | |||
end | end | ||