Module:labels: Difference between revisions

No edit summary
use large_pages in Module:headword/data instead of having it here
Line 3: Line 3:
export.lang_specific_data_list_module = "Module:labels/data/lang"
export.lang_specific_data_list_module = "Module:labels/data/lang"
export.lang_specific_data_modules_prefix = "Module:labels/data/lang/"
export.lang_specific_data_modules_prefix = "Module:labels/data/lang/"
local m_lang_specific_data = mw.loadData(export.lang_specific_data_list_module)
 
local load_module = "Module:load"
local load_module = "Module:load"
local parse_utilities_module = "Module:parse utilities"
local parse_utilities_module = "Module:parse utilities"
local string_utilities_module = "Module:string utilities"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local utilities_module = "Module:utilities"
local insert = table.insert
local require_when_needed = require("Module:require when needed")
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local dump = mw.dumpObject
local m_lang_specific_data = mw.loadData(export.lang_specific_data_list_module)
local m_table = require_when_needed("Module:table")


--[==[ intro:
--[==[ intro:
Line 41: Line 48:
local force_cat = false
local force_cat = false


local SUBPAGENAME = mw.title.getCurrentTitle().subpageText
local m_headword_data = mw.loadData("Module:headword/data")
local SUBPAGENAME = m_headword_data.pagename


-- Disable tracking on heavy pages to save time.
-- Disable tracking on heavy pages to save time.
local pages_where_tracking_is_disabled = {
local pages_where_tracking_is_disabled = m_headword_data.large_pages
-- pages that consistently hit timeouts
 
["a"] = true,
-- Add tracking category for PAGE. The tracking category linked to is [[Wiktionary:Tracking/labels/PAGE]].
-- pages that sometimes hit timeouts
-- We also add to [[Wiktionary:Tracking/labels/PAGE/LANGCODE]] and [[Wiktionary:Tracking/labels/PAGE/MODE]] if
["de"] = true,
-- LANGCODE and/or MODE given.
["i"] = true,
local function track(page, langcode, mode)
["и"] = true,
if pages_where_tracking_is_disabled[SUBPAGENAME] then
[""] = true,
return true
[""] = true,
end
["月"] = true,
-- avoid including links in pages (may cause error)
}
page = page:gsub("%[", "("):gsub("%]", ")"):gsub("|", "!")
require("Module:debug/track")("labels/" .. page)
if langcode then
require("Module:debug/track")("labels/" .. page .. "/" .. langcode)
end
if mode then
require("Module:debug/track")("labels/" .. page .. "/" .. mode)
end
-- We don't currently add a tracking label for both langcode and mode to reduce the total number of labels, to
-- save some memory.
return true
end


local function ucfirst(txt)
local function ucfirst(txt)
Line 79: Line 98:
local allowed_values = {}
local allowed_values = {}
for key, _ in pairs(mode_to_outer_class) do
for key, _ in pairs(mode_to_outer_class) do
table.insert(allowed_values, "'" .. key .. "'")
insert(allowed_values, "'" .. key .. "'")
end
end
table.sort(allowed_values)
table.sort(allowed_values)
Line 90: Line 109:
local mode_prefix = mode_to_property_prefix[mode]
local mode_prefix = mode_to_property_prefix[mode]
return mode_prefix and labdata[mode_prefix .. prop] or labdata[prop]
return mode_prefix and labdata[mode_prefix .. prop] or labdata[prop]
end
local function check_type(label, lang, prop, value, expected_types)
if value == nil or expected_types == nil then
return value
end
if type(expected_types) ~= "table" then
expected_types = {expected_types}
end
local valtype = type(value)
local matches = false
for _, expected_type in ipairs(expected_types) do
if type(expected_type) == "string" then
if valtype == expected_type then
matches = true
break
end
elseif value == expected_type then
matches = true
break
end
end
if not matches then
local function join_untagged_or(elements)
return m_table.serialCommaJoin(elements, {conj = "or", dontTag = true})
end
local quoted_types = {}
local quoted_values = {}
for _, expected_type in ipairs(expected_types) do
if type(expected_type) == "string" then
insert(quoted_types, "'" .. expected_type .. "'")
else
insert(quoted_values, "'" .. dump(expected_type) .. "'")
end
end
local possible_matches = {}
if quoted_types[1] then
insert(possible_matches, ("be of type%s %s"):format(
quoted_types[2] and "s" or "", join_untagged_or(quoted_types)))
end
if quoted_values[1] then
insert(possible_matches, ("have  the value%s %s"):format(
quoted_values[2] and "s" or "", join_untagged_or(quoted_values)))
end
error(("Internal error: For label '%s', langcode '%s', property '%s' should %s but is of type '%s' with value %s"):format(
label, lang and lang:getCode() or "UNKNOWN", prop, join_untagged_or(possible_matches), valtype, dump(value)))
end
end
end


Line 110: Line 177:
function export.get_langs_to_extract_wikipedia_articles_from_wikidata(lang)
function export.get_langs_to_extract_wikipedia_articles_from_wikidata(lang)
local wikipedia_langs = {}
local wikipedia_langs = {}
table.insert(wikipedia_langs, "en")
insert(wikipedia_langs, "en")
if lang then
if lang then
local article_lang = lang
local article_lang = lang
Line 117: Line 184:
local wmcodes = article_lang:getWikimediaLanguageCodes()
local wmcodes = article_lang:getWikimediaLanguageCodes()
for _, wmcode in ipairs(wmcodes) do
for _, wmcode in ipairs(wmcodes) do
table.insert(wikipedia_langs, wmcode)
insert(wikipedia_langs, wmcode)
end
end
end
end
Line 125: Line 192:
local family, wp_lang = unpack(family_to_wp_lang)
local family, wp_lang = unpack(family_to_wp_lang)
if lang:inFamily(family) then
if lang:inFamily(family) then
table.insert(wikipedia_langs, wp_lang)
insert(wikipedia_langs, wp_lang)
end
end
end
end
Line 156: Line 223:
end
end


local function labprop(prop)
local function labprop(prop, expected_types)
return getprop(labdata, mode, prop)
local retval = getprop(labdata, mode, prop)
check_type(canon_label, lang, prop, retval, expected_types)
return retval
end
end
local empty_list = {}
local empty_list = {}
Line 193: Line 262:
end
end


table.insert(categories, cat)
insert(categories, cat)
end
end


Line 229: Line 298:
]==]
]==]
function export.get_submodules(lang)
function export.get_submodules(lang)
local submodules = {}
local submodules = {
"Module:labels/data",
"Module:labels/data/qualifiers",
"Module:labels/data/regional",
"Module:labels/data/topical",
}
if not lang then
return submodules
end


