http://collaborativecollections.org/WorldWarOne/index.php?title=Module:Citation/CS1/COinS&feed=atom&action=historyModule:Citation/CS1/COinS - Revision history2024-03-29T14:50:06ZRevision history for this page on the wikiMediaWiki 1.27.0http://collaborativecollections.org/WorldWarOne/index.php?title=Module:Citation/CS1/COinS&diff=20264&oldid=prevGavinRobinson: 1 revision imported2016-04-05T16:20:34Z<p>1 revision imported</p>
<table class="diff diff-contentalign-left" data-mw="interface">
<tr style='vertical-align: top;' lang='en-GB'>
<td colspan='1' style="background-color: white; color:black; text-align: center;">← Older revision</td>
<td colspan='1' style="background-color: white; color:black; text-align: center;">Revision as of 16:20, 5 April 2016</td>
</tr><tr><td colspan='2' style='text-align: center;' lang='en-GB'><div class="mw-diff-empty">(No difference)</div>
</td></tr></table>GavinRobinsonhttp://collaborativecollections.org/WorldWarOne/index.php?title=Module:Citation/CS1/COinS&diff=20263&oldid=prevTrappist the monk: Protected "Module:Citation/CS1/COinS": High-risk Lua module ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))2016-01-15T14:31:31Z<p>Protected "<a href="/WorldWarOne/Module:Citation/CS1/COinS" title="Module:Citation/CS1/COinS">Module:Citation/CS1/COinS</a>": <a href="/WorldWarOne/index.php?title=WP:High-risk_templates&action=edit&redlink=1" class="new" title="WP:High-risk templates (page does not exist)">High-risk Lua module</a> ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))</p>
<p><b>New page</b></p><div>local coins = {};<br />
<br />
<br />
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------<br />
]]<br />
<br />
local is_set, in_array, remove_wiki_link; -- functions in Module:Citation/CS1/Utilities<br />
<br />
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration<br />
<br />
<br />
--[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >--------------------------------<br />
<br />
Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata.<br />
This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to<br />
markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind.<br />
<br />
]]<br />
<br />
local function strip_apostrophe_markup (argument)<br />
if not is_set (argument) then return argument; end<br />
<br />
if argument:find ( "''", 1, true ) == nil then -- Is there at least one double apostrophe? If not, exit.<br />
return argument;<br />
end<br />
<br />
while true do<br />
if argument:find ( "'''''", 1, true ) then -- bold italic (5)<br />
argument=argument:gsub("%'%'%'%'%'", ""); -- remove all instances of it<br />
elseif argument:find ( "''''", 1, true ) then -- italic start and end without content (4)<br />
argument=argument:gsub("%'%'%'%'", "");<br />
elseif argument:find ( "'''", 1, true ) then -- bold (3)<br />
argument=argument:gsub("%'%'%'", "");<br />
elseif argument:find ( "''", 1, true ) then -- italic (2)<br />
argument=argument:gsub("%'%'", "");<br />
else<br />
break;<br />
end<br />
end<br />
return argument; -- done<br />
end<br />
<br />
<br />
--[[--------------------------< M A K E _ C O I N S _ T I T L E >----------------------------------------------<br />
<br />
Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs)<br />
<br />
Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings<br />
of %27%27...<br />
<br />
]]<br />
<br />
local function make_coins_title (title, script)<br />
if is_set (title) then<br />
title = strip_apostrophe_markup (title); -- strip any apostrophe markup<br />
else<br />
title=''; -- if not set, make sure title is an empty string<br />
end<br />
if is_set (script) then<br />
script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string)<br />
script = strip_apostrophe_markup (script); -- strip any apostrophe markup<br />
else<br />
script=''; -- if not set, make sure script is an empty string<br />
end<br />
if is_set (title) and is_set (script) then<br />
script = ' ' .. script; -- add a space before we concatenate<br />
end<br />
return title .. script; -- return the concatenation<br />
end<br />
<br />
<br />
--[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >----------------------------------<br />
<br />
Returns a string where all of lua's magic characters have been escaped. This is important because functions like<br />
string.gsub() treat their pattern and replace strings as patterns, not literal strings.<br />
]]<br />
<br />
local function escape_lua_magic_chars (argument)<br />
argument = argument:gsub("%%", "%%%%"); -- replace % with %%<br />
argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other lua magic pattern characters<br />
return argument;<br />
end<br />
<br />
<br />
--[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------<br />
<br />
Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS.<br />
<br />
]]<br />
<br />
local function get_coins_pages (pages)<br />
local pattern;<br />
if not is_set (pages) then return pages; end -- if no page numbers then we're done<br />
<br />
while true do<br />
pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the url and following space(s): "[url "<br />
if nil == pattern then break; end -- no more urls<br />
pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape lua's magic pattern characters<br />
pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible<br />
end<br />
pages = pages:gsub("[%[%]]", ""); -- remove the brackets<br />
pages = pages:gsub("–", "-" ); -- replace endashes with hyphens<br />
pages = pages:gsub("&%w+;", "-" ); -- and replace html entities (&ndash; etc.) with hyphens; do we need to replace numerical entities like &#32; and the like?<br />
return pages;<br />
end<br />
<br />
<br />
--[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------<br />
<br />
There are three options for math markup rendering that depend on the editor's math preference settings. These<br />
settings are at [[Special:Preferences#mw-prefsection-rendering]] and are<br />
PNG images<br />
TeX source<br />
MathML with SVG or PNG fallback<br />
<br />
All three are heavy with html and css which doesn't belong in the metadata.<br />
<br />
Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings<br />
of the last editor to save the page.<br />
<br />
This function gets the rendered form of an equation according to the editor's preference before the page is saved. It<br />
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so<br />
that the page is saved without extraneous html/css markup and with a reasonably readable text form of the equation.<br />
<br />
When a replacement is made, this function returns true and the value with replacement; otherwise false and the intital<br />
value. To replace multipe equations it is necesary to call this function from within a loop.<br />
<br />
]=]<br />
<br />
local function coins_replace_math_stripmarker (value)<br />
local stripmarker = '\127UNIQ%-%-math%-[%a%d]+%-QINU\127'; -- math stripmarker pattern<br />
local rendering = value:match (stripmarker); -- is there a math stripmarker<br />
<br />
if not rendering then -- when value doesn't have a math stripmarker, abandon this test<br />
return false, value;<br />
end<br />
<br />
rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error)<br />
<br />
if rendering:match ('alt="[^"]+"') then -- if PNG math option<br />
rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text<br />
elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$<br />
rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text<br />
elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option<br />
rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text<br />
else<br />
return false, value; -- had math stripmarker but not one of the three defined forms<br />
end<br />
<br />
return true, value:gsub (stripmarker, rendering, 1);<br />
end<br />
<br />
<br />
--[[--------------------------< C O I N S _ C L E A N U P >----------------------------------------------------<br />
<br />
Cleanup parameter values for the metadata by removing or replacing invisible characters and certain html entities.<br />
<br />
2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaced math stripmarkers with the appropriate content<br />
when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29<br />
<br />
TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible<br />
characters table?<br />
<br />
]]<br />
<br />
local function coins_cleanup (value)<br />
local replaced = true; -- default state to get the do loop running<br />
<br />
while replaced do -- loop until all math stripmarkers replaced<br />
replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation<br />
end<br />
<br />
value = value:gsub ('\127UNIQ%-%-math%-[%a%d]+%-QINU\127', "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message<br />
<br />
value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content<br />
value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">&#39;s</span>', "'s"); -- replace {{'s}} template with simple apostrophe-s<br />
value = value:gsub ('&zwj;\226\128\138\039\226\128\139', "'"); -- replace {{'}} with simple apostrophe<br />
value = value:gsub ('\226\128\138\039\226\128\139', "'"); -- replace {{'}} with simple apostrophe (as of 2015-12-11)<br />
value = value:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with plain space<br />
value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space<br />
value = value:gsub ('&zwj;', ''); -- remove &zwj; entities<br />
value = value:gsub ('[\226\128\141\226\128\139]', '') -- remove zero-width joiner, zero-width space<br />
value = value:gsub ('[\194\173\009\010\013]', ' '); -- replace soft hyphen, horizontal tab, line feed, carriage return with plain space<br />
return value;<br />
end<br />
<br />
<br />
--[[--------------------------< C O I N S >--------------------------------------------------------------------<br />
<br />
COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information.<br />
<br />
]]<br />
<br />
local function COinS(data, class)<br />
if 'table' ~= type(data) or nil == next(data) then<br />
return '';<br />
end<br />
<br />
for k, v in pairs (data) do -- spin through all of the metadata parameter values<br />
if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed)<br />
data[k] = coins_cleanup (v);<br />
end<br />
end<br />
<br />
local ctx_ver = "Z39.88-2004";<br />
<br />
-- treat table strictly as an array with only set values.<br />
local OCinSoutput = setmetatable( {}, {<br />
__newindex = function(self, key, value)<br />
if is_set(value) then<br />
rawset( self, #self+1, table.concat{ key, '=', mw.uri.encode( remove_wiki_link( value ) ) } );<br />
end<br />
end<br />
});<br />
<br />
if in_array (class, {'arxiv', 'journal', 'news'}) or (in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or <br />
('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then<br />
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier<br />
if 'arxiv' == class then -- set genre according to the type of citation template we are rendering<br />
OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv<br />
elseif 'conference' == class then<br />
OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set)<br />
elseif 'web' == class then<br />
OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set)<br />
else<br />
OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles<br />
end<br />
OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only<br />
OCinSoutput["rft.atitle"] = data.Title; -- 'periodical' article titles<br />
<br />
-- these used only for periodicals<br />
OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall<br />
OCinSoutput["rft.chron"] = data.Chron; -- free-form date components<br />
OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books<br />
OCinSoutput["rft.issue"] = data.Issue;<br />
OCinSoutput["rft.pages"] = data.Pages; -- also used in book metadata<br />
<br />
elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes<br />
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier<br />
if 'report' == class or 'techreport' == class then -- cite report and cite techreport<br />
OCinSoutput["rft.genre"] = "report";<br />
elseif 'conference' == class then -- cite conference when Periodical not set<br />
OCinSoutput["rft.genre"] = "conference";<br />
OCinSoutput["rft.atitle"] = data.Chapter; -- conference paper as chapter in proceedings (book)<br />
elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then<br />
if is_set (data.Chapter) then<br />
OCinSoutput["rft.genre"] = "bookitem";<br />
OCinSoutput["rft.atitle"] = data.Chapter; -- book chapter, encyclopedia article, interview in a book, or map title<br />
else<br />
if 'map' == class or 'interview' == class then<br />
OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview<br />
else<br />
OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia<br />
end<br />
end<br />
else --{'audio-visual', 'AV-media-notes', 'DVD-notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'}<br />
OCinSoutput["rft.genre"] = "unknown";<br />
end<br />
OCinSoutput["rft.btitle"] = data.Title; -- book only<br />
OCinSoutput["rft.place"] = data.PublicationPlace; -- book only<br />
OCinSoutput["rft.series"] = data.Series; -- book only<br />
OCinSoutput["rft.pages"] = data.Pages; -- book, journal<br />
OCinSoutput["rft.edition"] = data.Edition; -- book only<br />
OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation<br />
<br />
else -- cite thesis<br />
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier<br />
OCinSoutput["rft.title"] = data.Title; -- dissertation (also patent but that is not yet supported)<br />
OCinSoutput["rft.degree"] = data.Degree; -- dissertation only<br />
OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation<br />
end<br />
-- and now common parameters (as much as possible)<br />
OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation<br />
<br />
for k, v in pairs( data.ID_list ) do -- what to do about these? For now assume that they are common to all?<br />
-- if k == 'ISBN' then v = clean_isbn( v ) end<br />
if k == 'ISBN' then v = v:gsub( "[^-0-9X]", "" ); end<br />
local id = cfg.id_handlers[k].COinS;<br />
if string.sub( id or "", 1, 4 ) == 'info' then -- for ids that are in the info:registry<br />
OCinSoutput["rft_id"] = table.concat{ id, "/", v };<br />
elseif string.sub (id or "", 1, 3 ) == 'rft' then -- for isbn, issn, eissn, etc that have defined COinS keywords<br />
OCinSoutput[ id ] = v;<br />
elseif id then -- when cfg.id_handlers[k].COinS is not nil<br />
OCinSoutput["rft_id"] = table.concat{ cfg.id_handlers[k].prefix, v }; -- others; provide a url<br />
end<br />
end<br />
<br />
--[[ <br />
for k, v in pairs( data.ID_list ) do -- what to do about these? For now assume that they are common to all?<br />
local id, value = cfg.id_handlers[k].COinS;<br />
if k == 'ISBN' then value = clean_isbn( v ); else value = v; end<br />
if string.sub( id or "", 1, 4 ) == 'info' then<br />
OCinSoutput["rft_id"] = table.concat{ id, "/", v };<br />
else<br />
OCinSoutput[ id ] = value;<br />
end<br />
end<br />
]]<br />
local last, first;<br />
for k, v in ipairs( data.Authors ) do<br />
last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki strip markers, non-printing or invisible characers<br />
if k == 1 then -- for the first author name only<br />
if is_set(last) and is_set(first) then -- set these COinS values if |first= and |last= specify the first author name<br />
OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation<br />
OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation<br />
elseif is_set(last) then <br />
OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name<br />
end<br />
else -- for all other authors<br />
if is_set(last) and is_set(first) then<br />
OCinSoutput["rft.au"] = table.concat{ last, ", ", first }; -- book, journal, dissertation<br />
elseif is_set(last) then<br />
OCinSoutput["rft.au"] = last; -- book, journal, dissertation<br />
end<br />
end<br />
end<br />
<br />
OCinSoutput.rft_id = data.URL;<br />
OCinSoutput.rfr_id = table.concat{ "info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage };<br />
OCinSoutput = setmetatable( OCinSoutput, nil );<br />
<br />
-- sort with version string always first, and combine.<br />
table.sort( OCinSoutput );<br />
table.insert( OCinSoutput, 1, "ctx_ver=" .. ctx_ver ); -- such as "Z39.88-2004"<br />
return table.concat(OCinSoutput, "&");<br />
end<br />
<br />
<br />
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------<br />
<br />
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.<br />
<br />
]]<br />
<br />
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)<br />
cfg = cfg_table_ptr;<br />
<br />
is_set = utilities_page_ptr.is_set; -- import functions from select Module:Citation/CS1/Utilities module<br />
in_array = utilities_page_ptr.in_array;<br />
remove_wiki_link = utilities_page_ptr.remove_wiki_link;<br />
end<br />
<br />
<br />
<br />
return {<br />
make_coins_title = make_coins_title,<br />
get_coins_pages = get_coins_pages,<br />
COinS = COinS,<br />
set_selected_modules = set_selected_modules,<br />
}</div>Trappist the monk