Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Module:Harvc
Module
Discussion
English
Read
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit source
View history
Move
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
require('strict') local anchor_id_list = mw.loadData ('Module:Footnotes/anchor_id_list').anchor_id_list; local code_open_tag = '<code class="cs1-code">'; -- cs1-code class defined in Module:Citation/CS1/styles.css local lock_icons = { --icon classes are defined in Module:Citation/CS1/styles.css ['registration'] = {'id-lock-registration', 'Free registration required'}, ['limited'] = {'id-lock-limited', 'Free access subject to limited trial, subscription normally required'}, ['subscription'] = {'id-lock-subscription', 'Paid subscription required'}, } --[[--------------------------< T A R G E T _ C H E C K >------------------------------------------------------ look for anchor_id (CITEREF name-list and year or text from |ref=) in anchor_id_list the 'no target' error may be suppressed with |ignore-err=yes when target cannot be found because target is inside a template that wraps another template; 'multiple targets' error may not be suppressed ]] local function target_check (anchor_id, ignore) local number = anchor_id_list[anchor_id]; -- nil when anchor_id not in list; else a number local msg; local category; if not number then if ignore then return ''; -- if ignore is true then no message, no category end msg = 'no target: ' .. anchor_id; -- anchor_id not found in this article category = '[[Category:Harv and Sfn no-target errors]]'; elseif 1 < number then msg = 'multiple targets (' .. number .. '×): ' .. anchor_id; -- more than one anchor_id in this article category = '[[Category:Harv and Sfn multiple-target errors]]'; end category = 0 == mw.title.getCurrentTitle().namespace and category or ''; -- only categorize in article space --use this version to show error messages return msg and ' <span class="error harv-error" style="display: inline; font-size:100%">Harvc error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; --use this version to hide error messages -- return msg and ' <span class="error harv-error" style="display: none; font-size:100%">Harvc error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; end --[[--------------------------< I S _ S E T >------------------------------------------------------------------ Whether variable is set or not. A varable is set when it is not nil and not empty. ]] local function is_set( var ) return not (var == nil or var == ''); end --[[--------------------------< C H E C K _ Y E A R S >-------------------------------------------------------- evaluates params to see if they are one of these forms with or without lowercase letter disambiguator (same as in Module:Footnotes): YYYY n.d. nd c. YYYY YYYY–YYYY (separator is endash) YYYY–YY (separator is endash) when anchor_year present, year portion must be same as year param and must have disambiguator returns empty string when params have correct form; error message else ]] local function check_years (year, anchor_year) local y, ay; if not is_set (year) then -- year is required so return error message when not set return ' missing ' .. code_open_tag .. '|year=</code>.'; end local patterns = { -- allowed year patterns from Module:Footnotes (captures added here) '^(%d%d%d%d?)%l?$', -- YYY or YYYY '^(n%.d%.)%l?$', -- n.d. '^(nd)%l?$', -- nd '^(c%. %d%d%d%d?)%l?$', -- c. YYY or c. YYYY '^(%d%d%d%d–%d%d%d%d)%l?$', -- YYYY–YYYY '^(%d%d%d%d–%d%d)%l?$' -- YYYY–YY } for _, pattern in ipairs (patterns) do -- spin through the patterns y = year:match (pattern); -- y is the year portion if y then break; -- when y is set, we found a match so done end end if not y then return ' invalid ' .. code_open_tag .. '|year=</code>.'; -- y not set, so year is malformed end if is_set (anchor_year) then -- anchor_year is optional for _, pattern in ipairs (patterns) do -- spin through the patterns ay = anchor_year:match (pattern); -- ay is the year portion if ay then break; -- when ay is set, we found a match so done end end if not ay then return ' invalid ' .. code_open_tag .. '|anchor-year</code>.'; -- ay not set, so anchor_year is malformed end -- if not anchor_year:match ('%l$') then -- return ' ' .. code_open_tag .. '|anchor-year=</code> missing dab.'; -- anchor_year must end with a disambiguator letter -- end if y ~= ay then return ' ' .. code_open_tag .. '|year=</code> / ' .. code_open_tag .. '|anchor-year=</code> mismatch.'; -- 'year' portions of year and anchor_year must be the same end end return ''; -- both years are good; empty string for concatenation end --[[--------------------------< M A K E _ N A M E >------------------------------------------------------------ Assembles last, first, link, or mask into a displayable contributor name. ]] local function make_name (last, first, link, mask) local name = last; if is_set (first) then name = name .. ', ' .. first; -- concatenate first onto last end if is_set (link) then name = '[[' .. link .. '|' .. name .. ']]'; -- form a wikilink around the name end if is_set (mask) then -- mask this author if tonumber(mask) then name = string.rep ('—', mask) -- make a string that number length of mdashes else name = mask; -- mask is not a number so use the mask text end end return name; end --[[--------------------------< C O R E >---------------------------------------------------------------------- Assembles the various parts provided by the template into a properly formatted bridging citation. Adds punctuation and text; encloses the whole within a span with id and class attributes. This creates a CITEREF anchor from |last1= through |last4= and |year=. It also creates a CITEREF link from |in1= through |in4= and |year=. It is presumed that the dates of contributions are the same as the date of the enclosing work. Even though not displayed, a year parameter is still required for the CITEREF anchor ]] local function core( args ) local span_open_tag; -- holds CITEREF and css local contributors = ''; -- chapter or contribution authors local source = ''; -- editor/author date list that forms a CITEREF link to a full citation local in_text = ' In '; -- form the CITEREF anchor if is_set (args.id) then args.id = mw.uri.anchorEncode (args.id) span_open_tag = '<span id="' .. args.id .. '" class="citation">'; -- for use when contributor name is same as source name else local citeref = 'CITEREF' .. table.concat (args.citeref) .. (is_set (args['anchor-year']) and args['anchor-year'] or args.year); citeref = mw.uri.anchorEncode (citeref); span_open_tag = '<span id="' .. citeref .. '" class="citation">'; end --[[ form the contributors display list: if |name-list-style=harv, display is similar to {{sfn}} and {{harv}}, 1 to 4 last names; if |display-authors= is empty or omitted, display is similar to cs1|2: display all names in last, first order if |display-authors=etal then displays all author names in last, first order and append et al. if value assigned to |display-authors= is less than the number of author last names, displays the specified number of author names in last, first order followed by et al. ]] if 'harv' ~= args.name_list_style then -- default cs1|2 style contributor list local i = 1; local count; local etal = false; -- when |display-authors= is same as number of authors in contributor list if is_set (args.display_authors) then if 'etal' == args.display_authors:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings count = #args.last; -- display all authors and ... etal = true; -- ... append 'et al.' else count = tonumber (args.display_authors) or 0; -- 0 if can't be converted to a number if 0 >= count then args.err_msg = args.err_msg .. ' invalid ' .. code_open_tag .. '|display-authors=</code>'; -- if zero, then emit error message end end if count > #args.last then count = #args.last; -- when |display-authors= is more than the number of authors, use the number of authors end if count < #args.last then -- when |display-authors= is less than the number of authors etal = true; -- append 'et al.' end else count = #args.last; -- set count to display all of the authors end while i <= count do if is_set (contributors) then contributors = contributors .. '; ' .. make_name (args.last[i], args.first[i], args.link[i], args.mask[i]); -- the rest of the contributors else contributors = make_name (args.last[i], args.first[i], args.link[i], args.mask[i]); -- first contributor's name end i = i+1; -- bump the index end if true == etal then contributors = contributors .. ' et al.'; -- append et al. elseif 'amp' == args.name_list_style then contributors = contributors:gsub('; ([^;]+)$', ' & %1') -- replace last separator with ' & ' end else -- do default harv- or sfn-style contributor display if 4 <= #args.last then -- four or more contributors (first followed by et al.) contributors = args.last[1] .. ' et al.'; elseif 3 == #args.last then -- three (display them all) contributors = args.last[1] .. ', ' .. args.last[2] .. ' & ' .. args.last[3]; elseif 2 == #args.last then -- two (first & second) contributors = args.last[1] .. ' & ' .. args.last[2]; elseif 1 == #args.last then -- just one (first) contributors = args.last[1]; else args.err_msg = args.err_msg .. ' no authors in contributor list.'; -- this code used to find holes in the list; no more end end --form the source author-date list if is_set (args.in4) and is_set (args.in3) and is_set (args.in2) and is_set (args.in1) then source = args.in1 .. ' et al.'; elseif not is_set (args.in4) and is_set (args.in3) and is_set (args.in2) and is_set (args.in1) then source = args.in1 .. ', ' .. args.in2 .. ' & ' .. args.in3; elseif not is_set (args.in4) and not is_set (args.in3) and is_set (args.in2) and is_set (args.in1) then source = args.in1 .. ' & ' .. args.in2; elseif not is_set (args.in4) and not is_set (args.in3) and not is_set (args.in2) and is_set (args.in1) then source = args.in1; else args.err_msg = args.err_msg .. ' author missing from source list.' end source = source .. ' ' .. args.open .. args.year .. args.close; -- add the year with or without brackets --assemble CITEREF wikilink local anchor_id; local target_err_msg; if '' ~= args.ref then anchor_id = mw.uri.anchorEncode (args.ref) else anchor_id = mw.uri.anchorEncode(table.concat ({'CITEREF', args.in1, args.in2, args.in3, args.in4, args.year})); end target_err_msg = target_check (anchor_id, args.ignore); -- see if there is a target for this anchor_id source = '[[#' .. anchor_id .. "|" .. source .. "]]"; -- special case for afterword, foreword, introduction, preface local no_quotes = ({['afterword']=true, ['foreword']=true, ['introduction']=true, ['preface']=true})[args.contribution:lower()]; --combine contribution with url to make external link if args.url ~= '' then args.contribution = '[' .. args.url .. ' ' .. args.contribution .. ']'; -- format external link if args['url-access'] then if lock_icons[args['url-access']] then args.contribution = table.concat ({ -- add access icon markup to this item '<span class="', -- open the opening span tag; icon classes are defined in Module:Citation/CS1/styles.css lock_icons[args['url-access']][1], -- add the appropriate lock icon class '" title="', -- and the title attribute lock_icons[args['url-access']][2], -- for an appropriate tool tip '">', -- close the opening span tag args.contribution, '</span>', -- and close the span }); end end end if is_set (args['anchor-year']) then contributors = contributors .. ' (' .. args['anchor-year'] .. ')' .. args.sepc; elseif args.sepc ~= contributors:sub(-1) and args.sepc .. ']]' ~= contributors:sub(-3) then contributors = contributors .. args.sepc; -- add separator if not same as last character in name list (|first=John S. or et al.) end -- pages and other insource location if args.p ~= '' then args.p = args.page_sep .. args.p; elseif args.pp ~= '' then args.p = args.pages_sep .. args.pp; -- args.p not set so use it to hold common insource location info end if args.loc ~= '' then args.p = args.p .. ', ' .. args.loc; -- add arg.loc to args.p end --wrap error messages in span and add help link if is_set (args.err_msg) then args.err_msg = '<span style="font-size:100%" class="error"> harvc:' .. args.err_msg .. ' ([[Template:Harvc|help]])</span>'; end if ',' == args.sepc then in_text = in_text:lower(); -- CS2 style use lower case end -- and put it all together local result = {}; -- the assemby of the above output table.insert (result, span_open_tag); table.insert (result, contributors); table.insert (result, no_quotes and ' ' or ' "'); -- foreword, afterword, introduction, preface contributions are not quoted; all other contributions are table.insert (result, args.contribution); table.insert (result, no_quotes and '' or '"'); -- foreword, afterword, introduction, preface contributions are not quoted; all other contributions are table.insert (result, args.sepc); table.insert (result, in_text); table.insert (result, source); table.insert (result, args.p); table.insert (result, args.ps); table.insert (result, args.err_msg); table.insert (result, target_err_msg); table.insert (result, '</span>'); return table.concat (result); -- make a string and done end --[[--------------------------< H A R V C >-------------------------------------------------------------------- Entry point from {{harvc}} template. Fetches parent frame parameters, does a bit of simple error checking ]] local function harvc (frame) local args = { err_msg = '', page_sep = ", p. ", pages_sep = ", pp. ", sepc = '.', ps = '.', open = '(', -- year brackets for source year close = ')', last = {}, first = {}, link = {}, mask = {}, citeref = {} } local pframe = frame:getParent(); args.contribution = pframe.args.c or -- chapter or contribution pframe.args.chapter or pframe.args.contribution or ''; args.id = pframe.args.id or ''; args.in1 = pframe.args['in'] or pframe.args.in1 or ''; -- source editor surnames; 'in' is a Lua reserved keyword args.in2 = pframe.args.in2 or ''; args.in3 = pframe.args.in3 or ''; args.in4 = pframe.args.in4 or ''; args.display_authors = pframe.args['display-authors']; -- the number of contributor names to display; cs1|2 format includes first names args.name_list_style = pframe.args['name-list-style'] or ''; -- when set to 'harv' display contributor list in sfn or harv style args.name_list_style = args.name_list_style:lower(); -- make it case agnostic if is_set (pframe.args.last) or is_set (pframe.args.last1) or is_set (pframe.args.author) or is_set (pframe.args.author1) then -- must have at least this to continue args.last[1] = pframe.args.last or pframe.args.last1 or pframe.args.author or pframe.args.author1; -- get first contributor's last name args.citeref[1] = args.last[1]; -- add it to the citeref args.first[1] = pframe.args.first or pframe.args.first1; -- get first contributor's first name args.link[1] = pframe.args['author-link'] or pframe.args['author-link1']; -- get first contributor's article link args.mask[1] = pframe.args['author-mask'] or pframe.args['author-mask1']; -- get first contributor's article link local i = 2; -- index for the rest of the names while is_set (pframe.args['last'..i]) or is_set (pframe.args['author'..i]) do -- loop through pframe.args and get the rest of the names args.last[i] = pframe.args['last'..i] or pframe.args['author'..i]; -- last names args.first[i] = pframe.args['first'..i]; -- first names args.link[i] = pframe.args['author-link'..i]; -- links args.mask[i] = pframe.args['author-mask'..i]; -- masks if 5 > i then args.citeref[i] = args.last[i]; -- collect first four last names for CITEREF anchor end i = i + 1 -- bump the index end end if 0 == #args.last then -- |last= is required args.err_msg = args.err_msg .. ' no authors in contributor list.'; end args.p = pframe.args.p or pframe.args.page or ''; -- source page number(s) or location args.pp = pframe.args.pp or pframe.args.pages or ''; args.loc = pframe.args.loc or ''; args.ref = pframe.args.ref or pframe.args.Ref or ''; -- used to match |ref=<text> in cs1|2 source template args.ignore = 'yes' == pframe.args['ignore-err']; -- suppress false-positive 'no target' errors if 'cs2' == pframe.args.mode then args.ps = ''; -- set postscript character to empty string, cs2 mode args.sepc = ','; -- set seperator character to comma, cs2 mode end do -- to limit scope of local temp local temp = pframe.args.ps or pframe.args.postscript; if is_set (temp) then if 'none' == temp:lower() then -- if |ps=none or |postscript=none then args.ps = ''; -- no postscript else args.ps = temp; -- override default postscript end end end -- end of scope limit if 'yes' == pframe.args.nb then -- if no brackets around year in link to cs1|2 template args.open = ''; -- unset these args.close = ''; end args.url = pframe.args.url or -- url for chapter or contribution pframe.args['chapter-url'] or pframe.args['contribution-url'] or ''; args['url-access'] = pframe.args['url-access']; args.year = pframe.args.year or ''; -- required args['anchor-year'] = pframe.args['anchor-year'] or ''; args.err_msg = args.err_msg .. check_years (args.year, args['anchor-year']); if not is_set (args.contribution) then args.err_msg = args.err_msg .. ' required contribution is missing.'; -- error message if source not provided args.contribution = args.url; -- if set it will give us linkable text end if args.last[1] == args.in1 and args.last[2] == args.in2 and args.last[3] == args.in3 and args.last[4] == args.in4 and not is_set (args.id) then args.err_msg = args.err_msg .. ' required ' .. code_open_tag .. '|id=</code> parameter missing.'; -- error message if contributor and source are the same end return table.concat ({frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1/styles.css'}), core (args)}); end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { harvc = harvc };
Summary:
Please note that all contributions to Ikwipedia are considered to be released under the Creative Commons Attribution-ShareAlike (see
Ikwipedia:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Toggle limited content width