<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://zoophilia.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ACitation%2FCS1%2FCOinS</id>
	<title>Module:Citation/CS1/COinS - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://zoophilia.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ACitation%2FCS1%2FCOinS"/>
	<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/COinS&amp;action=history"/>
	<updated>2026-09-20T23:46:44Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/COinS&amp;diff=475&amp;oldid=prev</id>
		<title>imported&gt;SockyPaws: Update submodule</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/COinS&amp;diff=475&amp;oldid=prev"/>
		<updated>2025-12-25T09:54:42Z</updated>

		<summary type="html">&lt;p&gt;Update submodule&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[-----------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------]]&lt;br /&gt;
-- Functions in Module:Citation/CS1/Utilities.&lt;br /&gt;
local has_accept_as_written&lt;br /&gt;
local in_array&lt;br /&gt;
local is_set&lt;br /&gt;
local remove_wiki_link&lt;br /&gt;
local strip_apostrophe_markup&lt;br /&gt;
&lt;br /&gt;
-- Configuration supertable that&amp;#039;s defined in Module:Citation/CS1/Configuration.&lt;br /&gt;
local cfg&lt;br /&gt;
&lt;br /&gt;
--[[-------------------&amp;lt; M A K E _ C O I N S _ T I T L E &amp;gt;----------------------&lt;br /&gt;
  Makes a title for COinS from Title and / or ScriptTitle (or any other&lt;br /&gt;
  name-script pairs). Apostrophe markup (bold, italics) is stripped from each&lt;br /&gt;
  value so that the COinS metadata isn&amp;#039;t corrupted with strings of %27%27…&lt;br /&gt;
]]&lt;br /&gt;
local function make_coins_title(title, script)&lt;br /&gt;
  title = has_accept_as_written(title)&lt;br /&gt;
  if is_set(title) then&lt;br /&gt;
    title = strip_apostrophe_markup(title)  -- Strip any apostrophe markup.&lt;br /&gt;
  else&lt;br /&gt;
    title = &amp;quot;&amp;quot;  -- If not set, make sure title is an empty string.&lt;br /&gt;
  end&lt;br /&gt;
  if is_set(script) then&lt;br /&gt;
    -- Remove language prefix if present (script value may now be empty string).&lt;br /&gt;
    script = script:gsub(&amp;quot;^%l%l%s*:%s*&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    script = strip_apostrophe_markup(script)  -- Strip any apostrophe markup.&lt;br /&gt;
  else&lt;br /&gt;
    script = &amp;quot;&amp;quot;  -- If not set, make sure script is an empty string.&lt;br /&gt;
  end&lt;br /&gt;
  if is_set(title) and is_set(script) then&lt;br /&gt;
    script = &amp;quot; &amp;quot; .. script  -- Add a space before we concatenate.&lt;br /&gt;
  end&lt;br /&gt;
  return title .. script  -- Return the concatenation.&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[---------------&amp;lt; E S C A P E _ L U A _ M A G I C _ C H A R S &amp;gt;--------------&lt;br /&gt;
  Returns a string where all of Lua&amp;#039;s magic characters have been escaped. This&lt;br /&gt;
  is important because functions like string.gsub() treat their pattern and&lt;br /&gt;
  replace strings as patterns, not literal strings.&lt;br /&gt;
]]&lt;br /&gt;
local function escape_lua_magic_chars(argument)&lt;br /&gt;
  argument = argument:gsub(&amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot;)  -- Replace % with %%.&lt;br /&gt;
  -- Replace all other Lua magic pattern characters.&lt;br /&gt;
  argument = argument:gsub(&amp;quot;([%^%$%(%)%.%[%]%*%+%-%?])&amp;quot;, &amp;quot;%%%1&amp;quot;)&lt;br /&gt;
  return argument&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------&amp;lt; G E T _ C O I N S _ P A G E S &amp;gt;-----------------------&lt;br /&gt;
  Extract page numbers from external wikilinks in any of the |page=, |pages=, or&lt;br /&gt;
  |at= parameters for use in COinS.&lt;br /&gt;
]]&lt;br /&gt;
local function get_coins_pages(pages)&lt;br /&gt;
  local pattern&lt;br /&gt;
  if not is_set(pages) then&lt;br /&gt;
    return pages&lt;br /&gt;
  end  -- If there are no page numbers, then we&amp;#039;re done.&lt;br /&gt;
