Module:Harvc/sandbox
Appearance
From Wikipedia, the free encyclopedia
This module depends on the following other modules:
Implements {{Harvc }}.
The above documentation is transcluded from Module:Harvc/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Add categories to the /doc subpage. Subpages of this module.
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Add categories to the /doc subpage. Subpages of this module.
require('strict') localcode_open_tag='<code class="cs1-code">';-- cs1-code class defined in Module:Citation/CS1/styles.css locallock_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 >------------------------------------------------------ check to see if target of harvc exists in the page somewhere. Uses the target check mechanism from Module:Footnotes setting |ignore-errors=yes in {{harvc}} will override this check ]] localfunctiontarget_check(anchor_id,ignore) localwhitelist_check=require('Module:Footnotes/sandbox').target_check localargs={ignore=ignore,template='Harvc',show=true} returnwhitelist_check(anchor_id,args) end --[[--------------------------< I S _ S E T >------------------------------------------------------------------ Whether variable is set or not. A variable is set when it is not nil and not empty. ]] localfunctionis_set(var) returnnot(var==nilorvar==''); 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 ]] localfunctioncheck_years(year,anchor_year) localy,ay; ifnotis_set(year)then-- year is required so return error message when not set return' missing '..code_open_tag..'|year=</code>.'; end localpatterns={-- 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_,patterninipairs(patterns)do-- spin through the patterns y=year:match(pattern);-- y is the year portion ifythen break;-- when y is set, we found a match so done end end ifnotythen return' invalid '..code_open_tag..'|year=</code>.';-- y not set, so year is malformed end ifis_set(anchor_year)then-- anchor_year is optional for_,patterninipairs(patterns)do-- spin through the patterns ay=anchor_year:match(pattern);-- ay is the year portion ifaythen break;-- when ay is set, we found a match so done end end ifnotaythen 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 ify~=aythen 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. ]] localfunctionmake_name(last,first,link,mask) localname=last; ifis_set(first)then name=name..', '..first;-- concatenate first onto last end ifis_set(link)then name='[['..link..'|'..name..']]';-- form a wikilink around the name end ifis_set(mask)then-- mask this author iftonumber(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 returnname; 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 ]] localfunctioncore(args) localspan_open_tag;-- holds CITEREF and css localcontributors='';-- chapter or contribution authors localsource='';-- editor/author date list that forms a CITEREF link to a full citation localin_text=' In '; -- form the CITEREF anchor ifis_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 localciteref='CITEREF'..table.concat(args.citeref)..(is_set(args['anchor-year'])andargs['anchor-year']orargs.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_stylethen-- default cs1|2 style contributor list locali=1; localcount; localetal=false;-- when |display-authors= is same as number of authors in contributor list ifis_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)or0;-- 0 if can't be converted to a number if0>=countthen args.err_msg=args.err_msg..' invalid '..code_open_tag..'|display-authors=</code>';-- if zero, then emit error message end end ifcount>#args.lastthen count=#args.last;-- when |display-authors= is more than the number of authors, use the number of authors end ifcount<#args.lastthen-- 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 whilei<=countdo ifis_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 iftrue==etalthen contributors=contributors..' et al.';-- append et al. elseif'amp'==args.name_list_stylethen contributors=contributors:gsub('; ([^;]+)$',' & %1')-- replace last separator with ' & ' end else-- do default harv- or sfn-style contributor display if4<=#args.lastthen-- four or more contributors (first followed by et al.) contributors=args.last[1]..' et al.'; elseif3==#args.lastthen-- three (display them all) contributors=args.last[1]..', '..args.last[2]..' & '..args.last[3]; elseif2==#args.lastthen-- two (first & second) contributors=args.last[1]..' & '..args.last[2]; elseif1==#args.lastthen-- 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 ifis_set(args.in4)andis_set(args.in3)andis_set(args.in2)andis_set(args.in1)then source=args.in1..' et al.'; elseifnotis_set(args.in4)andis_set(args.in3)andis_set(args.in2)andis_set(args.in1)then source=args.in1..', '..args.in2..' & '..args.in3; elseifnotis_set(args.in4)andnotis_set(args.in3)andis_set(args.in2)andis_set(args.in1)then source=args.in1..' & '..args.in2; elseifnotis_set(args.in4)andnotis_set(args.in3)andnotis_set(args.in2)andis_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 localanchor_id; localtarget_err_msg; if''~=args.refthen 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 localno_quotes=({['afterword']=true,['foreword']=true,['introduction']=true,['preface']=true})[args.contribution:lower()]; --combine contribution with url to make external link ifargs.url~=''then args.contribution='['..args.url..' '..args.contribution..']';-- format external link ifargs['url-access']then iflock_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 ifis_set(args['anchor-year'])then contributors=contributors..' ('..args['anchor-year']..')'..args.sepc; elseifargs.sepc~=contributors:sub(-1)andargs.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 ifargs.p~=''then args.p=args.page_sep..args.p; elseifargs.pp~=''then args.p=args.pages_sep..args.pp;-- args.p not set so use it to hold common insource location info end ifargs.loc~=''then args.p=args.p..', '..args.loc;-- add arg.loc to args.p end --wrap error messages in span and add help link ifis_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.sepcthen in_text=in_text:lower();-- CS2 style use lower case end -- and put it all together localresult={};-- the assemby of the above output table.insert(result,span_open_tag); table.insert(result,contributors); table.insert(result,no_quotesand' 'or' "');-- foreword, afterword, introduction, preface contributions are not quoted; all other contributions are table.insert(result,args.contribution); table.insert(result,no_quotesand''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); ifnotis_set(args.err_msg)then table.insert(result,target_err_msg) end table.insert(result,'</span>'); returntable.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 ]] localfunctionharvc(frame) localargs={ err_msg='', page_sep=", p. ", pages_sep=", pp. ", sepc='.', ps='.', open='(',-- year brackets for source year close=')', last={}, first={}, link={}, mask={}, citeref={} } localpframe=frame:getParent(); args.contribution=pframe.args.cor-- chapter or contribution pframe.args.chapteror pframe.args.contributionor''; args.id=pframe.args.idor''; args.in1=pframe.args['in']orpframe.args.in1or'';-- source editor surnames; 'in' is a Lua reserved keyword args.in2=pframe.args.in2or''; args.in3=pframe.args.in3or''; args.in4=pframe.args.in4or''; 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 ifis_set(pframe.args.last)oris_set(pframe.args.last1)or is_set(pframe.args.author)oris_set(pframe.args.author1)then-- must have at least this to continue args.last[1]=pframe.args.lastorpframe.args.last1orpframe.args.authororpframe.args.author1;-- get first contributor's last name args.citeref[1]=args.last[1];-- add it to the citeref args.first[1]=pframe.args.firstorpframe.args.first1;-- get first contributor's first name args.link[1]=pframe.args['author-link']orpframe.args['author-link1'];-- get first contributor's article link args.mask[1]=pframe.args['author-mask']orpframe.args['author-mask1'];-- get first contributor's article link locali=2;-- index for the rest of the names whileis_set(pframe.args['last'..i])oris_set(pframe.args['author'..i])do-- loop through pframe.args and get the rest of the names args.last[i]=pframe.args['last'..i]orpframe.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 if5>ithen args.citeref[i]=args.last[i];-- collect first four last names for CITEREF anchor end i=i+1-- bump the index end end if0==#args.lastthen-- |last= is required args.err_msg=args.err_msg..' no authors in contributor list.'; end args.p=pframe.args.porpframe.args.pageor'';-- source page number(s) or location args.pp=pframe.args.pporpframe.args.pagesor''; args.loc=pframe.args.locor''; args.ref=pframe.args.reforpframe.args.Refor'';-- 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.modethen 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 localtemp=pframe.args.psorpframe.args.postscript; ifis_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.nbthen-- if no brackets around year in link to cs1|2 template args.open='';-- unset these args.close=''; end args.url=pframe.args.urlor-- 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.yearor'';-- required args['anchor-year']=pframe.args['anchor-year']or''; args.err_msg=args.err_msg..check_years(args.year,args['anchor-year']); ifnotis_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 ifargs.last[1]==args.in1and args.last[2]==args.in2and args.last[3]==args.in3and args.last[4]==args.in4and notis_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 returntable.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 };