diff --git a/module_citeq.lua b/module_citeq.lua index ceead63..fe1f6fd 100644 --- a/module_citeq.lua +++ b/module_citeq.lua @@ -80,62 +80,16 @@ local function accept_value( param_val, wd_val ) return val end --- Split string of comma-separated first names into a table of initials -local function getInitials(str) - local initials = {} - for _, word in pairs(mw.text.split(str, ' ', true)) do - local initial = mw.text.trim(word) - if #initial > 0 then - table.insert(initials, initial:sub(1, 1):upper()) - end - end - return initials -end - --- Return initials given a first name string and a name-list-style value --- (e.g. 'vanc' for Vancouver, or APA) -local function getStyledNames(names, style) - -- Vancouver style (vanc) is handled by CS1: Doe JQ - if style == 'apa' then -- APA: Doe, J. Q. - return table.concat(getInitials(names), '. ') .. '.' - else - -- Otherwise, just remove any trailing commas from names - return mw.text.trim(names:gsub(', ', ' ')) - end -end - -- function to fetch a value to display -local function makelink(v, out, link, maxpos, wdl, namestyle) +local function makelink(v, out, link, maxpos, wdl) local label - local max_authors_displayed = 10 -- TODO: this is probably in CS1 config somewhere - local item_lookup = false if v.mainsnak.snaktype == "value" then if v.mainsnak.datatype == "wikibase-item" then local qnumber = v.mainsnak.datavalue.value.id local sitelink = mw.wikibase.getSitelink(qnumber) if qnumber == "Q2818964" then sitelink = nil end -- suppress link to "Various authors" - - -- Last name, first name(s) from "author given names" and "author last names" qualifiers - local last_name - local first_names - if v.qualifiers and v.qualifiers.P9688 and v.qualifiers.P9688[1] then - last_name = v.qualifiers.P9688[1].datavalue.value - end - if v.qualifiers and v.qualifiers.P9687 and v.qualifiers.P9687[1] then - first_names = v.qualifiers.P9687[1].datavalue.value - end - -- Otherwise, get last name, first name(s) from author item properties - -- but this requires a getValue WD item lookup for each author, and - -- lookups are limited to 500 per page, so do this after we have the - -- "series ordinal" order, then only do the first few since there are - -- article items out there with 400+ authors(!) - if not last_name or not first_names then - item_lookup = true - end - - -- use object named as for the label if v.qualifiers and v.qualifiers.P1932 then - label = v.qualifiers.P1932[1].datavalue.value -- "object named as" + label = v.qualifiers.P1932[1].datavalue.value -- object named as else label = mw.wikibase.getLabel(qnumber) if label then @@ -146,32 +100,14 @@ local function makelink(v, out, link, maxpos, wdl, namestyle) 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) + 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) - - -- now try determining first/last names with item lookup, if needed - if item_lookup and position <= max_authors_displayed then - last_name = last_name or getValue({"P734", qid=qnumber, maxvals=1, ps=2}) - first_names = first_names or getValue({"P735", qid=qnumber, maxvals=0, ps=2}) - end - if first_names then - first_names = getStyledNames(first_names, namestyle) - end - if sitelink then -- just the plain name, -- but keep a record of the links, using the same index - if last_name and first_names then - out[position] = { - label = label, - last = last_name or nil, - first = first_names or nil, - } - else - out[position] = label - end + out[position] = label link[position] = sitelink else if wdl then @@ -184,68 +120,24 @@ local function makelink(v, out, link, maxpos, wdl, namestyle) ) else -- no Wikidata links wanted, so just give the plain label - if last_name and first_names then - out[position] = { - label = label, - last = last_name or nil, - first = first_names or nil, - } - else - out[position] = label - end + out[position] = label end end elseif v.mainsnak.datatype == "string" then 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) + 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) - - -- Names from "author given names" and "author last names" qualifiers - local last_name - local first_names - if v.qualifiers and v.qualifiers.P9688 and v.qualifiers.P9688[1] then - last_name = v.qualifiers.P9688[1].datavalue.value - end - if v.qualifiers and v.qualifiers.P9687 and v.qualifiers.P9687[1] then - first_names = getStyledNames(v.qualifiers.P9687[1].datavalue.value, namestyle) - end - - if last_name and first_names then - out[position] = { - label = v.mainsnak.datavalue.value, - last = last_name or nil, - first = first_names or nil, - } - else - out[position] = v.mainsnak.datavalue.value - end + out[position] = v.mainsnak.datavalue.value else -- not a wikibase-item or a string! end else - -- try the "object named as" qualifier, otherwise use the unknown author item + -- code here if we want to return something when author is "unknown" if v.qualifiers and v.qualifiers.P1932 then - label = v.qualifiers.P1932[1].datavalue.value -- "object named as" - - -- Names from "author given names" and "author last names" qualifiers - local last_name - local first_names - if v.qualifiers and v.qualifiers.P9688 and v.qualifiers.P9688[1] then - last_name = v.qualifiers.P9688[1].datavalue.value - end - if v.qualifiers and v.qualifiers.P9687 and v.qualifiers.P9687[1] then - first_names = getStyledNames(v.qualifiers.P9687[1].datavalue.value, namestyle) - end - if last_name and first_names then - label = { - label = label, - last = last_name or nil, - first = first_names or nil, - } - end + label = v.qualifiers.P1932[1].datavalue.value else label = mw.wikibase.getLabel("Q4233718"):gsub("^%l", mw.ustring.upper) .. (cfg.i18n_t.trackingcats["unknown-author"] or "") end @@ -321,7 +213,7 @@ local function get_name_list (nl_type, args, qid, wdl) if props and props[1] then for k, v in pairs(props) do if 'deprecated' ~= v.rank then -- ignore deprecated names - maxpos = makelink(v, out, link, maxpos, wdl, args['name-list-style']) + maxpos = makelink(v, out, link, maxpos, wdl) end end end @@ -329,7 +221,7 @@ local function get_name_list (nl_type, args, qid, wdl) -- second properties for k, v in pairs(fallback) do if 'deprecated' ~= v.rank then -- ignore deprecated names - maxpos = makelink(v, out, link, maxpos, wdl, args['name-list-style']) + maxpos = makelink(v, out, link, maxpos, wdl) end end end @@ -343,27 +235,15 @@ local function get_name_list (nl_type, args, qid, wdl) end table.sort(keys) -- as they might be out of order for i, k in ipairs(keys) do - local label - if out[k].label then - label = out[k].label - else - label = out[k] - end - label = label:gsub(''', '\''); -- prevent cs1|2 multiple names categorization; replace html entity with the actual character - mw.log(i .. " " .. k .. " " .. label) + out[k] = out[k]:gsub (''', '\''); -- prevent cs1|2 multiple names categorization; replace html entity with the actual character + mw.log(i .. " " .. k .. " " .. (out[k])) if args[nl_type .. i] then -- name gets overwritten -- pull corresponding -link only if overwritten name is same as WD name - if link[k] and (args[nl_type .. i] == label) then + if link[k] and (args[nl_type .. i] == out[k]) then args[nl_type .. '-link' .. i] = args[nl_type .. '-link' .. i] or link[k] -- author-linkn or editor-linkn end else -- name does not get overwritten, so pull name from WD - if out[k].first and out[k].last then - -- First/last names were found, so add them - args[nl_type .. '-last' .. i] = args[nl_type .. '-last' .. i] or out[k].last - args[nl_type .. '-first' .. i] = args[nl_type .. '-first' .. i] or out[k].first - else - args[nl_type .. i] = label - end + args[nl_type .. i] = out[k] if link[k] then args[nl_type .. '-link' .. i] = args[nl_type .. '-link' .. i] or link[k] -- author-linkn or editor-linkn end @@ -393,12 +273,11 @@ end -- gets the language codes of a Wikidata entry as a table local function _lang_code(qid) - -- P407 "language of work or name" - local lc = _getPropOfProp( {qid = qid, prop1 = "P407", prop2 = "P424", ps = 1} ) -- "Wikimedia language code" + local lc = _getPropOfProp( {qid = qid, prop1 = "P407", prop2 = "P424", ps = 1} ) if lc then return mw.text.split( lc, "[, ]+" ) end - lc = _getPropOfProp( {qid = qid, prop1 = "P407", prop2 = "P218", ps = 1} ) -- "ISO 639-1 code" + lc = _getPropOfProp( {qid = qid, prop1 = "P407", prop2 = "P218", ps = 1} ) if lc then return mw.text.split( lc, "[, ]+" ) end - return _getLangOfProp(qid, "P1476") -- "title" + return _getLangOfProp(qid, "P1476") end local function lang_code(frame) return table.concat(_lang_code(frame.args.qid or mw.text.trim(frame.args[1] or "")), ", ") @@ -423,11 +302,8 @@ local function yearFromDate(datestr) return datestr end --- Attempt to determine heuristically what we're citing -local function getTemplateFromInstance(qid, args) - local chapteritems = { - 'Q1980247', -- chapter - } +-- Attempt to determine heuristically if we're citing a news article +local function isNewsArticle(qid, args) local newsitems = { 'Q5707594', -- news article 'Q30070590', -- magazine article @@ -446,9 +322,7 @@ local function getTemplateFromInstance(qid, args) } -- most of the time a cheap lookup to a single value will work if args['instance-of'] and in_array(args['instance-of'], newsitems) then - return 'news' - elseif args['instance-of'] and in_array(args['instance-of'], chapteritems) then - return 'chapter' + return true end -- otherwise check multiple non-deprecated values local instance_of = mw.wikibase.getBestStatements(qid, 'P31') @@ -456,14 +330,12 @@ local function getTemplateFromInstance(qid, args) for k, v in pairs(instance_of) do if v.mainsnak.snaktype == "value" and v.mainsnak.datatype == "wikibase-item" then if in_array(v.mainsnak.datavalue.value.id, newsitems) then - return 'news' - elseif in_array(v.mainsnak.datavalue.value.id, chapteritems) then - return 'chapter' + return true end end end end - return '' + return false end -- Figure out a URL access value, from the "online access status" (P6954) qualifier of an identifier @@ -830,20 +702,14 @@ local function _cite_q (citeq_args) -- code to make a guess what template to use from the supplied parameters -- (first draft for proof-of-concept) local pubyear = yearFromDate(citeq_args['publication-date']) - local guessedType = getTemplateFromInstance(qid, citeq_args) - if guessedType == 'news' then + local is_news = isNewsArticle(qid, citeq_args) + if is_news then template = template or "news" -- some items use P123 (publisher) as the newspaper instead of P1433 (published in) if citeq_args.publisher and not citeq_args.journal then citeq_args.journal = citeq_args.publisher citeq_args.publisher = nil end - elseif guessedType == 'chapter' then - template = template or "book" - citeq_args['publication-date'] = pubyear or citeq_args['publication-date'] - citeq_args.chapter = citeq_args.title - citeq_args.title = citeq_args.journal - citeq_args.journal = nil elseif citeq_args.journal then template = template or "journal" citeq_args['publication-date'] = pubyear or citeq_args['publication-date'] @@ -1008,9 +874,6 @@ local function _cite_q (citeq_args) -- remove any remaining non-CS1 fields citeq_args['instance-of'] = nil - if citeq_args['name-list-style'] and citeq_args['name-list-style'] == 'apa' then - citeq_args['name-list-style'] = nil - end -- render the template local lc_template = template and template:lower() or "citation"