&lt;br /&gt;
  while true do&lt;br /&gt;
    -- Pattern is the opening bracket, the URL and following space(s): &amp;quot;[url &amp;quot;.&lt;br /&gt;
    pattern = pages:match(&amp;quot;%[(%w*:?//[^ ]+%s+)[%w%d].*%]&amp;quot;)&lt;br /&gt;
    if nil == pattern then&lt;br /&gt;
      break&lt;br /&gt;
    end  -- No more URLs.&lt;br /&gt;
    -- Pattern is not a literal string; escape Lua&amp;#039;s magic pattern characters.&lt;br /&gt;
    pattern = escape_lua_magic_chars(pattern)&lt;br /&gt;
    -- Remove as many instances of pattern as possible.&lt;br /&gt;
    pages = pages:gsub(pattern, &amp;quot;&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  pages = pages:gsub(&amp;quot;[%[%]]&amp;quot;, &amp;quot;&amp;quot;)  -- Remove the brackets.&lt;br /&gt;
  pages = pages:gsub(&amp;quot;–&amp;quot;, &amp;quot;-&amp;quot;)  -- Replace endashes with hyphens…&lt;br /&gt;
  -- …and replace HTML entities (&amp;amp;ndash; etc.) with hyphens; do we need to&lt;br /&gt;
  -- replace numerical entities like &amp;amp;#32; and the like, too?&lt;br /&gt;
  pages = pages:gsub(&amp;quot;&amp;amp;%w+;&amp;quot;, &amp;quot;-&amp;quot;)&lt;br /&gt;
  -- Remove HTML-like tags; spans are added to &amp;lt;Pages&amp;gt; by&lt;br /&gt;
  -- utilities.hyphen_to_dash(), which should not appear in COinS metadata.&lt;br /&gt;
  pages = pages:gsub(&amp;quot;%b&amp;lt;&amp;gt;&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
  return pages&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[-----&amp;lt; 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 &amp;gt;-------&lt;br /&gt;
  There are three options for math markup rendering that depend on the editor&amp;#039;s&lt;br /&gt;
  math preference settings. These settings are at&lt;br /&gt;
  [[Special:Preferences#mw-prefsection-rendering]] and are: PNG images, TeX&lt;br /&gt;
  source and MathML (with SVG or PNG fallback). All three are heavy with HTML&lt;br /&gt;
  and CSS which doesn&amp;#039;t belong in the metadata.&lt;br /&gt;
&lt;br /&gt;
  Without this function, the metadata saved in the raw wikitext contained the&lt;br /&gt;
  rendering determined by the settings of the last editor to save the page.&lt;br /&gt;
&lt;br /&gt;
  This function gets the rendered form of an equation according to the editor&amp;#039;s&lt;br /&gt;
  preference before the page is saved. It then searches the rendering for the&lt;br /&gt;
  text equivalent of the rendered equation and replaces the rendering with that&lt;br /&gt;
  so that the page is saved without extraneous HTML/CSS markup and with a&lt;br /&gt;
  reasonably readable text form of the equation.&lt;br /&gt;
&lt;br /&gt;
  When a replacement is made, this function returns true and the value with&lt;br /&gt;
  replacement, otherwise false and the initial value. To replace multipe&lt;br /&gt;
  equations, it is necessary to call this function from within a loop.&lt;br /&gt;
]=]&lt;br /&gt;
local function coins_replace_math_stripmarker(value)&lt;br /&gt;
  local stripmarker = cfg.stripmarkers[&amp;quot;math&amp;quot;]&lt;br /&gt;
  local rendering = value:match(stripmarker)  -- Is there a math stripmarker?&lt;br /&gt;
&lt;br /&gt;
  -- When value doesn&amp;#039;t have a math stripmarker, abandon this test.&lt;br /&gt;
  if not rendering then&lt;br /&gt;
    return false, value&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  -- Convert stripmarker into rendered value (or nil? when math render error).&lt;br /&gt;
  rendering = mw.text.unstripNoWiki(rendering)&lt;br /&gt;
&lt;br /&gt;
  if rendering:match(&amp;#039;alt=&amp;quot;[^&amp;quot;]+&amp;quot;&amp;#039;) then  -- If PNG math option…&lt;br /&gt;
    rendering = rendering:match(&amp;#039;alt=&amp;quot;([^&amp;quot;]+)&amp;quot;&amp;#039;)&lt;br /&gt;
  -- If TeX math option; $ is legit character that is escapes as \$.&lt;br /&gt;
  elseif rendering:match(&amp;quot;$%s+.+%s+%$&amp;quot;) then&lt;br /&gt;
    rendering = rendering:match(&amp;quot;$%s+(.+)%s+%$&amp;quot;)&lt;br /&gt;
  elseif rendering:match(&amp;quot;&amp;lt;annotation[^&amp;gt;]+&amp;gt;.+&amp;lt;/annotation&amp;gt;&amp;quot;) then -- If MathML.&lt;br /&gt;
    rendering = rendering:match(&amp;quot;&amp;lt;annotation[^&amp;gt;]+&amp;gt;(.+)&amp;lt;/annotation&amp;gt;&amp;quot;)&lt;br /&gt;
  else&lt;br /&gt;
    return false, value  -- Had math stripmarker but not of the defined forms.&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  return true, value:gsub(stripmarker, rendering, 1)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[---------------------&amp;lt; C O I N S _ C L E A N U P &amp;gt;--------------------------&lt;br /&gt;
  Cleanup parameter values for the metadata by removing or replacing invisible&lt;br /&gt;
  characters and certain HTML entities.&lt;br /&gt;
&lt;br /&gt;
  2015-12-10: There is a bug in mw.text.unstripNoWiki(). It replaces math&lt;br /&gt;
  stripmarkers with the appropriate content when it shouldn&amp;#039;t. See phab:121085&lt;br /&gt;
  and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29.&lt;br /&gt;
&lt;br /&gt;
  TODO: Move the replacement patterns and replacement values into a table in&lt;br /&gt;
  /Configuration, similar to the invisible characters table?&lt;br /&gt;
]]&lt;br /&gt;
local function coins_cleanup(value)&lt;br /&gt;
  local replaced = true  -- Default state to get the do loop running.&lt;br /&gt;
  while replaced do  -- Loop until all math stripmarkers replaced.&lt;br /&gt;
  -- Replace math stripmarker with text representation of the equation.&lt;br /&gt;
    replaced, value = coins_replace_math_stripmarker(value)&lt;br /&gt;
  end&lt;br /&gt;
  -- One or more couldn&amp;#039;t be replaced; insert vague error message.&lt;br /&gt;
  value = value:gsub(cfg.stripmarkers[&amp;quot;math&amp;quot;], &amp;quot;MATH RENDER ERROR&amp;quot;)&lt;br /&gt;
  -- Replace nowiki stripmarkers with their content.&lt;br /&gt;
  value = mw.text.unstripNoWiki(value)&lt;br /&gt;
  -- Replace {{&amp;#039;}} or {{&amp;#039;s}} with simple apostrophe or apostrophe-s.&lt;br /&gt;
  value = value:gsub(&amp;#039;&amp;lt;span class=&amp;quot;nowrap&amp;quot; style=&amp;quot;padding%-left: 0%.1em;&amp;quot;&amp;gt;&amp;amp;#39;(s?)&amp;lt;/span&amp;gt;&amp;#039;, &amp;quot;&amp;#039;%1&amp;quot;)&lt;br /&gt;
  value = value:gsub(&amp;quot;&amp;amp;nbsp;&amp;quot;, &amp;quot; &amp;quot;) -- Replace &amp;amp;nbsp; entity with plain space.&lt;br /&gt;
  value = value:gsub(&amp;quot;\226\128\138&amp;quot;, &amp;quot; &amp;quot;) -- Replace hair space with space.&lt;br /&gt;
  -- Don&amp;#039;t remove zero-width joiner characters from Indic scripts.&lt;br /&gt;
  if not mw.ustring.find(value, cfg.indic_script) then&lt;br /&gt;
    value = value:gsub(&amp;quot;&amp;amp;zwj;&amp;quot;, &amp;quot;&amp;quot;)  -- Remove &amp;amp;zwj; entities.&lt;br /&gt;
    -- Remove zero-width joiner, zero-width space and soft hyphen.&lt;br /&gt;
    value = mw.ustring.gsub(value, &amp;quot;[\226\128\141\226\128\139\194\173]&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
  -- Replace horizontal tab, line feed and carriage return with plain space.&lt;br /&gt;
  value = value:gsub(&amp;quot;[\009\010\013 ]+&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
  return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C O I N S &amp;gt;-------------------------------------&lt;br /&gt;
  COinS metadata (see &amp;lt;https://ocoins.info/&amp;gt;) allows automated tools to parse&lt;br /&gt;
  the citation information.&lt;br /&gt;
]]&lt;br /&gt;
local function COinS(data, class)&lt;br /&gt;
  if &amp;quot;table&amp;quot; ~= type(data) or nil == next(data) then&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  for k, v in pairs(data) do  -- Loop through all the metadata parameter values.&lt;br /&gt;
    -- Except the ID_list and Author tables (author nowiki stripmarker done when&lt;br /&gt;
    -- Author table processed).&lt;br /&gt;
    if &amp;quot;ID_list&amp;quot; ~= k and &amp;quot;Authors&amp;quot; ~= k then&lt;br /&gt;
      data[k] = coins_cleanup(v)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  local ctx_ver = &amp;quot;Z39.88-2004&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  -- Treat table strictly as an array with only set values.&lt;br /&gt;
  local OCinSoutput =&lt;br /&gt;
    setmetatable(&lt;br /&gt;
      {},&lt;br /&gt;
      {&lt;br /&gt;
        __newindex = function(self, key, value)&lt;br /&gt;
          if is_set(value) then&lt;br /&gt;
            rawset(self, #self + 1, table.concat {key, &amp;quot;=&amp;quot;, mw.uri.encode(remove_wiki_link(value))})&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
  if&lt;br /&gt;
  in_array(class, {&amp;quot;arxiv&amp;quot;, &amp;quot;biorxiv&amp;quot;, &amp;quot;citeseerx&amp;quot;, &amp;quot;medrxiv&amp;quot;, &amp;quot;ssrn&amp;quot;, &amp;quot;journal&amp;quot;, &amp;quot;news&amp;quot;, &amp;quot;magazine&amp;quot;}) or&lt;br /&gt;
    (in_array(class, {&amp;quot;conference&amp;quot;, &amp;quot;interview&amp;quot;, &amp;quot;map&amp;quot;, &amp;quot;press release&amp;quot;, &amp;quot;web&amp;quot;}) and is_set(data.Periodical)) or&lt;br /&gt;
    (&amp;quot;citation&amp;quot; == class and is_set(data.Periodical) and not is_set(data.Encyclopedia))&lt;br /&gt;
  then&lt;br /&gt;
    -- Journal metadata identifier.&lt;br /&gt;
    OCinSoutput.rft_val_fmt = &amp;quot;info:ofi/fmt:kev:mtx:journal&amp;quot;&lt;br /&gt;
    -- Set genre according to the type of citation template we are rendering&lt;br /&gt;
    if in_array(class, {&amp;quot;arxiv&amp;quot;, &amp;quot;biorxiv&amp;quot;, &amp;quot;citeseerx&amp;quot;, &amp;quot;medrxiv&amp;quot;, &amp;quot;ssrn&amp;quot;}) then&lt;br /&gt;
      -- Cite_arxiv, Cite_biorxiv, Cite_citeseerx, Cite_medrxiv, Cite_SSRN.&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;preprint&amp;quot;&lt;br /&gt;
    elseif &amp;quot;conference&amp;quot; == class then&lt;br /&gt;
      -- Cite_conference (when Periodical set).&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;conference&amp;quot;&lt;br /&gt;
    elseif &amp;quot;web&amp;quot; == class then&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;unknown&amp;quot; -- Cite_web, when Periodical set.&lt;br /&gt;
    else&lt;br /&gt;
      -- Journal and other &amp;#039;periodical&amp;#039; articles.&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;article&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.jtitle&amp;quot;] = data.Periodical  -- Journal only.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.atitle&amp;quot;] = data.Title  -- &amp;#039;periodical&amp;#039; article titles&lt;br /&gt;
&lt;br /&gt;
    -- These used only for periodicals.&lt;br /&gt;
    -- Keywords: winter, spring, summer, fall.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.ssn&amp;quot;] = data.Season&lt;br /&gt;
    -- Single digits 1-&amp;gt;first quarter, etc.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.quarter&amp;quot;] = data.Quarter&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.chron&amp;quot;] = data.Chron  -- Free-form date components.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.volume&amp;quot;] = data.Volume  -- Does not apply to books.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.issue&amp;quot;] = data.Issue&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.artnum&amp;quot;] = data.ArticleNumber  -- {{Cite journal}} only&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.pages&amp;quot;] = data.Pages  -- Also used in book metadata.&lt;br /&gt;
    -- All others except Cite_thesis are treated as &amp;#039;book&amp;#039; metadata; genre&lt;br /&gt;
    -- distinguishes.&lt;br /&gt;
  elseif &amp;quot;thesis&amp;quot; ~= class then&lt;br /&gt;
    -- Book metadata identifier.&lt;br /&gt;
    OCinSoutput.rft_val_fmt = &amp;quot;info:ofi/fmt:kev:mtx:book&amp;quot;&lt;br /&gt;
    -- Cite_report and Cite_techreport.&lt;br /&gt;
    if &amp;quot;report&amp;quot; == class or &amp;quot;techreport&amp;quot; == class then&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;report&amp;quot;&lt;br /&gt;
    -- Cite_conference when Periodical not set.&lt;br /&gt;
    elseif &amp;quot;conference&amp;quot; == class then&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;conference&amp;quot;&lt;br /&gt;
      -- Conference paper as chapter in proceedings (book).&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.atitle&amp;quot;] = data.Chapter&lt;br /&gt;
    elseif in_array(class, {&amp;quot;book&amp;quot;, &amp;quot;citation&amp;quot;, &amp;quot;encyclopaedia&amp;quot;, &amp;quot;interview&amp;quot;, &amp;quot;map&amp;quot;}) then&lt;br /&gt;
      if is_set(data.Chapter) then&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;bookitem&amp;quot;&lt;br /&gt;
        -- Book chapter, encyclopedia article, book interview or map title.&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.atitle&amp;quot;] = data.Chapter&lt;br /&gt;
      else&lt;br /&gt;
        if &amp;quot;map&amp;quot; == class or &amp;quot;interview&amp;quot; == class then&lt;br /&gt;
          OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;unknown&amp;quot; -- Standalone map/interview.&lt;br /&gt;
        else&lt;br /&gt;
          OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;book&amp;quot;  -- Book and encyclopedia.&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    -- {&amp;#039;audio-visual&amp;#039;, &amp;#039;AV-media-notes&amp;#039;, &amp;#039;DVD-notes&amp;#039;, &amp;#039;episode&amp;#039;, &amp;#039;interview&amp;#039;,&lt;br /&gt;
    -- &amp;#039;mailinglist&amp;#039;, &amp;#039;map&amp;#039;, &amp;#039;newsgroup&amp;#039;, &amp;#039;podcast&amp;#039;, &amp;#039;press release&amp;#039;,&lt;br /&gt;
    -- &amp;#039;serial&amp;#039;, &amp;#039;sign&amp;#039;, &amp;#039;speech&amp;#039;, &amp;#039;web&amp;#039;}&lt;br /&gt;
    else&lt;br /&gt;
      OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;unknown&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.btitle&amp;quot;] = data.Title  -- Book only.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.place&amp;quot;] = data.PublicationPlace  -- Book only.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.series&amp;quot;] = data.Series  -- Book only.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.pages&amp;quot;] = data.Pages  -- Book, journal.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.edition&amp;quot;] = data.Edition  -- Book only.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.pub&amp;quot;] = data.PublisherName  -- Book and dissertation.&lt;br /&gt;
  else  -- Cite thesis.&lt;br /&gt;
    -- Dissertation metadata identifier.&lt;br /&gt;
    OCinSoutput.rft_val_fmt = &amp;quot;info:ofi/fmt:kev:mtx:dissertation&amp;quot;&lt;br /&gt;
    -- Dissertation (also patent, but that is not yet supported).&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.title&amp;quot;] = data.Title&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.degree&amp;quot;] = data.Degree  -- Dissertation only.&lt;br /&gt;
    OCinSoutput[&amp;quot;rft.inst&amp;quot;] = data.PublisherName  -- Book and dissertation.&lt;br /&gt;
  end&lt;br /&gt;
  -- NB. Not currently supported are &amp;quot;info:ofi/fmt:kev:mtx:patent&amp;quot;,&lt;br /&gt;
  -- &amp;quot;info:ofi/fmt:kev:mtx:dc&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:sch_svc&amp;quot;,&lt;br /&gt;
  -- &amp;quot;info:ofi/fmt:kev:mtx:ctx&amp;quot; and now common parameters (as much as can be).&lt;br /&gt;
  OCinSoutput[&amp;quot;rft.date&amp;quot;] = data.Date  -- Book, journal, dissertation.&lt;br /&gt;