-- get language-specific labels from data module
-- get language-specific labels from data module
local langcode = lang and lang:getFullCode() or nil
local langcode = lang:getFullCode()


if langcode and m_lang_specific_data.langs_with_lang_specific_modules[langcode] then
if m_lang_specific_data.langs_with_lang_specific_modules[langcode] then
-- prefer per-language label in order to pick subvariety labels over regional ones
-- prefer per-language label in order to pick subvariety labels over regional ones
table.insert(submodules, export.lang_specific_data_modules_prefix .. langcode)
insert(submodules, 1, export.lang_specific_data_modules_prefix .. langcode)
end
end
table.insert(submodules, "Module:labels/data")
 
table.insert(submodules, "Module:labels/data/qualifiers")
table.insert(submodules, "Module:labels/data/regional")
table.insert(submodules, "Module:labels/data/topical")
return submodules
return submodules
end
end
Line 261: Line 336:


mode = validate_mode(mode)
mode = validate_mode(mode)
local function labprop(prop)
local function labprop(prop, expected_types)
return getprop(labdata, mode, prop)
local retval = getprop(labdata, mode, prop)
check_type(label, lang, prop, retval, expected_types)
return retval
end
end
deprecated = deprecated or labprop("deprecated")
deprecated = deprecated or labprop("deprecated")
Line 278: Line 355:
end
end


