Permanently protected module

Module:OsmPageTitleParser

From OpenStreetMap Wiki
Jump to navigation Jump to search

local p = {}
local data = mw.loadData('Module:OSM Constants')

-- Module_talk:OsmPageTitleParser/testcases  has many test cases showing how to use this module
-- Simple debugging:
--  =p.parseTitle(mw.title.new('Key:test')).key

-- A wrapper to return the parse results. See p.parseTitleToObj
function p.parseTitle(title)
  local result = {}
  p.parseTitleToObj(result, title)
  return result
end

-- given a title string in a form of (lang-code:)?(tag|key):(tagkey)(=tagvalue)?
-- tries to parse it into language (object), key, and optional value strings
-- We have to do it manually because Lua regex support is not that great
-- The actual tag and key prefixes are ignored. Value will be nil if no equal sign.
-- The output result object will always get the language unless title is nil,
-- but no other values will be set unless successfuly parsed
-- Params:  title object,  result table to get the results
-- Returns true if parsed, false otherwise
function p.parseTitleToObj(result, title)
  if not title then return false end

  local language, prefix, tagkey, tagvalue

  -- if this is one of the known language namespaces, do not allow more language codes
  local ns = title.namespace / 2 * 2
  ns = ns - ns % 2 -- treat talk pages as their corresponding main pages
  local langCode = data.nsToLangCodeMap[ns]
  if langCode then
    language = mw.getLanguage(langCode)
  end

  local canonicalTitle = mw.ustring.gsub(title.text, ' ', '_')
  local keyvalue
  for _, val in ipairs(mw.text.split(canonicalTitle, ':', true)) do
    if not prefix then
      -- this could be the language code or the prefix (tag or key)
      local lval = string.lower(val)
      if lval == 'tag' or lval == 'key' then
        prefix = lval
      elseif not language and (data.customLangCodes[lval] or mw.language.isSupportedLanguage(lval)) then
      	-- mw.getLanguage will creat an object even if the language is not supported
        language = mw.getLanguage(lval)
      else
        -- unrecognized, there was no tag or key as first or second part
        break
      end
    else
      -- combine the values back into a single string after we found the prefix
      if keyvalue then
        keyvalue = keyvalue .. ':' .. val
      else
        keyvalue = val
      end
    end
  end

  if keyvalue then
    -- now split the keyvalue into key and (optional) value
    tagkey, tagvalue = p.splitKeyValue(keyvalue)
    if not tagkey and not tagvalue then
      keyvalue = nil
    end
  end

  if not language then
    result.language = mw.language.getContentLanguage()
  else
    result.language = language
  end

  if keyvalue then
    result.key = tagkey
    if tagvalue then result.value = tagvalue end
    return true
  else
    return false
  end
end

-- given a key=value string, split it into two parts and return both
-- if there is no equal sign, return key and nil value
function p.splitKeyValue(keyvalue)
	if not keyvalue then return end
	local tagkey, tagvalue
    local eqlSignPos = mw.ustring.find(keyvalue, '=', 1, true)
    if not eqlSignPos then
      tagkey = keyvalue
    else
      local keyvalLen = mw.ustring.len(keyvalue)
      if eqlSignPos > 1 then
        tagkey = mw.ustring.sub(keyvalue, 1, eqlSignPos - 1)
        tagvalue = mw.ustring.sub(keyvalue, eqlSignPos + 1)
      end
    end
    return tagkey, tagvalue
end

-- Given a language code, returns proper title prefix:
-- empty string for English, all caps for the namespaces, first letter cap for rest
function p.langPrefix(langCode)
	langCode = langCode and mw.ustring.lower(langCode) or ''
	if not langCode or langCode == '' or langCode == 'en' then
		return ''
	end
	for _,v in pairs(data.nsToLangCodeMap) do
	  if v == langCode then
	    return string.upper(langCode) .. ':'
	  end
	end
	return mw.getContentLanguage():ucfirst(langCode) .. ':'
end

function p.languageCodeInTitle(frame)
	local title = mw.title.new(frame.args[1])
	local language = p.parseTitle(title).language
	return language.code
end

function p.keyInTitle(frame)
	local title = mw.title.new(frame.args[1])
	return p.parseTitle(title).key
end

function p.valueInTitle(frame)
	local title = mw.title.new(frame.args[1])
	return p.parseTitle(title).value
end

function p.dataItemLabelFromTitle(frame)
	local title = mw.title.new(frame.args[1])
	local parsedTitle = p.parseTitle(title)
	if parsedTitle.value then
		return parsedTitle.key .. "=" .. parsedTitle.value
	end
	return parsedTitle.key
end

return p