&lt;br /&gt;
  -- What to do about these? For now, assume that they are common to all?&lt;br /&gt;
  for k, v in pairs(data.ID_list) do&lt;br /&gt;
    if k == &amp;quot;ISBN&amp;quot; then&lt;br /&gt;
      v = v:gsub(&amp;quot;[^-0-9X]&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    local id = cfg.id_handlers[k].COinS&lt;br /&gt;
    -- For IDs that are in the info:registry.&lt;br /&gt;
    if string.sub(id or &amp;quot;&amp;quot;, 1, 4) == &amp;quot;info&amp;quot; then&lt;br /&gt;
      OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat {id, &amp;quot;/&amp;quot;, v}&lt;br /&gt;
      -- For ISBN, ISSN, eISSN, etc., that have defined COinS keywords.&lt;br /&gt;
    elseif string.sub(id or &amp;quot;&amp;quot;, 1, 3) == &amp;quot;rft&amp;quot; then&lt;br /&gt;
      OCinSoutput[id] = v&lt;br /&gt;
    -- For URLs that are assembled in ~/Identifiers; |asin= and |ol=.&lt;br /&gt;
    elseif &amp;quot;url&amp;quot; == id then&lt;br /&gt;
      OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat({data.ID_list[k], &amp;quot;#id-name=&amp;quot;, cfg.id_handlers[k].label})&lt;br /&gt;
    -- When cfg.id_handlers[k].COinS is not nil so urls created here.&lt;br /&gt;
    elseif id then&lt;br /&gt;
      OCinSoutput[&amp;quot;rft_id&amp;quot;] =&lt;br /&gt;
        table.concat {&lt;br /&gt;
          cfg.id_handlers[k].prefix,&lt;br /&gt;
          v,&lt;br /&gt;
          cfg.id_handlers[k].suffix or &amp;quot;&amp;quot;,&lt;br /&gt;
          &amp;quot;#id-name=&amp;quot;,&lt;br /&gt;
          cfg.id_handlers[k].label&lt;br /&gt;
        }&lt;br /&gt;
      -- Others; provide a URL and indicate identifier name as #fragment&lt;br /&gt;
      -- (human-readable, but transparent to browsers).&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  local last, first&lt;br /&gt;
  for k, v in ipairs(data.Authors) do&lt;br /&gt;
    -- Replace any nowiki stripmarkers, non-printing or invisible characters.&lt;br /&gt;
    last, first = coins_cleanup(v.last), coins_cleanup(v.first or &amp;quot;&amp;quot;)&lt;br /&gt;
    if k == 1 then  -- For the first author name only.&lt;br /&gt;
    -- Set these COinS values if |first= and |last= specify first author name.&lt;br /&gt;
      if is_set(last) and is_set(first) then&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.aulast&amp;quot;] = last  -- Book, journal, dissertation.&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.aufirst&amp;quot;] = first  -- Book, journal, dissertation.&lt;br /&gt;
      elseif is_set(last) then&lt;br /&gt;
        -- Book, journal, dissertation; otherwise use this for the first name.&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.au&amp;quot;] = last&lt;br /&gt;
      end&lt;br /&gt;
    else  -- For all other authors.&lt;br /&gt;
      -- TODO: At present we do not report &amp;quot;et al.&amp;quot;. Add anything special if&lt;br /&gt;
      -- this condition applies?&lt;br /&gt;
      if is_set(last) and is_set(first) then&lt;br /&gt;
        -- Book, journal, dissertation.&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.au&amp;quot;] = table.concat {last, &amp;quot;, &amp;quot;, first}&lt;br /&gt;
      elseif is_set(last) then&lt;br /&gt;
        OCinSoutput[&amp;quot;rft.au&amp;quot;] = last  -- Book, journal, dissertation.&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  OCinSoutput.rft_id = data.URL&lt;br /&gt;
  OCinSoutput.rfr_id = table.concat {&amp;quot;info:sid/&amp;quot;, mw.site.server:match(&amp;quot;[^/]*$&amp;quot;), &amp;quot;:&amp;quot;, data.RawPage}&lt;br /&gt;