formatted_label = labprop("special_display"):gsub("<(.-)>", add_language_name)
formatted_label = labprop("special_display", "string"):gsub("<(.-)>", add_language_name)
else
else
--[=[
--[=[
If labdata.glossary or labdata.Wikipedia are set to true, there is a glossary definition
We proceed as follows:
with an anchor identical to the label, or a Wikipedia article with a title
1. The display form comes from either (a) the `override_display` variable if set (this happens when
identical to the label.
  the user uses a label like '!British'); (b) the `display` property, if set; or (c) the label iself.
For example, the code
2. If the display form contains a link, use it directly and ignore the other display-related settings.
labels["formal"] = {
  (NOTE: Settings `Wikipedia` and `Wikidata` may still be used on the category page itself, by the
glossary = true,
  category tree code.)
}
3. Otherwise, use one of the other display-related settings, in the following order:
indicates that there is a glossary entry for "formal".
  `glossary` > `Wiktionary` > `Wikipedia` > `Wikidata`. Specifically:
 
  a. If any of the values is equal to `true`, that is equivalent to specifying a string consisting of
Otherwise:
  the canonical label.
* labdata.glossary specifies the anchor in [[Appendix:Glossary]].
  b. If `glossary` is set, it specifies the anchor in [[Appendix:Glossary]].
* labdata.Wiktionary specifies an arbitrary Wiktionary page or page + anchor (e.g. a separate Appendix
  c. If `Wiktionary` is set, it specifies an arbitrary Wiktionary page or page + anchor (e.g. a
  entry).
  separate Appendix entry).
* labdata.Wikipedia specifies an arbitrary Wikipedia article.
  d. If `Wikipedia` is set, it specifies an arbitrary Wikipedia article, or a list of such items (in
* labdata.Wikidata specifies an arbitrary Wikidata item to retrieve a Wikipedia article from, or a list
  this case, we select the first one, but the category tree uses all of them).
  of such items (in this case, we select the first one, but other modules using this info might use all
  e. If `Wikidata` is set, it specifies an arbitrary Wikidata item to retrieve a Wikipedia article from,
  of them). If the item is of the form `wmcode:id`, the Wikipedia article corresponding to `wmcode` is
  or a list of such items (in this case, we select the first one, but the category tree uses all of
  fetched if available. Otherwise, the English-language Wikipedia article is retrieved if available,
  them). If the item is of the form `wmcode:id`, the Wikipedia article corresponding to `id` in the
  falling back to the Wikimedia language(s) corresponding to `lang` and then (in certain cases) to the
  `wmcode`-language Wikipedia is fetched if available. Otherwise, the English-language Wikipedia
  macrolanguage that `lang` is part of.
  article corresponding to `id` is retrieved if available, falling back to the Wikimedia language(s)
  corresponding to `lang` and then (in certain cases) to the macrolanguage that `lang` is part of.


Note that if `mode` is specified, prefixed properties (e.g. "accent_display" for `mode` == "accent",
Note that if `mode` is specified, prefixed properties (e.g. `accent_display` for `mode` == "accent",
"form_display" for `mode` == "form") are checked before the bare equivalent (e.g. "display").
`form_display` for `mode` == "form") are checked before the bare equivalent (e.g. `display`).
]=]
]=]
local display = override_display or labprop("display") or label
local display = override_display or labprop("display", "string") or label


-- There are several 'Foo spelling' labels specially designed for use in the |from= param in
-- There are several 'Foo spelling' labels specially designed for use in the |from= param in
Line 319: Line 397:
formatted_label = display
formatted_label = display
else
else
local glossary = labprop("glossary")
local glossary = labprop("glossary", {"string", true})
local Wiktionary = labprop("Wiktionary")
local Wiktionary = labprop("Wiktionary", {"string", true})
local Wikipedia = labprop("Wikipedia")
local Wikipedia = labprop("Wikipedia", {"string", true, "table"})
local Wikidata = labprop("Wikidata")
local Wikidata = labprop("Wikidata", {"string", true, "table"})
if glossary then
if glossary then
local glossary_entry = type(glossary) == "string" and glossary or label
local glossary_entry = glossary == true and label or glossary
formatted_label = "[[wikt:Appendix:Glossary#" .. glossary_entry .. "|" .. display .. "]]"
formatted_label = "[[Appendix:Glossary#" .. glossary_entry .. "|" .. display .. "]]"
elseif Wiktionary then
elseif Wiktionary then
formatted_label = "[[wikt:" .. Wiktionary .. "|" .. display .. "]]"
local Wiktionary_entry = Wiktionary == true and label or Wiktionary
if Wiktionary == display then
formatted_label = "[[" .. display .. "]]"
else
formatted_label = "[[" .. Wiktionary_entry .. "|" .. display .. "]]"
end
elseif Wikipedia then
elseif Wikipedia then
local Wikipedia_entry = type(Wikipedia) == "string" and Wikipedia or label
if type(Wikipedia) == "table" then
Wikipedia = Wikipedia[1]
end
local Wikipedia_entry = Wikipedia == true and label or Wikipedia
formatted_label = "[[w:" .. Wikipedia_entry .. "|" .. display .. "]]"
formatted_label = "[[w:" .. Wikipedia_entry .. "|" .. display .. "]]"
elseif Wikidata then
elseif Wikidata then
Line 389: Line 475:
   `categories` to be formatted for documentation display.
   `categories` to be formatted for documentation display.
