Module:Tag: Difference between revisions
Jump to navigation
Jump to search
Minh Nguyen (talk | contribs) (Properly escape * to keep it from getting interpreted as a bullet point, but w/o inserting a literal “<nowiki/>” into the output; see Template talk:Tag#Edit 2024-05-07 broke template) |
Minh Nguyen (talk | contribs) m (string.sub() is an instance member, not a type member) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 146: | Line 146: | ||
local lastSubkey = lastKeyComponent:match("%w+$") |
local lastSubkey = lastKeyComponent:match("%w+$") |
||
local value = args[3] |
local value = args[3] |
||
-- A wiki page title cannot contain a square bracket, so this is likely already a wikilink or external link. |
|||
local isLiteralLink = (value:sub(1, 1)) == "[" |
|||
local pageName |
local pageName |
||
local url |
|||
⚫ | |||
if not isLiteralLink then |
|||
if lastSubkey == "wikipedia" or lastBaseKeyComponent == "wikipedia" then |
|||
if lastSubkey ~= "wikipedia" then |
|||
⚫ | |||
end |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
pageName = "Commons:" .. value |
|||
end |
|||
⚫ | |||
url = value |
|||
end |
end |
||
⚫ | |||
elseif lastSubkey == "wikidata" or lastBaseKeyComponent == "wikidata" then |
|||
⚫ | |||
⚫ | |||
⚫ | |||
end |
end |
||
if url then |
|||
⚫ | |||
local label = mw.html.create("bdi") |
local label = mw.html.create("bdi") |
||
:css("white-space", "normal") |
:css("white-space", "normal") |
||
:wikitext(mw.text.nowiki( |
:wikitext(mw.text.nowiki(url)) |
||
table.insert(components, "[" .. |
table.insert(components, "[" .. url .. " " .. tostring(label) .. "]") |
||
elseif pageName then |
elseif pageName then |
||
local label = mw.html.create("bdi"):wikitext(args[3]) |
local label = mw.html.create("bdi"):wikitext(args[3]) |
Revision as of 01:33, 17 May 2024
This documentation is transcluded from Module:Tag/doc. (Edit | history)
Note to editors: Please don't categorize this template by editing it directly. Instead, place the category in its documentation page, in its "includeonly" section.
Note to editors: Please don't categorize this template by editing it directly. Instead, place the category in its documentation page, in its "includeonly" section.
Usage
Utilities related to OSM tags.
A number of testcases verify the correctness of these functions. Run the unit tests.
key
Returns a human-readable reference to a key.
Parameters:
- |1 =
- The name of a key.
- |subkey = (|subkey1 =), |subkey2 =, |subkey3 =, etc.
- The name of each successive subkey. A subkey is separated by a semicolon and links to the key description page of the base key.
- |: =, |:: =, |::: =, etc.
- The name of each successive key component. A key component is separated by a semicolon and links to a key description page specifically about the key component.
- |kl =, |kl: =, |kl:: =, etc.
- The language code of the page to link each successive key component. |kl = determines the link for |1 =, |kl: = for |: =, and so on. If the language is unspecified, the key component is linked to the page in the same language as the page that transcludes this template, falling back to English.
- |lang =
- The language code of all the link targets. If the language is unspecified, each link points to the page in the same language as the page that transcludes this template, falling back to English.
value
Returns a human-readable reference to a tag value.
Parameters:
- |key = or |1 =
- The name of a key.
- |value =
- A tag value, which will be linked or unlinked depending on the value of |link =.
- |link =
- Determines the link target of the link that this template outputs:
- |link = key
- Links to the key's description page.
- |link = key#
- Links to a named anchor on the key's description page in the form
key-value
. - |link = value
- Links to the value's description page.
- |link = none
- No link.
- |2 =
- A tag value to be linked to a value description page. Use this parameter or the combination of |link = value and |value = for any value of an enumeration-typed key.
- |3 =
- A tag value to be linked to the key's description page. Use this parameter or the combination of |link = key# and |value = for any value of an enumeration-typed key that is specifically documented on the key's description page.
- |4 =
- An unlinked tag value. Use this parameter and leave |2 = and |3 = blank, or combine |link = key with |value =, for any value of a key that is not specifically documented anywhere. Alternatively, this parameter and leave |2 = and |3 = blank, or combine |link = none with |value =, for any value of a key that holds freeform text, a URL, or more complex syntax.
- |lang = or |kl =
- The language code of the link target. If the language is unspecified, the key component is linked to the page in the same language as the page that transcludes this template, falling back to English.
tag
Returns a human-readable reference to a key or key-value pair using key=value syntax.
Parameters:
- |1 =
- The name of a key.
- |subkey = (|subkey1 =), |subkey2 =, |subkey3 =, etc.
- The name of each successive subkey. A subkey is separated by a semicolon and links to the key description page of the base key.
- |: =, |:: =, |::: =, etc.
- The name of each successive key component. A key component is separated by a semicolon and links to a key description page specifically about the key component.
- |kl =, |kl: =, |kl:: =, etc.
- The language code of the page to link each successive key component. |kl = determines the link for |1 =, |kl: = for |: =, and so on. If the language is unspecified, the key component is linked to the page in the same language as the page that transcludes this template, falling back to English.
- |2 =, |; = (|subval =), |;; = (|subval2 =), etc.
- Tag values separated by semicolons. Each value is linked to a value description page. Use these parameters for any value of an enumeration-typed key.
- |vl =, |vl2 =, |vl3 =, etc.
- The language code of the page to link each successive value. |vl = determines the link for |2 =, |vl2 = for |; = or |subval =, |vl3 = for |;; = or |subval2 =, and so on. If the language is unspecified, the value is linked to the page in the same language as the page that transcludes this template, falling back to English.
- |3 =
- A tag value. The value is unlinked. Use this parameter and leave |2 = blank for any value of a key that holds freeform text, a URL, or more complex syntax, or for explanatory placeholder text. A value of *:wikipedia=*, *:wikidata=*, *:wikimedia_commons=*, *:url=*, or *:website=* is linked to the referenced URL.
- |lang =
- The language code of all the link targets. If the language is unspecified, each link points to the page in the same language as the page that transcludes this template, falling back to English.
keyComponentList
Returns an unordered list of key components that form the given key. Each key component is annotated with its description from the associated data item, if available.
Parameters:
- |1 =
- The key to split into components.
- |intro =
- Introductory text to insert before the list.
See also
- {{Tag}}
- {{TagKey}}
- {{TagValue}}
- {{Key components}}
- Module:Taglink
local p = {}
local getArgs = require('Module:Arguments').getArgs
local languages = require("Module:Languages")
local currentTitle = mw.title.getCurrentTitle()
local defaultLangCode = languages.languageFromTitle(currentTitle)
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
trim = true,
removeBlanks = false,
})
return p[funcName](args)
end
end
function pageLink(pageName, label, langCode)
if langCode then
if #langCode > 0 then
pageName = languages.translationPageName(langCode, mw.title.new(pageName))
end
elseif defaultLangCode ~= "en" and pageName ~= currentTitle.fullText then
local translatedPageName = languages.translationPageName(defaultLangCode, mw.title.new(pageName))
if mw.title.new(translatedPageName).exists then
pageName = translatedPageName
end
end
return "[[" .. pageName .. "|" .. label .. "]]"
end
function valueLink(key, value, langCode)
local pageName = "Tag:" .. key .. "=" .. value
return pageLink(pageName, tostring(mw.html.create("bdi"):wikitext(value)), langCode)
end
p.value = makeInvokeFunc("_value")
function p._value(args)
local langCode = args.kl or args.lang
local key = args.key or args[1]
local pageName
if args.link == "value" or args.link == "tag" or (args[2] and #args[2] > 0) then
if key == "type" then
pageName = "Relation:" .. (args.value or args[2])
else
pageName = mw.ustring.format("Tag:%s=%s", key, args.value or args[2])
end
elseif args.link == "key#" or (args[3] and #args[3] > 0) then
pageName = mw.ustring.format("Key:%s#%s-%s", key, key, args.value or args[3])
elseif args.link ~= "none" and key then
pageName = "Key:" .. key
end
local label = args.value or args[4] or args[3] or args[2] or mw.text.nowiki("*")
label = mw.html.create("bdi"):wikitext(label)
if pageName then
return tostring(pageLink(pageName, tostring(label), langCode))
else
return tostring(label)
end
end
function tag(args, includesValue)
local components = {}
local keyComponents = {}
local keyComponentsToLink = {}
-- Key
local key = args[1]
table.insert(keyComponents, key)
table.insert(keyComponentsToLink, key)
-- Give |subkey= precedence over |subkey1=.
if args.subkey then
table.insert(keyComponents, args.subkey)
end
-- Collect subkeys.
local subkeyIndex = 2
while args["subkey" .. subkeyIndex] do
local subkey = args["subkey" .. subkeyIndex]
table.insert(keyComponents, subkey)
subkeyIndex = subkeyIndex + 1
end
-- Combine |subkey*= with |key=, but not for linking purposes.
keyComponents = {
table.concat(keyComponents, mw.text.nowiki(":")),
}
-- Collect subkeys to be linked separately.
local subkeyIndex = 1
while args[string.rep(":", subkeyIndex)] do
local subkey = args[string.rep(":", subkeyIndex)]
table.insert(keyComponents, subkey)
table.insert(keyComponentsToLink, subkey)
subkeyIndex = subkeyIndex + 1
end
-- Link the key and any subkeys.
local linkedKeyComponents = {}
for i, key in ipairs(keyComponentsToLink) do
local langCode = args["kl" .. string.rep(":", i - 1)] or args.lang
table.insert(linkedKeyComponents, pageLink("Key:" .. key, keyComponents[i], langCode))
end
table.insert(components, table.concat(linkedKeyComponents, ":"))
components = {
tostring(mw.html.create("bdi")
:css("white-space", "nowrap")
:wikitext(table.concat(components)))
}
if not includesValue then
return table.concat(components)
end
table.insert(components, "=")
-- Values
local lastKeyComponent = keyComponents[#keyComponents]
if args[2] and #args[2] > 0 then
local values = {}
if args[2] then
table.insert(values, args[2])
end
if args[";"] or args.subval then
table.insert(values, args[";"] or args.subval)
end
local subvalueIndex = 2
while args[string.rep(";", subvalueIndex)] or args["subval" .. subvalueIndex] do
local otherValue = args[string.rep(";", subvalueIndex)] or args["subval" .. subvalueIndex]
if #otherValue > 0 then
table.insert(values, otherValue)
end
subvalueIndex = subvalueIndex + 1
end
local linkedValues = {}
for i, value in ipairs(values) do
local langCode = args[i > 1 and ("vl" .. i) or "vl"] or args.lang
table.insert(linkedValues, valueLink(lastKeyComponent, value, langCode))
end
table.insert(components, table.concat(linkedValues, ";"))
elseif args[3] and #args[3] > 0 then
local lastBaseKeyComponent = keyComponentsToLink[#keyComponentsToLink]
local lastSubkey = lastKeyComponent:match("%w+$")
local value = args[3]
-- A wiki page title cannot contain a square bracket, so this is likely already a wikilink or external link.
local isLiteralLink = (value:sub(1, 1)) == "["
local pageName
local url
if not isLiteralLink then
if lastSubkey == "wikipedia" or lastBaseKeyComponent == "wikipedia" then
if lastSubkey ~= "wikipedia" then
value = lastSubkey .. ":" .. value
end
pageName = "w:" .. value
elseif lastSubkey == "wikidata" or lastBaseKeyComponent == "wikidata" then
pageName = "d:" .. value
elseif lastSubkey == "wikimedia_commons" or lastBaseKeyComponent == "wikimedia_commons" then
pageName = "Commons:" .. value
end
if lastSubkey == "url" or lastBaseKeyComponent == "url" or lastSubkey == "website" or lastBaseKeyComponent == "website" then
url = value
end
end
if url then
local label = mw.html.create("bdi")
:css("white-space", "normal")
:wikitext(mw.text.nowiki(url))
table.insert(components, "[" .. url .. " " .. tostring(label) .. "]")
elseif pageName then
local label = mw.html.create("bdi"):wikitext(args[3])
table.insert(components, pageLink(pageName, tostring(label), ""))
else
local label = mw.html.create("bdi"):wikitext(args[3])
table.insert(components, tostring(label))
end
else
table.insert(components, mw.text.nowiki("*"))
end
return table.concat(components)
end
p.key = makeInvokeFunc("_key")
function p._key(args)
return tag(args, false)
end
p.tag = makeInvokeFunc("_tag")
function p._tag(args)
return tag(args, true)
end
function p.keyComponents(key)
if #key == 0 then
return {}
end
local rawComponents = mw.text.split(key, ":", true)
local resolvedComponents = {}
local mostSpecificTitle
local mostSpecificEntityId
local mostSpecificDescription
local seenCoreComponent = false
for i, component in ipairs(rawComponents) do
local base = table.concat(resolvedComponents, ":")
if #base > 0 then
base = base .. ":"
end
local key = mw.ustring.format("%s%s", base, component)
local title
local entityId
-- First check if this component is a prefix.
-- TODO: Require the prefix to precede any non-prefixes.
local pageName = mw.ustring.format("Key:%s:*", key)
title = mw.title.new(pageName)
entityId = mw.wikibase.getEntityIdForTitle(pageName)
-- How about a suffix?
-- TODO: Require the suffix to follow any non-suffixes.
if not entityId and not (title and title.exists) then
local pageName = mw.ustring.format("Key:*:%s", key)
title = mw.title.new(pageName)
entityId = mw.wikibase.getEntityIdForTitle(pageName)
end
if not entityId and not (title and title.exists) then
local pageName = mw.ustring.format("Key:%s", key)
title = mw.title.new(pageName)
entityId = mw.wikibase.getEntityIdForTitle(pageName)
end
if entityId or title.exists then
local description = mw.wikibase.getDescription(entityId)
if (description or not mw.ustring.find(key, ":")) and
-- Avoid deprecated keys, which are less likely to be key components.
(not entityId or #mw.wikibase.getBestStatements(entityId, "P17") == 0) then
table.insert(resolvedComponents, component)
mostSpecificTitle = title
mostSpecificEntityId = entityId
mostSpecificDescription = description
else
break
end
else
break
end
end
if #resolvedComponents == 0 then
local component = rawComponents[1]
if mw.language.isKnownLanguageTag(component) then
table.insert(resolvedComponents, component)
mostSpecificDescription = mw.ustring.format("[[w:ISO 639:%s|%s]]",
component,
mw.language.fetchLanguageName(component, defaultLangCode))
end
end
local subkey = table.concat(rawComponents, ":", #resolvedComponents + 1)
if #resolvedComponents == 0 then
local component = {
name = subkey,
}
return { component }
end
local superkey = {
name = table.concat(resolvedComponents, ":"),
title = mostSpecificTitle,
entityId = mostSpecificEntityId,
description = mostSpecificDescription,
}
resolvedComponents = p.keyComponents(subkey)
table.insert(resolvedComponents, 1, superkey)
return resolvedComponents
end
function p.keyComponentList(frame)
-- Get arguments from the calling frame, falling back to its calling frame
local args = frame.args[1] and frame.args or frame:getParent().args
local key = args[1]
local components = p.keyComponents(key)
if #components < 2 then
return ""
end
local listItems = {}
for i, component in ipairs(components) do
local tag
if i == 1 then
tag = frame:expandTemplate {
title = "Tag",
args = { component["name"] },
}
elseif component["title"] or component["entityId"] then
tag = frame:expandTemplate {
title = "Tag",
args = {
"*",
[":"] = component["name"]
},
}
else
tag = frame:expandTemplate {
title = "Value",
args = {
mw.ustring.format("*:%s=*", component["name"]),
},
}
end
local description = component.description
local edit = component.entityId and frame:expandTemplate {
title = "Edit",
args = {
"Item:" .. component.entityId,
},
} or ""
if description then
table.insert(listItems, mw.ustring.format("* %s: %s %s", tag, description, edit))
else
table.insert(listItems, mw.ustring.format("* %s %s", tag, edit))
end
end
if args.intro and #args.intro > 0 then
table.insert(listItems, 1, args.intro)
end
return table.concat(listItems, "\n")
end
return p