Module:Tag

From OpenStreetMap Wiki
Jump to navigation Jump to search
[Create] Documentation
local p = {}
local languages = require("Module:Languages")
local currentTitle = mw.title.getCurrentTitle()
local defaultLangCode = languages.languageFromTitle(currentTitle)

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

function p.tag(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 components = {}
	local keyComponents = {}
	
	-- Key
	local key = args[1]
	table.insert(keyComponents, 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=.
	-- TODO: Keep this from affecting links.
	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)
		subkeyIndex = subkeyIndex + 1
	end
	
	-- Link the key and any subkeys.
	local linkedKeyComponents = {}
	for i, key in ipairs(keyComponents) do
		local langCode = args["kl" .. string.rep(":", i - 1)]
		table.insert(linkedKeyComponents, pageLink("Key:" .. key, key, langCode))
	end
	table.insert(components, table.concat(linkedKeyComponents, ":"))
	
	components = {
		tostring(mw.html.create("bdi")
			:css("white-space", "nowrap")
			:wikitext(table.concat(components)))
	}
	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"]
			table.insert(linkedValues, valueLink(lastKeyComponent, value, langCode))
		end
		table.insert(components, table.concat(linkedValues, ";"))
	elseif args[3] and #args[3] > 0 then
		local value = args[3]
		local pageName
		if lastKeyComponent == "wikipedia" then
			pageName = "w:" .. value
		elseif lastKeyComponent == "wikidata" then
			pageName = "d:" .. value
		elseif lastKeyComponent == "commons" then
			pageName = "Commons:" .. value
		end
		
		if lastKeyComponent == "url" or lastKeyComponent == "website" then
			local label = mw.html.create("bdi")
				:css("white-space", "normal")
				:wikitext(mw.text.nowiki(value))
			table.insert(components, "[" .. value .. " " .. 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, "*")
	end
	
	return table.concat(components)
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