* `nocat`: If true, don't add the label to any categories.
* `nocat`: If true, don't add the label to any categories.
* `force_cat`: Force adding categories even in namespaces that normally exclude them (e.g. userspace and discussion
  pages).
* `notrack`: Disable all tracking for this label.
* `notrack`: Disable all tracking for this label.
* `sort`: Sort key for categorization.
* `already_seen`: An object used to track labels already seen, so they aren't displayed twice. Tracking is according
* `already_seen`: An object used to track labels already seen, so they aren't displayed twice. Tracking is according
   to the display form of the label, so if two labels have the same display form, the second one won't be displayed
   to the display form of the label, so if two labels have the same display form, the second one won't be displayed
Line 422: Line 511:
* `label`: The formatted form of the label. This is what is actually shown to the user. If the label is recognized
* `label`: The formatted form of the label. This is what is actually shown to the user. If the label is recognized
   (found in some module), this will typically be in the form of a link.
   (found in some module), this will typically be in the form of a link.
* `categories`: A list of the categories to add the label to; an empty list of `nocat` was specified.
* `categories`: A list of the categories to add the label to; an empty list if `nocat` was specified.
* `formatted_categories`: A string containing the formatted categories; {nil} if `nocat` or `for_doc` was specified,
* `formatted_categories`: A string containing the formatted categories; {nil} if `nocat` or `for_doc` was specified,
   or if `categories` is empty. Currently will be an empty string if there are categories to format but the namespace is
   or if `categories` is empty. Currently will be an empty string if there are categories to format but the namespace is
Line 496: Line 585:
label = resolved_label or label
label = resolved_label or label
break
break
elseif not data.notrack then
-- Track use of a label that fails the lang restriction.
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/wrong-lang-label]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/wrong-lang-label/LANGCODE]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/wrong-lang-label/LABEL]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/wrong-lang-label/LABEL/LANGCODE]]
track("wrong-lang-label", data_langcode)
track("wrong-lang-label/" .. label, data_langcode)
if resolved_label then
track("wrong-lang-label/" .. resolved_label, data_langcode)
end
end
end
end
end
Line 515: Line 615:
-- Note that this is an alias and store the canonical version.
-- Note that this is an alias and store the canonical version.
ret.canonical = label
ret.canonical = label
end
if not data.notrack then -- labprop("track") then -- track all labels now
-- Track label (after converting aliases to canonical form; but also track raw label (alias) if different
-- from canonical label).
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/label/LABEL]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/label/LABEL/LANGCODE]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/labels/label/LABEL/MODE]]
track("label/" .. label, data_langcode, mode)
if label ~= non_canonical then
track("label/" .. non_canonical, data_langcode, mode)
end
end
end


Line 526: Line 638:
depcat = "<code>" .. depcat .. "</code>"
depcat = "<code>" .. depcat .. "</code>"
end
end
table.insert(ret.categories, depcat)
insert(ret.categories, depcat)
end
end
end
end
Line 552: Line 664:
local cats = export.fetch_categories(label, labdata, data.lang, mode, data.for_doc)
local cats = export.fetch_categories(label, labdata, data.lang, mode, data.for_doc)
for _, cat in ipairs(cats) do
for _, cat in ipairs(cats) do
table.insert(ret.categories, cat)
insert(ret.categories, cat)
end
end
if not ret.categories[1] or data.for_doc then
if not ret.categories[1] or data.for_doc then
Line 560: Line 672:
else
else
ret.formatted_categories = require(utilities_module).format_categories(ret.categories, data.lang,
ret.formatted_categories = require(utilities_module).format_categories(ret.categories, data.lang,
data.sort, nil, force_cat)
data.sort, nil, force_cat or data.force_cat)
end
end
end
end
Line 626: Line 738:
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `nocat`: If true, don't add the label to any categories.
* `nocat`: If true, don't add the label to any categories.
* `force_cat`: Force adding categories even in namespaces that normally exclude them (e.g. userspace and discussion
  pages).
