Module:Wd: Difference between revisions
From Zoophilia Wiki
Jump to navigationJump to search
meta>Thayts No edit summary |
meta>Thayts No edit summary |
||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local outPreferred = {} | local function newState() | ||
return { | |||
outPreferred = {}, | |||
outNormal = {}, | |||
outDeprecated = {}, | |||
bestRank = true, | |||
foundRank = 3, | |||
maxRank, minRank, | |||
linked = false, | |||
propertyWithQualifier = false, | |||
withUnit = false, | |||
unknownDatatypeError = function(type) | |||
return "<strong class=\"error\">Unknown or unsupported datatype '" .. type .. "'</strong>" | return "<strong class=\"error\">Unknown or unsupported datatype '" .. type .. "'</strong>" | ||
end | end, | ||
convertUnit = function(unit) | |||
local i, j, itemID, label, target | local i, j, itemID, label, target | ||
Line 57: | Line 59: | ||
return " " .. unit | return " " .. unit | ||
end | end, | ||
getValue = function(snak, appendUnit) | |||
appendUnit = appendUnit or false | appendUnit = appendUnit or false | ||
Line 105: | Line 107: | ||
return nil | return nil | ||
end | end | ||
end | end, | ||
getRawValue = function(snak) | |||
local temp, value | local temp, value | ||
if snak.snaktype == 'value' and snak.datavalue.type == 'wikibase-entityid' then | if snak.snaktype == 'value' and snak.datavalue.type == 'wikibase-entityid' then | ||
Line 118: | Line 120: | ||
return value | return value | ||
end | end | ||
end | end, | ||
snakEqualsValue = function(snak, value) | |||
if snak.snaktype == 'value' then | if snak.snaktype == 'value' then | ||
local snakValue = getRawValue(snak) | local snakValue = getRawValue(snak) | ||
Line 142: | Line 144: | ||
return false | return false | ||
end | end | ||
end | end, | ||
setRankBoundaries = function(rank) | |||
local rankPos | local rankPos | ||
Line 179: | Line 181: | ||
minRank = rankPos | minRank = rankPos | ||
end | end | ||
end | end, | ||
convertRank = function(rank) | |||
if (rank == "preferred") then | if (rank == "preferred") then | ||
return 1 | return 1 | ||
Line 191: | Line 193: | ||
return 4 -- default (in its literal sense) | return 4 -- default (in its literal sense) | ||
end | end | ||
end | end, | ||
rankMatches = function(rankPos) | |||
if bestRank then | if bestRank then | ||
if foundRank > rankPos then | if foundRank > rankPos then | ||
Line 211: | Line 213: | ||
return (maxRank <= rankPos and rankPos <= minRank) | return (maxRank <= rankPos and rankPos <= minRank) | ||
end | end | ||
end | end, | ||
appendOutput = function(value, rankPos) | |||
if rankPos == 1 then | if rankPos == 1 then | ||
outPreferred[#outPreferred + 1] = value | outPreferred[#outPreferred + 1] = value | ||
Line 221: | Line 223: | ||
outDeprecated[#outDeprecated + 1] = value | outDeprecated[#outDeprecated + 1] = value | ||
end | end | ||
end | end, | ||
out = function() | |||
local out = "" | local out = "" | ||
Line 251: | Line 253: | ||
return out | return out | ||
end | end, | ||
processFlag = function(flag) | |||
if flag == "linked" then | if flag == "linked" then | ||
linked = true | linked = true | ||
Line 266: | Line 268: | ||
return false | return false | ||
end | end | ||
end | |||
} | |||
end | end | ||
p.property = function(frame) | p.property = function(frame) | ||
local s = newState() | |||
local entity, propertyID, claims, rankPos, value | local entity, propertyID, claims, rankPos, value | ||
local nextArg = mw.text.trim(frame.args[1] or "") | local nextArg = mw.text.trim(frame.args[1] or "") | ||
local nextIndex = 2 | local nextIndex = 2 | ||
setRankBoundaries("best") | s.setRankBoundaries("best") | ||
while processFlag(nextArg) do | while s.processFlag(nextArg) do | ||
nextArg = mw.text.trim(frame.args[nextIndex] or "") | nextArg = mw.text.trim(frame.args[nextIndex] or "") | ||
nextIndex = nextIndex + 1 | nextIndex = nextIndex + 1 | ||
Line 291: | Line 296: | ||
if claims then | if claims then | ||
for k, v in pairs(claims) do | for k, v in pairs(claims) do | ||
rankPos = convertRank(v.rank) | rankPos = s.convertRank(v.rank) | ||
if rankMatches(rankPos) then | if s.rankMatches(rankPos) then | ||
value = getValue(v.mainsnak, withUnit) | value = s.getValue(v.mainsnak, withUnit) | ||
if value then appendOutput(value, rankPos) end | if value then s.appendOutput(value, rankPos) end | ||
end | end | ||
end | end | ||
return out() | return s.out() | ||
else | else | ||
return "" | return "" |
Revision as of 21:13, 30 August 2016
Documentation for this module may be created at Module:Wd/doc
local p = {}
local function newState()
return {
outPreferred = {},
outNormal = {},
outDeprecated = {},
bestRank = true,
foundRank = 3,
maxRank, minRank,
linked = false,
propertyWithQualifier = false,
withUnit = false,
unknownDatatypeError = function(type)
return "<strong class=\"error\">Unknown or unsupported datatype '" .. type .. "'</strong>"
end,
convertUnit = function(unit)
local i, j, itemID, label, target
if unit == "" or unit == "1" then
return nil
end
if unit:match('^http[s]?://') then
i, j = unit:find("Q")
if i then
itemID = unit:sub(i)
if itemID == "Q11229" then -- percentage
return "%"
else
label = mw.wikibase.label(itemID)
target = nil
if linked or label == nil then
target = mw.wikibase.sitelink(itemID)
end
if linked then
if target then
return " " .. "[[" .. target .. "|" .. (label or target) .. "]]"
end
if not label then
return " " .. "[[:d:" .. itemID .. "|" .. itemID .. "]]"
end
end
return " " .. (label or target or itemID)
end
end
end
return " " .. unit
end,
getValue = function(snak, appendUnit)
appendUnit = appendUnit or false
if snak.snaktype == 'value' then
if snak.datavalue.type == 'string' then
return snak.datavalue.value
elseif snak.datavalue.type == 'monolingualtext' then
if snak.datavalue.value['language'] == "en" then
return snak.datavalue.value['text']
else
return nil
end
elseif snak.datavalue.type == 'quantity' then
-- strip + signs from front
local value = mw.ustring.gsub(snak.datavalue.value['amount'], "\+(.+)", "%1")
if appendUnit then
local unit = convertUnit(snak.datavalue.value['unit'])
if unit then
value = value .. unit
end
end
return value
elseif snak.datavalue.type == 'wikibase-entityid' then
local itemID = "Q" .. snak.datavalue.value['numeric-id']
local value = mw.wikibase.label(itemID)
local target = mw.wikibase.sitelink(itemID)
if linked then
if target then
value = "[[" .. target .. "|" .. (value or target) .. "]]"
elseif not value then
value = "[[:d:" .. itemID .. "|" .. itemID .. "]]"
end
elseif not value then
value = (target or itemID)
end
return value
else
return unknownDatatypeError(snak.datavalue.type)
end
elseif snak.snaktype == 'somevalue' then
return "unknown"
elseif snak.snaktype == 'novalue' then
return "none"
else
return nil
end
end,
getRawValue = function(snak)
local temp, value
if snak.snaktype == 'value' and snak.datavalue.type == 'wikibase-entityid' then
return "Q" .. snak.datavalue.value['numeric-id']
else
temp = linked
linked = false
value = getValue(snak, false)
linked = temp
return value
end
end,
snakEqualsValue = function(snak, value)
if snak.snaktype == 'value' then
local snakValue = getRawValue(snak)
if snakValue and snak.datavalue.type == 'wikibase-entityid' then value = value:upper() end
return snakValue == value
elseif snak.snaktype == 'somevalue' then
if value == " " then -- single space represents 'somevalue'
return true
else
return false
end
elseif snak.snaktype == 'novalue' then
if value == "" then -- empty value represents 'novalue'
return true
else
return false
end
else
return false
end
end,
setRankBoundaries = function(rank)
local rankPos
if (rank == "best") then
bestRank = true
foundRank = 3
return
else
bestRank = false
end
if (rank == "all") then
maxRank = 1
minRank = 3
return
end
if (rank:sub(1,9) == "preferred") then
rankPos = 1
elseif (rank:sub(1,6) == "normal") then
rankPos = 2
elseif (rank:sub(1,10) == "deprecated") then
rankPos = 3
end
if (rank:sub(-1) == "+") then
maxRank = 1
minRank = rankPos
elseif (rank:sub(-1) == "-") then
maxRank = rankPos
minRank = 3
else
maxRank = rankPos
minRank = rankPos
end
end,
convertRank = function(rank)
if (rank == "preferred") then
return 1
elseif (rank == "normal") then
return 2
elseif (rank == "deprecated") then
return 3
else
return 4 -- default (in its literal sense)
end
end,
rankMatches = function(rankPos)
if bestRank then
if foundRank > rankPos then
foundRank = rankPos
-- found a better rank, reset worse rank outputs
if foundRank == 1 then
outNormal = {}
outDeprecated = {}
elseif foundRank == 2 then
outDeprecated = {}
end
end
return foundRank >= rankPos -- == would also work here
else
return (maxRank <= rankPos and rankPos <= minRank)
end
end,
appendOutput = function(value, rankPos)
if rankPos == 1 then
outPreferred[#outPreferred + 1] = value
elseif rankPos == 2 then
outNormal[#outNormal + 1] = value
elseif rankPos == 3 then
outDeprecated[#outDeprecated + 1] = value
end
end,
out = function()
local out = ""
outPreferred = table.concat(outPreferred, ", ")
outNormal = table.concat(outNormal, ", ")
outDeprecated = table.concat(outDeprecated, ", ")
if outPreferred ~= "" then
out = outPreferred
end
if outNormal ~= "" then
if out ~= "" then
out = out .. "; "
end
out = out .. outNormal
end
if outDeprecated ~= "" then
if out ~= "" then
out = out .. "; "
end
out = out .. outDeprecated
end
return out
end,
processFlag = function(flag)
if flag == "linked" then
linked = true
return true
elseif flag == "unit" then
withUnit = true
return true
elseif flag == "best" or flag == "all" or flag:match('^preferred[+-]?$') or flag:match('^normal[+-]?$') or flag:match('^deprecated[+-]?$') then
setRankBoundaries(flag)
return true
else
return false
end
end
}
end
p.property = function(frame)
local s = newState()
local entity, propertyID, claims, rankPos, value
local nextArg = mw.text.trim(frame.args[1] or "")
local nextIndex = 2
s.setRankBoundaries("best")
while s.processFlag(nextArg) do
nextArg = mw.text.trim(frame.args[nextIndex] or "")
nextIndex = nextIndex + 1
end
if nextArg:sub(1,1):upper() == "Q" then
entity = mw.wikibase.getEntity(nextArg)
propertyID = mw.text.trim(frame.args[nextIndex] or "")
else
entity = mw.wikibase.getEntity()
propertyID = nextArg
end
if entity and entity.claims then claims = entity.claims[propertyID] end
if claims then
for k, v in pairs(claims) do
rankPos = s.convertRank(v.rank)
if s.rankMatches(rankPos) then
value = s.getValue(v.mainsnak, withUnit)
if value then s.appendOutput(value, rankPos) end
end
end
return s.out()
else
return ""
end
end
p.qualifier = function(frame)
local entity, propertyID, propertyValue, qualifierID, claims, qualifiers, rankPos, outValue, outInter, outQualifier
local nextArg = mw.text.trim(frame.args[1] or "")
local nextIndex = 2
setRankBoundaries("best")
while processFlag(nextArg) do
nextArg = mw.text.trim(frame.args[nextIndex] or "")
nextIndex = nextIndex + 1
end
if nextArg:sub(1,1):upper() == "Q" then
entity = mw.wikibase.getEntity(nextArg)
propertyID = mw.text.trim(frame.args[nextIndex] or "")
nextIndex = nextIndex + 1
else
entity = mw.wikibase.getEntity()
propertyID = nextArg
end
nextArg = frame.args[nextIndex]
nextIndex = nextIndex + 1
qualifierID = nextArg
nextArg = mw.text.trim(frame.args[nextIndex] or "")
nextIndex = nextIndex + 1
if nextArg == "" then
propertyValue = nil
qualifierID = mw.text.trim(qualifierID or "")
else
propertyValue = qualifierID -- cannot be nil when reached; empty value represents 'novalue'
if propertyValue ~= "" and mw.text.trim(propertyValue) == "" then
propertyValue = " " -- single space represents 'somevalue'
else
propertyValue = mw.text.trim(propertyValue)
end
qualifierID = nextArg
end
if entity and entity.claims then claims = entity.claims[propertyID] end
if claims then
for k, v in pairs(claims) do
rankPos = convertRank(v.rank)
if propertyValue == nil or snakEqualsValue(v.mainsnak, propertyValue) then
if rankMatches(rankPos) then
outValue = nil
outInter = nil
outQualifier = {}
if propertyWithQualifier then
outValue = getValue(v.mainsnak, withUnit)
end
if v.qualifiers then qualifiers = v.qualifiers[qualifierID] end
if (not propertyWithQualifier or outValue) and qualifiers then
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
outInter = getValue(v2, withUnit)
if outInter then
if not propertyWithQualifier then
appendOutput(outInter, rankPos)
else
outQualifier[#outQualifier + 1] = outInter
end
end
end
end
if outValue and propertyWithQualifier then
outQualifier = table.concat(outQualifier, ", ")
if outQualifier ~= "" then
outQualifier = " <span style=\"font-size:smaller\">(" .. outQualifier .. ")</span>"
outValue = outValue .. outQualifier
end
appendOutput(outValue, rankPos)
end
end
end
end
return out()
else
return ""
end
end
p.propertyWithQualifier = function(frame)
propertyWithQualifier = true
withUnit = true
return p.qualifier(frame)
end
p.label = function(frame)
local label, target
local nextArg = mw.text.trim(frame.args[1] or "")
local nextIndex = 2
while processFlag(nextArg) do
nextArg = mw.text.trim(frame.args[nextIndex] or "")
nextIndex = nextIndex + 1
end
if nextArg then
label = mw.wikibase.label(nextArg)
target = nil
if nextArg:sub(1,1):upper() == "Q" then
if linked or label == nil then
target = mw.wikibase.sitelink(nextArg)
end
if linked and target then
return "[[" .. target .. "|" .. (label or target) .. "]]"
end
end
return (label or target)
else
return mw.wikibase.label()
end
end
return p