&lt;br /&gt;
  -- TODO: Add optional extra info:&lt;br /&gt;
  -- rfr_dat=#REVISION&amp;lt;version&amp;gt; (referrer private data)&lt;br /&gt;
  -- ctx_id=&amp;lt;data.RawPage&amp;gt;#&amp;lt;ref&amp;gt; (identifier for the context object)&lt;br /&gt;
  -- ctx_tim=&amp;lt;ts&amp;gt; (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd)&lt;br /&gt;
  -- ctx_enc=info:ofi/enc:UTF-8 (character encoding)&lt;br /&gt;
  OCinSoutput = setmetatable(OCinSoutput, nil)&lt;br /&gt;
&lt;br /&gt;
  -- sort with version string always first, and combine.&lt;br /&gt;
  -- table.sort( OCinSoutput );&lt;br /&gt;
  table.insert(OCinSoutput, 1, &amp;quot;ctx_ver=&amp;quot; .. ctx_ver) -- such as &amp;quot;Z39.88-2004&amp;quot;&lt;br /&gt;
  return table.concat(OCinSoutput, &amp;quot;&amp;amp;&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;-------------------&lt;br /&gt;
  Sets local cfg table and imported functions table to same (live or sandbox) as&lt;br /&gt;
  that used by the other modules.&lt;br /&gt;
]]&lt;br /&gt;
local function set_selected_modules(cfg_table_ptr, utilities_page_ptr)&lt;br /&gt;
  cfg = cfg_table_ptr&lt;br /&gt;
  -- Import functions from selected Module:Citation/CS1/Utilities module.&lt;br /&gt;
  has_accept_as_written = utilities_page_ptr.has_accept_as_written&lt;br /&gt;
  is_set = utilities_page_ptr.is_set&lt;br /&gt;
  in_array = utilities_page_ptr.in_array&lt;br /&gt;
  remove_wiki_link = utilities_page_ptr.remove_wiki_link&lt;br /&gt;
  strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[-----------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------]]&lt;br /&gt;
return {&lt;br /&gt;
  make_coins_title = make_coins_title,&lt;br /&gt;
  get_coins_pages = get_coins_pages,&lt;br /&gt;
  COinS = COinS,&lt;br /&gt;
  set_selected_modules = set_selected_modules&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>imported&gt;SockyPaws</name></author>
	</entry>
</feed>