* `notrack`: Disable all tracking for this label.
* `notrack`: Disable all tracking for this label.
* `sort`: Sort key for categorization.
* `sort`: Sort key for categorization.
Line 631: Line 745:
   to the display form of the label, so if two labels have the same display form, the second one won't be displayed
   to the display form of the label, so if two labels have the same display form, the second one won't be displayed
   (but its categories will still be added). If `already_seen` is {nil}, this tracking doesn't happen.
   (but its categories will still be added). If `already_seen` is {nil}, this tracking doesn't happen.
 
* `ok_to_destructively_modify`: If set, the `data` structure will be destructively modified in the process of this
'''WARNING''': This destructively modifies the `data` structure.
  function running.
]==]
]==]
function export.process_raw_labels(data)
function export.process_raw_labels(data)
local label_infos = {}
local label_infos = {}
if not data.ok_to_destructively_modify then
data = m_table.shallowCopy(data)
data.ok_to_destructively_modify = true
end


local function get_info_and_insert(label)
local function get_info_and_insert(label)
-- Reuse this structure to save memory.
-- Reuse this structure to save memory.
data.label = label
data.label = label
table.insert(label_infos, export.get_label_info(data))
insert(label_infos, export.get_label_info(data))
end
end


Line 649: Line 768:
if i % 2 == 1 then
if i % 2 == 1 then
local raw_text_type = i == 1 and "begin" or i == #segments and "end" or "middle"
local raw_text_type = i == 1 and "begin" or i == #segments and "end" or "middle"
table.insert(label_infos, {raw_text = raw_text_type, label = segment, categories = {}})
insert(label_infos, {raw_text = raw_text_type, label = segment, categories = {}})
else
else
local segment_labels = export.split_labels_on_comma(segment)
local segment_labels = export.split_labels_on_comma(segment)
Line 674: Line 793:
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `nocat`: If true, don't add the label to any categories.
* `nocat`: If true, don't add the label to any categories.
* `force_cat`: Force adding categories even in namespaces that normally exclude them (e.g. userspace and discussion
  pages).
* `notrack`: Disable all tracking for this label.
* `notrack`: Disable all tracking for this label.
* `sort`: Sort key for categorization.
* `sort`: Sort key for categorization.
Line 679: Line 800:
   to the display form of the label, so if two labels have the same display form, the second one won't be displayed
   to the display form of the label, so if two labels have the same display form, the second one won't be displayed
   (but its categories will still be added). If `already_seen` is {nil}, this tracking doesn't happen.
   (but its categories will still be added). If `already_seen` is {nil}, this tracking doesn't happen.
 
* `ok_to_destructively_modify`: If set, the `data` structure will be destructively modified in the process of this
'''WARNING''': This destructively modifies the `data` structure.
  function running.
]==]
]==]
function export.split_and_process_raw_labels(data)
function export.split_and_process_raw_labels(data)
if not data.ok_to_destructively_modify then
data = m_table.shallowCopy(data)
data.ok_to_destructively_modify = true
end
data.labels = export.split_labels_on_comma(data.labels)
data.labels = export.split_labels_on_comma(data.labels)
return export.process_raw_labels(data)
return export.process_raw_labels(data)
Line 697: Line 822:
* `labels`: List of the label objects to format, in the format returned by {get_label_info()}.
* `labels`: List of the label objects to format, in the format returned by {get_label_info()}.
* `lang`: The language of the labels.
* `lang`: The language of the labels.
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `sort`: Sort key for categorization.
* `already_seen`: An object used to track labels already seen, so they aren't displayed twice, as documented in
  {get_label_info()}. To enable this, set this to an empty object. If `already_seen` is {nil}, this tracking doesn't
  happen, meaning if the same label appears twice, it will be displayed twice.
* `open`: Open bracket or parenthesis to display before the concatenated labels. If specified, it is wrapped in the
* `open`: Open bracket or parenthesis to display before the concatenated labels. If specified, it is wrapped in the
   {"ib-brac"} CSS class. If {nil}, no open bracket is displayed.
   {"ib-brac"} and {"label-brac"} CSS classes. If {nil} or {false}, no open bracket is displayed.
