en:Module:Wd 2017年10月22日 (日) 08:19(UTC)より
template>K-iczn (en:Module:Wd 2017年10月11日 (水) 06:56(UTC)より) |
template>K-iczn (en:Module:Wd 2017年10月22日 (日) 08:19(UTC)より) |
||
18行目: | 18行目: | ||
end | end | ||
p. | p.valueCommands = { | ||
property = "property", | property = "property", | ||
properties = "properties", | properties = "properties", | ||
24行目: | 24行目: | ||
qualifiers = "qualifiers", | qualifiers = "qualifiers", | ||
reference = "reference", | reference = "reference", | ||
references = "references" | references = "references" | ||
} | |||
p.nameCommands = { | |||
label = "label", | label = "label", | ||
title = "title", | title = "title", | ||
118行目: | 121行目: | ||
["sep%r"] = nil, -- none | ["sep%r"] = nil, -- none | ||
["punc"] = nil -- none | ["punc"] = nil -- none | ||
} | |||
local rankTable = { | |||
["preferred"] = 1, | |||
["normal"] = 2, | |||
["deprecated"] = 3 | |||
} | } | ||
200行目: | 209行目: | ||
end | end | ||
function replaceAlias( | function replaceAlias(id) | ||
if p.aliasesP[ | if p.aliasesP[id] then | ||
id = p.aliasesP[id] | |||
end | end | ||
return | return id | ||
end | end | ||
function errorText(code, param) | function errorText(code, param) | ||
local | local text = i18n["errors"][code] | ||
if param then | if param then text = mw.ustring.gsub(text, "$1", param) end | ||
return | return text | ||
end | end | ||
function throwError(errorMessage, param) | function throwError(errorMessage, param) | ||
error(errorText(errorMessage, param)) | error(errorText(errorMessage, param)) | ||
302行目: | 312行目: | ||
function parseWikidataURL(url) | function parseWikidataURL(url) | ||
local | local id | ||
if url:match('^http[s]?://') then | if url:match('^http[s]?://') then | ||
id = split(url, "Q") | |||
if | if id[2] then | ||
return "Q" .. | return "Q" .. id[2] | ||
end | end | ||
end | end | ||
575行目: | 585行目: | ||
return root, params | return root, params | ||
end | end | ||
595行目: | 593行目: | ||
for i, v in ipairs(claims) do | for i, v in ipairs(claims) do | ||
rankPos = | rankPos = rankTable[v.rank] or 4 | ||
ranks[rankPos][#ranks[rankPos] + 1] = v | ranks[rankPos][#ranks[rankPos] + 1] = v | ||
end | end | ||
606行目: | 604行目: | ||
end | end | ||
-- if | -- if id == nil then item connected to current page is used | ||
function Config:getLabel(id, raw, link, short) | |||
function Config:getLabel( | |||
local label = nil | local label = nil | ||
local title = nil | local title = nil | ||
local prefix= "" | local prefix= "" | ||
local lang | local lang | ||
if not id then | |||
id = mw.wikibase.getEntityIdForCurrentPage() | |||
if not id then | |||
return "" | |||
end | |||
end | |||
id = id:upper() -- just to be sure | |||
if raw then | if raw then | ||
if | -- check if given id actually exists | ||
if mw.wikibase.getEntity(id) then | |||
label = id | |||
label = | |||
if | if id:sub(1,1) == "P" then | ||
prefix = "Property:" | prefix = "Property:" | ||
end | end | ||
645行目: | 637行目: | ||
-- try short name first if requested | -- try short name first if requested | ||
if short then | if short then | ||
label = | label = p._property({p.aliasesP.shortName, [p.args.eid] = id}) -- get short name | ||
if label == "" then | if label == "" then | ||
654行目: | 646行目: | ||
-- get label | -- get label | ||
if not label then | if not label then | ||
label, lang = mw.wikibase.getLabelWithLang( | label, lang = mw.wikibase.getLabelWithLang(id) | ||
-- don't allow language fallback | -- don't allow language fallback | ||
668行目: | 660行目: | ||
-- build a link if requested | -- build a link if requested | ||
if not title then | if not title then | ||
if | if id:sub(1,1) == "Q" then | ||
title = mw.wikibase.sitelink(id) | |||
elseif id:sub(1,1) == "P" then | |||
title = mw.wikibase.sitelink( | |||
elseif | |||
-- properties have no sitelink, link to Wikidata instead | -- properties have no sitelink, link to Wikidata instead | ||
title = | title = id | ||
prefix = "d:Property:" | prefix = "d:Property:" | ||
end | end | ||
757行目: | 747行目: | ||
function Config:convertUnit(unit, raw, link, short, unitOnly) | function Config:convertUnit(unit, raw, link, short, unitOnly) | ||
local space = " " | local space = " " | ||
local label = "" | local label = "" | ||
791行目: | 776行目: | ||
function Config:getValue(snak, raw, link, short, anyLang, unitOnly, noSpecial) | function Config:getValue(snak, raw, link, short, anyLang, unitOnly, noSpecial) | ||
if snak.snaktype == 'value' then | if snak.snaktype == 'value' then | ||
local datatype = snak.datavalue.type | |||
if | local subtype = snak.datatype | ||
local datavalue = snak.datavalue.value | |||
if datatype == 'string' then | |||
if subtype == 'url' and link then | |||
-- create link explicitly | -- create link explicitly | ||
if raw then | if raw then | ||
-- will render as a linked number like [1] | -- will render as a linked number like [1] | ||
return "[" . | return "[" .. datavalue .. "]" | ||
else | else | ||
return "[" . | return "[" .. datavalue .. " " .. datavalue .. "]" | ||
end | end | ||
elseif | elseif subtype == 'commonsMedia' then | ||
if link then | if link then | ||
return buildWikilink("c:File:" . | return buildWikilink("c:File:" .. datavalue, datavalue) | ||
elseif not raw then | elseif not raw then | ||
return "[[File:" . | return "[[File:" .. datavalue .. "]]" | ||
else | else | ||
return | return datavalue | ||
end | end | ||
elseif | elseif subtype == 'geo-shape' and link then | ||
return buildWikilink("c:" . | return buildWikilink("c:" .. datavalue, datavalue) | ||
elseif | elseif subtype == 'math' and not raw then | ||
return mw.getCurrentFrame():extensionTag("math", | return mw.getCurrentFrame():extensionTag("math", datavalue) | ||
else | else | ||
return | return datavalue | ||
end | end | ||
elseif | elseif datatype == 'monolingualtext' then | ||
if anyLang then | if anyLang then | ||
return | return datavalue['text'], datavalue['language'] | ||
elseif | elseif datavalue['language'] == self.langCode then | ||
return | return datavalue['text'] | ||
else | else | ||
return nil | return nil | ||
end | end | ||
elseif | elseif datatype == 'quantity' then | ||
local value = "" | local value = "" | ||
local unit | local unit | ||
837行目: | 819行目: | ||
if not unitOnly then | if not unitOnly then | ||
-- get value and strip + signs from front | -- get value and strip + signs from front | ||
value = mw.ustring.gsub( | value = mw.ustring.gsub(datavalue['amount'], "^\+(.+)$", "%1") | ||
if raw then | if raw then | ||
850行目: | 832行目: | ||
end | end | ||
unit = self:convertUnit( | unit = self:convertUnit(datavalue['unit'], raw, link, short, unitOnly) | ||
if unit then | if unit then | ||
857行目: | 839行目: | ||
return value | return value | ||
elseif | elseif datatype == 'time' then | ||
local y, m, d, p, yDiv, yRound, yFull, value, calendarID, dateStr | local y, m, d, p, yDiv, yRound, yFull, value, calendarID, dateStr | ||
local yFactor = 1 | local yFactor = 1 | ||
865行目: | 847行目: | ||
local mayAddCalendar = false | local mayAddCalendar = false | ||
local calendar = "" | local calendar = "" | ||
local precision = | local precision = datavalue['precision'] | ||
if precision == 11 then | if precision == 11 then | ||
876行目: | 858行目: | ||
end | end | ||
y, m, d = parseDate( | y, m, d = parseDate(datavalue['time'], p) | ||
if y < 0 then | if y < 0 then | ||
1,002行目: | 984行目: | ||
if mayAddCalendar then | if mayAddCalendar then | ||
calendarID = parseWikidataURL( | calendarID = parseWikidataURL(datavalue['calendarmodel']) | ||
if calendarID and calendarID == aliasesQ.prolepticJulianCalendar then | if calendarID and calendarID == aliasesQ.prolepticJulianCalendar then | ||
1,065行目: | 1,047行目: | ||
return value | return value | ||
elseif | elseif datatype == 'globecoordinate' then | ||
-- logic from https://github.com/DataValues/Geo | -- logic from https://github.com/DataValues/Geo | ||
1,101行目: | 1,083行目: | ||
end | end | ||
latitude = | latitude = datavalue['latitude'] | ||
longitude = | longitude = datavalue['longitude'] | ||
if latitude < 0 then | if latitude < 0 then | ||
1,122行目: | 1,104行目: | ||
end | end | ||
precision = | precision = datavalue['precision'] | ||
latitude = math.floor(latitude / precision + 0.5) * precision | latitude = math.floor(latitude / precision + 0.5) * precision | ||
1,179行目: | 1,161行目: | ||
if link then | if link then | ||
globe = parseWikidataURL( | globe = parseWikidataURL(datavalue['globe']) | ||
if globe then | if globe then | ||
1,191行目: | 1,173行目: | ||
return value | return value | ||
elseif | elseif datatype == 'wikibase-entityid' then | ||
local label | local label | ||
local itemID = | local itemID = datavalue['numeric-id'] | ||
if | if subtype == 'wikibase-item' then | ||
itemID = "Q" .. itemID | itemID = "Q" .. itemID | ||
elseif | elseif subtype == 'wikibase-property' then | ||
itemID = "P" .. itemID | itemID = "P" .. itemID | ||
else | else | ||
return '<strong class="error">' .. errorText('unknown-data-type', | return '<strong class="error">' .. errorText('unknown-data-type', subtype) .. '</strong>' | ||
end | end | ||
1,211行目: | 1,193行目: | ||
return label | return label | ||
else | else | ||
return '<strong class="error">' .. errorText('unknown-data-type', | return '<strong class="error">' .. errorText('unknown-data-type', datatype) .. '</strong>' | ||
end | end | ||
elseif snak.snaktype == 'somevalue' and not noSpecial then | elseif snak.snaktype == 'somevalue' and not noSpecial then | ||
1,378行目: | 1,360行目: | ||
end | end | ||
if flag == p. | if flag == p.valueCommands.property or flag == p.valueCommands.properties then | ||
param = parameters.property | param = parameters.property | ||
elseif flag == p. | elseif flag == p.valueCommands.qualifier or flag == p.valueCommands.qualifiers then | ||
self.states.qualifiersCount = self.states.qualifiersCount + 1 | self.states.qualifiersCount = self.states.qualifiersCount + 1 | ||
param = parameters.qualifier .. self.states.qualifiersCount | param = parameters.qualifier .. self.states.qualifiersCount | ||
self.separators["sep"..param] = {copyTable(defaultSeparators["sep%q\\d"])} | self.separators["sep"..param] = {copyTable(defaultSeparators["sep%q\\d"])} | ||
elseif flag == p. | elseif flag == p.valueCommands.reference or flag == p.valueCommands.references then | ||
param = parameters.reference | param = parameters.reference | ||
else | else | ||
1,412行目: | 1,394行目: | ||
end | end | ||
function Config:qualifierMatches(claim, | function Config:qualifierMatches(claim, id, value) | ||
local qualifiers | local qualifiers | ||
if claim.qualifiers then qualifiers = claim.qualifiers[ | if claim.qualifiers then qualifiers = claim.qualifiers[id] end | ||
if qualifiers then | if qualifiers then | ||
for i, v in pairs(qualifiers) do | for i, v in pairs(qualifiers) do | ||
1,535行目: | 1,517行目: | ||
-- check if the claim's rank and time period match | -- check if the claim's rank and time period match | ||
rankPos = | rankPos = rankTable[claim.rank] or 4 | ||
matches = (matches and self.conf:rankMatches(rankPos) and self.conf:timeMatches(claim)) | matches = (matches and self.conf:rankMatches(rankPos) and self.conf:timeMatches(claim)) | ||
1,866行目: | 1,848行目: | ||
-- gets a detail of one particular type for a reference | -- gets a detail of one particular type for a reference | ||
function State:getReferenceDetail(snaks, dType, raw, link, anyLang, noUnset) | function State:getReferenceDetail(snaks, dType, raw, link, anyLang, noUnset) | ||
local switchLang = anyLang | local switchLang = anyLang | ||
local value = nil | local value = nil | ||
1,905行目: | 1,882行目: | ||
-- gets the details of one particular type for a reference | -- gets the details of one particular type for a reference | ||
function State:getReferenceDetails(snaks, dType, raw, link, anyLang, noUnset) | function State:getReferenceDetails(snaks, dType, raw, link, anyLang, noUnset) | ||
local values = {} | local values = {} | ||
2,046行目: | 2,018行目: | ||
end | end | ||
function | function extractEntityFromInput(id, allowUnknown) | ||
if id:sub(1,1):upper() == "Q" then | |||
return | return id:upper() | ||
elseif id:sub(1,9):lower() == "property:" then | |||
return replaceAlias(mw.text.trim(id:sub(10))):upper() -- entity ID of a property was given | |||
elseif allowUnknown and id ~= "" then | |||
return replaceAlias(id):upper() | |||
else | |||
return nil | |||
end | |||
end | end | ||
function | function extractEntityFromArgs(args, nextIndex, handleUnknownPos) | ||
local id, eidArg | |||
if args[nextIndex] then | |||
args[nextIndex] = mw.text.trim(args[nextIndex]) | |||
else | |||
args[nextIndex] = "" | |||
end | |||
id = extractEntityFromInput(args[nextIndex], handleUnknownPos) | |||
eidArg = args[p.args.eid] | |||
if id then | |||
return id, nextIndex + 1 | |||
elseif not eidArg then | |||
return mw.wikibase.getEntityIdForCurrentPage(), nextIndex -- by default, use item-entity connected to current page | |||
else | |||
return extractEntityFromInput(eidArg, true), nextIndex | |||
end | end | ||
return | |||
end | |||
end | end | ||
2,113行目: | 2,058行目: | ||
local hooks = {count = 0} | local hooks = {count = 0} | ||
local | local nextIndex = 1 | ||
-- process flags and commands | -- process flags and commands | ||
while _:processFlagOrCommand( | while _:processFlagOrCommand(args[nextIndex]) do | ||
nextIndex = nextIndex + 1 | nextIndex = nextIndex + 1 | ||
end | end | ||
_.entityID, nextIndex = extractEntityFromArgs(args, nextIndex, false) | |||
-- if eid was expliclty set to empty, then this returns an empty string | |||
if _.entityID == nil then | |||
return "" | |||
end | end | ||
_.entity = mw.wikibase.getEntity(_.entityID) | |||
_.propertyID = replaceAlias(args[nextIndex]):upper() | |||
nextIndex = nextIndex + 1 | |||
if _.states.qualifiersCount > 0 then | |||
-- do further processing if "qualifier(s)" command was given | |||
if _.states.qualifiersCount > 0 then | |||
-- do further processing if "qualifier(s)" command was given | |||
if #args - nextIndex + 1 > _.states.qualifiersCount then | if #args - nextIndex + 1 > _.states.qualifiersCount then | ||
2,177行目: | 2,087行目: | ||
for i = 1, _.states.qualifiersCount do | for i = 1, _.states.qualifiersCount do | ||
-- check if given qualifier ID is an alias and add it | |||
_.qualifierIDs[parameters.qualifier..i] = replaceAlias(mw.text.trim(args[nextIndex] or "")):upper() | |||
nextIndex = nextIndex + 1 | nextIndex = nextIndex + 1 | ||
end | end | ||
elseif _.states[parameters.reference] then | elseif _.states[parameters.reference] then | ||
-- do further processing if "reference(s)" command was given | -- do further processing if "reference(s)" command was given | ||
if args[nextIndex] then | |||
_.propertyValue = mw.text.trim(args[nextIndex]) | |||
_.propertyValue = mw.text.trim( | |||
end | end | ||
-- not incrementing nextIndex because it is never used after this | |||
end | end | ||
2,283行目: | 2,189行目: | ||
-- must come AFTER defining the hooks | -- must come AFTER defining the hooks | ||
if _.sourcedOnly and not _.states[parameters.reference] then | if _.sourcedOnly and not _.states[parameters.reference] then | ||
_:processFlagOrCommand(p. | _:processFlagOrCommand(p.valueCommands.reference) -- use singular "reference" to minimize overhead | ||
end | end | ||
2,325行目: | 2,231行目: | ||
return "" | return "" | ||
end | end | ||
end | end | ||
2,371行目: | 2,237行目: | ||
_.curState = State.new(_) | _.curState = State.new(_) | ||
local value = nil | local value = nil | ||
local nextIndex = 1 | |||
while _:processFlag(args[nextIndex]) do | |||
while _:processFlag( | |||
nextIndex = nextIndex + 1 | nextIndex = nextIndex + 1 | ||
end | end | ||
_.entityID, nextIndex = extractEntityFromArgs(args, nextIndex, true) | |||
-- | -- if eid was expliclty set to empty, then this returns an empty string | ||
if _.entityID == nil then | |||
return "" | |||
end | end | ||
-- serve according to the given command | -- serve according to the given command | ||
if funcName == p. | if funcName == p.nameCommands.label then | ||
value = _:getLabel( | value = _:getLabel(_.entityID, _.curState.rawValue, _.curState.linked, _.curState.shortName) | ||
elseif funcName == p. | elseif funcName == p.nameCommands.title then | ||
_.pageTitle = true | _.pageTitle = true | ||
if | if _.entityID:sub(1,1) == "Q" then | ||
value = mw.wikibase.sitelink(_.entityID) | |||
value = mw.wikibase.sitelink( | |||
end | end | ||
2,442行目: | 2,264行目: | ||
value = buildWikilink(value) | value = buildWikilink(value) | ||
end | end | ||
elseif funcName == p. | elseif funcName == p.nameCommands.alias or funcName == p.nameCommands.aliases then | ||
local aliases, parsedFormat, formatParams, sep | local aliases, parsedFormat, formatParams, sep | ||
local hooks = {count = 0} | local hooks = {count = 0} | ||
if funcName == p. | if funcName == p.nameCommands.alias then | ||
_.curState.singleValue = true | _.curState.singleValue = true | ||
end | end | ||
2,484行目: | 2,306行目: | ||
_.curState.puncMark = _.separators["punc"] | _.curState.puncMark = _.separators["punc"] | ||
_.entity = mw.wikibase.getEntity( | _.entity = mw.wikibase.getEntity(_.entityID) | ||
if _.entity and _.entity.aliases then aliases = _.entity.aliases[_.langCode] end | if _.entity and _.entity.aliases then aliases = _.entity.aliases[_.langCode] end | ||
2,501行目: | 2,323行目: | ||
return value | return value | ||
end | end | ||
-- modules that include this module should call the functions with an underscore prepended, e.g.: p._property(args) | |||
function establishCommands(commandList, commandFunc) | |||
for commandIndex, commandName in pairs(commandList) do | |||
local function wikitextWrapper(frame) | |||
loadSubmodules(frame) | |||
return commandFunc(copyTable(frame.args), commandName) | |||
end | |||
p[commandName] = wikitextWrapper | |||
local function luaWrapper(args) | |||
loadSubmodules() | |||
return commandFunc(args, commandName) | |||
end | |||
p["_" .. commandName] = luaWrapper | |||
end | |||
end | |||
establishCommands(p.valueCommands, valueCommand) | |||
establishCommands(p.nameCommands, nameCommand) | |||
-- main function that is supposed to be used by wrapper templates | -- main function that is supposed to be used by wrapper templates |