Module:Tag



From OpenStreetMap Wiki



Jump to navigation  Jump to search  

[Edit] [Purge] Documentation

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

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)
 local validPageName
 if langCode and #langCode > 0 then
  validPageName = languages.translationPageName(langCode, mw.title.new(pageName))
 elseif defaultLangCode ~= "en" and pageName ~= currentTitle.fullText then
  local translatedPageName = languages.translationPageName(defaultLangCode, mw.title.new(pageName))
  if mw.title.new(translatedPageName).exists then
   validPageName = translatedPageName
  else
   validPageName = pageName
  end
 elseif mw.title.new(pageName) then
  validPageName = pageName
 end
 
 if validPageName then
  return "[[" .. validPageName .. "|" .. label .. "]]"
 else
  return label
 end
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("&#x2a;&#x3a;%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
Retrieved from "https://wiki.openstreetmap.org/w/index.php?title=Module:Tag&oldid=2722374"

Category: 
Link templates
 


Navigation menu


Personal tools  



English
Create account
Log in
 

Namespaces  



Module
Discussion