* `close`: Close bracket or parenthesis to display after the concatenated labels. If specified, it is wrapped in the
* `close`: Close bracket or parenthesis to display after the concatenated labels. If specified, it is wrapped in the
   {"ib-brac"} CSS class. If {nil}, no close bracket is displayed.
   {"ib-brac"} and {"label-brac"} CSS classes. If {nil} or {false}, no close bracket is displayed.
* `no_ib_content`: By default, the concatenated formatted labels inside of the open/close brackets are wrapped in the
* `no_ib_content`: By default, the concatenated formatted labels inside of the open/close brackets are wrapped in the
   {"ib-content"} CSS class. Specify this to suppress this wrapping.
   {"ib-content"} and {"label-content"} CSS classes. Specify this to suppress this wrapping.
* `raw`: Suppress all CSS wrapping of content, including open/close parentheses, content and comma delimiters (which
  are normally wrapped in {"ib-comma"} and {"label-comma"} CSS classes).
* `ok_to_destructively_modify`: If set, the `data` structure, and the `data.labels` table inside of it, will be
  destructively modified in the process of this function running.
* `split_output`: If not given, the return value is a concatenation of the formatted concatenated labels and formatted
  categories. Otherwise, two values are returned: the formatted pronunciation and the categories. If `split_output` is
  the value {"raw"}, the categories are returned in list form, where the list elements are strings f the form suitable
  for passing to {format_categories()} in [[Module:utilities]]. If `split_output` is any other value besides {nil}, the
  categories are returned as a pre-formatted concatenated string.


Return value is a string containing the contenated labels, optionally surrounded by open/close brackets or parentheses.
The return value (or the first return value, if `split_output` is given) is a string containing the contenated labels,
Normally, labels are separated by comma-space sequences, but this may be suppressed for certain labels. If `nocat`
optionally surrounded by open/close brackets or parentheses. Normally, labels are separated by comma-space sequences,
wasn't given to {get_label_info() or process_raw_labels()}, the label objects will contain formatted categories in
but this may be suppressed for certain labels. If `nocat` wasn't given to {get_label_info()} or {process_raw_labels()},
them, which will be inserted into the returned text. The concatenated text inside of the open/close brackets is normally
and `split_output` wasn't given, the label objects will contain formatted categories in them, which will be inserted
wrapped in the {"ib-content"} CSS class, but this can be suppressed, as mentioned above.
into the returned text. (Use `split_output` if you need the categories returned separately.) The concatenated text
 
inside of the open/close brackets is normally wrapped in the {"ib-content"} CSS class, but this can be suppressed, as
'''WARNING''': This destructively modifies the `data` structure.
mentioned above.
]==]
]==]
function export.format_processed_labels(data)
function export.format_processed_labels(data)
if not data.labels then
if not data.labels then
error("`data` must now be an object containing the params")
error("`data` must now be an object containing the params")
end
if not data.ok_to_destructively_modify then
data = m_table.shallowCopy(data)
data.labels = m_table.deepCopy(data.labels)
data.ok_to_destructively_modify = true
end
end
local labels = data.labels
local labels = data.labels
Line 754: Line 888:
end
end


local function wrap_css(txt, suffix)
if data.raw then
return txt
end
return ("<span class=\"ib-%s label-%s\">%s</span>"):format(suffix, suffix, txt)
end
local categories = nil
local formatted_categories = split_output and split_output ~= "raw" and {} or nil
for i, labelinfo in ipairs(labels) do
for i, labelinfo in ipairs(labels) do
local label
local label
Line 764: Line 907:
label = ""
label = ""
else
else
label = (labelinfo.omit_comma and "" or '<span class="ib-comma">,</span>') ..
label = (labelinfo.omit_comma and "" or wrap_css(",", "comma")) ..
(labelinfo.omit_space and "" or "&#32;") ..
(labelinfo.omit_space and "" or "&#32;") ..
labelinfo.label
labelinfo.label
end
end
labels[i] = label .. (labelinfo.formatted_categories or "")
if split_output then
labels[i] = label
if split_output == "raw" then
if labelinfo.categories and labelinfo.categories[1] then
if categories then
m_table.extend(categories, labelinfo.categories)
else
categories = labelinfo.categories
end
end
elseif labelinfo.formatted_categories then
insert(formatted_categories, labelinfo.formatted_categories)
end
else
labels[i] = label .. (labelinfo.formatted_categories or "")
end
end
end


