モジュール:Citeq
モジュールの解説[作成]
require('strict')
local wdib = require('Module:WikidataIB')
local getValue = wdib._getValue
local getPropOfProp = wdib._getPropOfProp
local followQid = wdib._followQid
local simple_properties = { -- PXXX, is multiple?, linked?
publisher = {id="P123", maxvals=1},
oclc = {id="P243", maxvals=1},
place = {id="P291", maxvals=0,linked='no'},
doi = {id="P356", maxvals=1},
issue = {id="P433", maxvals=1, populate_from_journal = true},
pmid = {id="P698", maxvals=1},
arxiv = {id="P818", maxvals=1},
bibcode = {id="P819", maxvals=1},
jstor = {id="P888", maxvals=1},
mr = {id="P889", maxvals=1},
ssrn = {id="P893", maxvals=1},
pmc = {id="P932", maxvals=1},
lccn = {id="P1144", maxvals=1},
hdl = {id="P1184", maxvals=1},
ismn = {id="P1208", maxvals=1},
journal = {id="P1433", maxvals=1},
citeseerx = {id="P3784", maxvals=1},
osti = {id="P3894", maxvals=1},
biorxiv = {id="P3951", maxvals=1},
isbn = {id="P212", maxvals=1, populate_from_journal = true}, -- ISBN 13
issn = {id="P236", maxvals=1, populate_from_journal = true},
chapter = {id="P792", maxvals=1},
["date"] = {id="P577", maxvals=1, populate_from_journal = true},
series = {id="P179", maxvals=1, populate_from_journal = true},
volume = {id="P478", maxvals=1, populate_from_journal = true},
title = {id="P1476", maxvals=1},
url = {id="P953", maxvals=1}, -- full work available at
pages = {id="P304", maxvals=1, populate_from_journal = true},
translator = {id="P655", maxvals=0}, -- does **not** go to "others" section!
illustrator = {id="P110", maxvals=0, others=true}, -- goes to "others" section
composer = {id="P86", maxvals=0, others=true}, -- goes to "others" section
animator = {id="P6942", maxvals=0, others=true}, -- goes to "others" section
director = {id="P57", maxvals=0, others=true}, -- goes to "others" section
screenwriter = {id="P58", maxvals=0, others=true}, -- goes to "others" section
}
local citeq = {}
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
]]
local function is_set( var )
return not (var == nil or var == '');
end
--[=[-------------------------< G E T _ N A M E _ L I S T >----------------------------------------------------
get_name_list -- adapted from getAuthors code taken from [[Module:RexxS]]
arguments:
nl_type - type of name list to fetch: nl_type = 'author' for authors; 'editor' for editors
args - pointer to the parameter arguments table from the template call
qid - value from |qid= parameter; the Q-id of the source (book, etc.) in qid
wdl - value from the |wdlinks= parameter; a boolean passed to enable links to Wikidata when no article exists
returns nothing; modifies the args table
]=]
local function get_name_list (nl_type, args, qid, wdl)
local propertyID = "P50"
local fallbackID = "P2093" -- author name string
if 'author' == nl_type then
propertyID = 'P50'; -- for authors
fallbackID = 'P2093';
elseif 'editor' == nl_type then
propertyID = 'P98'; -- for editors
fallbackID = nil;
else
return; -- not specified so return
end
-- wdlinks is a boolean passed to enable links to Wikidata when no article exists
-- if "false" or "no" or "0" is passed set it false
-- if nothing or an empty string is passed set it false
if wdl and (#wdl > 0) then
wdl = wdl:lower()
wdl = (wdl == "false") or (wdl == "no") or (wdl == "0")
else
-- wdl is empty, so
wdl = false
end
local entity = mw.wikibase.getEntity(qid)
local props = nil
local fallback = nil
if entity and entity.claims then
props = entity.claims[propertyID]
if fallbackID then
fallback = entity.claims[fallbackID]
end
end
-- Make sure it actually has at least one of the properties requested
if not (props and props[1]) and not (fallback and fallback[1]) then
return nil
end
-- So now we have something to return:
-- table 'out' is going to store the names(s):
-- and table 'link' will store any links to the name's article
local out = {}
local link = {}
local maxpos = 0
if props and props[1] then
for k, v in pairs(props) do
local qnumber = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
local sitelink = mw.wikibase.sitelink(qnumber)
local label = mw.wikibase.label(qnumber)
if label then
label = mw.text.nowiki(label)
else
label = qnumber
end
local position = maxpos + 1 -- Default to 'next' author.
-- use P1545 (series ordinal) instead of default position.
if v["qualifiers"] and v.qualifiers["P1545"] and v.qualifiers["P1545"][1] then
position = tonumber(v.qualifiers["P1545"][1].datavalue.value)
end
maxpos = math.max(maxpos, position)
if sitelink then
-- just the plain name,
-- but keep a record of the links, using the same index
out[position] = label
link[position] = sitelink
else
-- no sitelink, so check first for a redirect with that label
-- this code works, but causes the article to appear in WhatLinksHere for the possible destination, so remove
-- local artitle = mw.title.new(label, 0)
-- if artitle.id > 0 then
-- if artitle.isRedirect then
-- no sitelink,
-- but there's a redirect with the same title as the label;
-- so store the link to that
-- out[position] = label
-- link[position] = label
-- else
-- no sitelink and not a redirect but an article exists with the same title as the label
-- that's probably a dab page, so output the plain label
-- out[position] = label
-- end
--else
-- no article or redirect with the same title as the label
if wdl then
-- show that there's a Wikidata entry available
out[position] = "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]] <span title='" .. i18n["errors"]["local-article-not-found"] .. "'>[[File:Wikidata-logo.svg|16px|alt=|link=]]</span>"
else
-- no wikidata links wanted, so just give the plain label
out[position] = label
end
-- end
end
end
end
if fallback and fallback[1] then
-- Fallback to name-only authors / editors
for k, v in pairs(fallback) do
local label = v.mainsnak.datavalue["value"]
local position = maxpos + 1 -- Default to 'next' author.
-- use P1545 (series ordinal) instead of default position.
if v["qualifiers"] and v.qualifiers["P1545"] and v.qualifiers["P1545"][1] then
position = tonumber(v.qualifiers["P1545"][1].datavalue.value)
end
maxpos = math.max(maxpos, position)
out[position] = label
end
end
-- if there's anything to return, then insert the additions in the template arguments table
-- in the form |author1=firstname secondname |author2= ...
-- Renumber, in case we have inconsistent numbering
local keys = {}
for k,v in pairs(out) do
keys[#keys+1] = k
end
table.sort(keys) -- as they might be out of order
for i, k in ipairs(keys) do
mw.log(i.." "..k.." "..out[k])
args[nl_type .. i] = out[k] -- author-n or editor-n
if link[k] then
args[nl_type .. '-link' .. i] = link[k] -- author-linkn or editor-linkn
end
end
end
--[[-------------------------< C I T E _ Q >------------------------------------------------------------------
Takes standard cs1|2 template parameters and passes all to {{citation}}. If neither of |author= and |author1=
are set, calls get_authors() to try to get an author name-list from wikidata. The result is passed to
{{citation}} for rendering.
]]
local function wrap_nowiki(str)
return mw.text.nowiki(str or '')
end
function citeq.cite_q (frame)
local citeq_args = {};
for k, v in pairs(frame:getParent().args) do
citeq_args[k] = v
end
for k, v in pairs(frame.args) do
citeq_args[k] = v
end
local qid = citeq_args.qid
local wdl = citeq_args.wdl
citeq_args.qid = nil
citeq_args.wdl = nil
local oth = {}
citeq_args.language = citeq_args.language or getPropOfProp( {qid = qid, prop1 = "P407", prop2 = "P218", ps = 1} )
if citeq_args.language == '' then
citeq_args.language = nil
end
if not citeq_args.language then
-- try fallback to journal's language
local journal_qid = followQid({qid = qid, props = "P1433"})
citeq_args.language = journal_qid and getPropOfProp( {qid = journal_qid, prop1 = "P407", prop2 = "P218", ps = 1} )
end
for name, data in pairs(simple_properties) do
citeq_args[name] = getValue( {data.id, ps = 1, qid = qid, maxvals=data.maxvals, linked=data.linked, citeq_args[name] } )
if data.populate_from_journal then
citeq_args[name] = getValue( {"P1433", ps = 1, qid = qid, maxvals=0, citeq_args[name], qual=data.id, qualsonly='yes'} )
citeq_args[name] = citeq_args[name] or getPropOfProp({qid = qid, prop1 = "P1433", prop2 = data.id, maxvals=data.maxvals, ps = 1})
end
if citeq_args[name] and citeq_args[name]:find('[[Category:Articles with missing Wikidata information]]', 1, true) then
-- try fallback to work's native language
citeq_args[name] = getValue( {data.id, ps = 1, qid = qid, maxvals=data.maxvals, linked="no", lang = citeq_args.language } )
if citeq_args[name]:find('^Q%d+$') then -- qid was returned
-- try fallback to qid's native language
local qid_language = getPropOfProp( {qid = citeq_args[name], prop1 = "P407", prop2 = "P218", ps = 1} )
citeq_args[name] = getValue( {data.id, ps = 1, qid = qid, maxvals=data.maxvals, linked="no", lang = qid_language } )
if citeq_args[name]:find('^Q%d+$') then -- qid was returned again
citeq_args[name] = nil
end
end
end
if data.others then
oth[#oth+1] = citeq_args[name] and (name:gsub("^%l", string.upper) .. ": " .. citeq_args[name])
citeq_args[name] = nil
end
end
citeq_args.others = citeq_args.others or table.concat(oth, ". ")
citeq_args.journal = citeq_args.journal and citeq_args.journal:gsub("^''", ""):gsub("''$", ""):gsub("|''", "|"):gsub("'']]", "]]")
citeq_args.ol = (getValue( {"P648", ps = 1, qid = qid, maxvals=1, citeq_args.ol } ) or ''):gsub("^OL(.+)$", "%1")
citeq_args.biorxiv = citeq_args.biorxiv and ("10.1101/" .. citeq_args.biorxiv)
citeq_args.isbn = getValue( {"P957", ps = 1, qid = qid, maxvals=0, citeq_args.isbn } ) -- try ISBN 10
citeq_args.url = getValue( {"P856", ps = 1, qid = qid, maxvals=0, citeq_args.url } ) -- try official website
citeq_args.url = getValue( {"P2699", ps = 1, qid = qid, maxvals=0, citeq_args.url } ) -- try url
local slink = mw.wikibase.getSitelink(qid)
local label = mw.wikibase.getLabel(qid) or citeq_args.language and mw.wikibase.getLabelByLang(qid, citeq_args.language)
if citeq_args.title then
if slink then
citeq_args.url = nil
citeq_args.title = '[[' .. slink .. '|' .. wrap_nowiki(citeq_args.title) .. ']]'
else
citeq_args.title = wrap_nowiki(citeq_args.title)
end
else
if slink then
citeq_args.url = nil
if slink:lower() == label:lower() then
citeq_args.title = '[[' .. slink .. ']]'
else
citeq_args.title = '[[' .. slink .. '|' .. wrap_nowiki(slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "")) .. ']]'
end
else
citeq_args.title = wrap_nowiki(label)
end
end
if citeq_args.p or citeq_args.page then
citeq_args.pages = nil
end
if citeq_args.pages then
local _, count = string.gsub(citeq_args.pages, " %d+", "")
if count == 1 then
citeq_args.p = citeq_args.pages
citeq_args.pages = nil
end
end
for k, v in pairs(citeq_args) do
if v == 'unset' or type(k) ~= 'string' then
citeq_args[k] = nil
end
end
if is_set (qid) then
if not is_set (citeq_args.author) and not is_set (citeq_args.author1) then -- if neither are set, try to get authors from wikidata
get_name_list ('author', citeq_args, qid, wdl); -- modify citeq_args table with authors from wikidata
end
if not is_set (citeq_args.editor) and not is_set (citeq_args.editor1) then -- if neither are set, try to get editors from wikidata
get_name_list ('editor', citeq_args, qid, wdl); -- modify citeq_args table with editors from wikidata
end
end
local author_count = 0
for k, v in pairs(citeq_args) do
if k:find("^author%d+$") then
author_count = author_count + 1
end
end
if author_count > 8 then -- convention in astronomy journals
citeq_args['display-authors'] = citeq_args['display-authors'] or 3
end
local editor_count = 0
for k, v in pairs(citeq_args) do
if k:find("^editor%d+$") then
editor_count = editor_count + 1
end
end
if editor_count > 8 then -- convention in astronomy journals
citeq_args['display-editors'] = citeq_args['display-editors'] or 3
end
local returntext = frame:expandTemplate{title = 'citation', args = citeq_args} -- render the template
if citeq_args.mode ~= 'cs1' then
returntext = returntext .. ','
end
returntext = returntext .. ' [[WDQ (識別子)|Wikidata]] [[:d:' .. qid .. '|' .. qid .. ']]' -- go through special "WDQ (identifier)" redirect to reduce clutter in "What links here" and improve reverse lookup. (A better name might be "QID (identifier)", but needs to be kept in sync with what's used by Template:QID.)
return returntext
end
return citeq