local function wrap_open_close(val)
local function wrap_open_close(val)
if val then
if val then
return "<span class=\"ib-brac\">" .. val .. "</span>"
return wrap_css(val, "brac")
else
else
return ""
return ""
Line 781: Line 939:
local concatenated_labels = table.concat(labels, "")
local concatenated_labels = table.concat(labels, "")
if not data.no_ib_content then
if not data.no_ib_content then
concatenated_labels = "<span class=\"ib-content\">" .. concatenated_labels .. "</span>"
concatenated_labels = wrap_css(concatenated_labels, "content")
end
end


return wrap_open_close(data.open) .. concatenated_labels .. wrap_open_close(data.close)
local ret_labels = wrap_open_close(data.open) .. concatenated_labels .. wrap_open_close(data.close)
if split_output == "raw" then
return ret_labels, categories
elseif split_output then
return ret_labels, concat(formatted_categories)
else
return ret_labels
end
end
end


Line 796: Line 961:
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `mode`: How the label was invoked; see {get_label_info()} for more information.
* `nocat`: If true, don't add the labels to any categories.
* `nocat`: If true, don't add the labels to any categories.
* `force_cat`: Force adding categories even in namespaces that normally exclude them (e.g. userspace and discussion
  pages).
* `notrack`: Disable all tracking for these labels.
* `notrack`: Disable all tracking for these labels.
* `sort`: Sort key for categorization.
* `sort`: Sort key for categorization.
Line 804: Line 971:
* `close`: Close bracket or parenthesis to display after the concatenated labels. If {nil}, defaults to a close
* `close`: Close bracket or parenthesis to display after the concatenated labels. If {nil}, defaults to a close
   parenthesis. Set to {false} to disable.
   parenthesis. Set to {false} to disable.
* `no_ib_content`: As in `format_processed_labels()`.
* `raw`: As in `format_processed_labels()`. Also suppress wrapping the entire formatted result in a usage label CSS
  class (see below).
* `ok_to_destructively_modify`: If set, the `data` structure will be destructively modified in the process of this
  function running.


Compared with {format_processed_labels()}, this function has the following differences:
Compared with {format_processed_labels()}, this function has the following differences:
Line 810: Line 982:
# Tracking of already-seen labels is enabled unless explicitly turned off using `no_track_already_seen`.
# Tracking of already-seen labels is enabled unless explicitly turned off using `no_track_already_seen`.
# The entire formatted result is wrapped in a {"usage-label-<var>type</var>"} CSS class (depending on the value of
# The entire formatted result is wrapped in a {"usage-label-<var>type</var>"} CSS class (depending on the value of
   `mode`).
   `mode`), unless `raw` is given.
 
'''WARNING''': This destructively modifies the `data` structure.
]==]
]==]
function export.show_labels(data)
function export.show_labels(data)
if not data.labels then
if not data.labels then
error("`data` must now be an object containing the params")
error("`data` must now be an object containing the params")
end
if not data.ok_to_destructively_modify then
data = m_table.shallowCopy(data)
data.ok_to_destructively_modify = true
end
end
local labels = data.labels
local labels = data.labels
Line 837: Line 1,011:
end
end
local formatted = export.format_processed_labels(data)
local formatted = export.format_processed_labels(data)
return "<span class=\"" .. mode_to_outer_class[mode] .. "\">" .. formatted .. "</span>"
if data.raw then
return formatted
else
return "<span class=\"" .. mode_to_outer_class[mode] .. "\">" .. formatted .. "</span>"
end
end
end


--[==[Helper function for the data modules.]==]
--[==[Helper function for the data modules.]==]
function export.alias(labels, key, aliases)
function export.alias(labels, key, aliases)
require(table_module).alias(labels, key, aliases)
m_table.alias(labels, key, aliases)
end
end


Line 859: Line 1,037:
return link, display
return link, display
end
end
local link = label:match("^%[%[([^%[%]|])+%]%]$")
link = label:match("^%[%[([^%[%]|])+%]%]$")
if link then
if link then
return link, link
return link, link
Line 888: Line 1,066:
--[==[Used to finalize the data into the form that is actually returned.]==]
--[==[Used to finalize the data into the form that is actually returned.]==]
function export.finalize_data(labels)
function export.finalize_data(labels)
local shallow_copy = require(table_module).shallowCopy
local shallow_copy = m_table.shallowCopy
local aliases = {}
local aliases = {}
for label, data in pairs(labels) do
for label, data in pairs(labels) do