Module:Sister project links
- Afrikaans
- Алтай тил
- العربية
- Արեւմտահայերէն
- Авар
- Azərbaycanca
- تۆرکجه
- Basa Bali
- বাংলা
- Cebuano
- الدارجة
- فارسی
- ГӀалгӀай
- ગુજરાતી
- 한국어
- Hausa
- Հայերեն
- Ирон
- Italiano
- Ladin
- Latviešu
- Ligure
- മലയാളം
- مصرى
- مازِرونی
- ꯃꯤꯇꯩ ꯂꯣꯟ
- नेपाली
- 日本語
- Napulitano
- Norsk bokmål
- ਪੰਜਾਬੀ
- ပအိုဝ်ႏဘာႏသာႏ
- Piemontèis
- Русский
- Sicilianu
- සිංහල
- Slovenščina
- Suomi
- Tarandíne
- Татарча / tatarça
- ไทย
- Тыва дыл
- Vèneto
- Tiếng Việt
- 中文
Appearance
From Wikipedia, the free encyclopedia
Warning This Lua module is used on approximately 20,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them.
This module depends on the following other modules:
CSS This module uses TemplateStyles:
Implements {{Sister project links }}
See {{Sister project links/testcases }} for test cases for box, {{Sister bar/testcases }} for bar.
Note: in order to make the test cases work, the Sandbox CSS classes have "-sand" appended to their names. If you wish to update the CSS, copy the contents of each class from Module:Sister project links/sandbox/styles.css to Module:Sister project links/styles.css, but do not alter the class names, nor just copy-paste the entire CSS file. For the current difference in CSS between Sandbox and Main, see here.
The above documentation is transcluded from Module:Sister project links/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit) pages.
Subpages of this module.
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit) pages.
Subpages of this module.
require('strict') -- Module to create sister project link box localgetArgs=require('Module:Arguments').getArgs localsideBox=require('Module:Side box')._main localp={} localinSandbox=mw.getCurrentFrame():getTitle():find('sandbox',1,true) -- Function to add "-sand" to classes when called from sandbox localfunctionsandbox(s) returninSandboxands.."-sand"ors end -- Information about how to handle each sister lives in separate data file localcfg=mw.loadData(sandbox('Module:Sister project links/config')) locallogo=cfg.logo localdarkOnLight=cfg.darkOnLight localPDicon=cfg.PDicon localprefixList=cfg.prefixList localsisterName=cfg.sisterName localsisterInfo=cfg.sisterInfo localdefaultSisters=cfg.defaultSisters localsisterDb=cfg.sisterDb localtrackingType=cfg.trackingType -- Function to canonicalize string -- search for variants of "yes", and "no", and transform -- them into a standard form (like [[Template:YesNo]]) -- Argument: -- s --- input string -- Result: -- {x,y} list of length 2 -- x = nil if s is canonicalized, otherwise has trimmed s -- y = canonical form of s (true if "yes" or other, false if "no", nil if blank) localfunctioncanonicalize(s) ifs==nilthen return{nil,nil} end -- if s is table/list, then assume already canonicalized and return unchanged iftostring(type(s))=="table"then returns end s=mw.text.trim(tostring(s)) ifs==""then return{nil,nil} end locallowerS=s:lower() -- Check for various forms of "yes" iflowerS=='yes'orlowerS=='y'orlowerS=='t' orlowerS=='1'orlowerS=='true'orlowerS=='on'then return{nil,true} end -- Check for various forms of "no" iflowerS=='no'orlowerS=='n'orlowerS=='f' orlowerS=='0'orlowerS=='false'orlowerS=='off'then return{nil,false} end -- Neither yes nor no recognized, leave string trimmed return{s,true} end -- Merge two or more canonicalized argument lists -- Arguments: -- argList = list of canonicalized arguments -- noAll = if true, return no when all argList is no. -- otherwise, return blank when all argList is blank localfunctionmergeArgs(argList,noAll) localtest=nil-- default, return blank if all blank ifnoAllthen test=false-- return no if all no end localallSame=true -- Search through string for first non-no or non-blank for_,arginipairs(argList)do ifarg[2]then returnarg-- found non-no and non-blank, return it end -- test to see if argList is all blank / no allSame=allSameand(arg[2]==test) end -- if all blank / no, return blank / no ifallSamethen return{nil,test}-- all match no/blank, return it end -- otherwise, return no / blank ifnoAllthen return{nil,nil} end return{nil,false} end -- Function to determine whether to suppress link to icon -- Arguments: -- prefix = sister wiki prefix localfunctionsuppressLink(prefix) returnprefixandPDicon[prefix]and'|link='or'' end -- Function to get sitelink for a wiki -- Arguments: -- wiki = db name of wiki to lookup -- qid = QID of entity to search for, current page entity by default localfunctiongetSitelink(wiki,qid) -- return nil if some sort of lookup failure returnqidandmw.wikibase.getSitelink(qid,wiki) end -- Function to get sitelink for a wiki -- Arguments: -- prefix = prefix string for wiki to lookup -- qid = QID of entity to search for, current page entity by default localfunctionfetchWikidata(prefix,qid) localsisterDbName=sisterDb[prefix] returnsisterDbNameandgetSitelink(sisterDbName,qid) end -- Function to generate the sister link itself -- Arguments: -- args = argument table for function -- args[1] = page to fetch -- args.default = link when blank -- args.auto = new auto mode (don't fall back to search) -- args.sitelink = wikidata sitelink (if available) -- args.qid = QID of entity -- args.search = fallback string to search for -- args.sisterPrefix = wikitext prefix for sister site -- args.information = type of info sister site contains -- tracking = tracking table localfunctiongenSisterLink(args,tracking) ifargs[1][2]==falseor(notargs.defaultandargs[1][2]==nil)then returnnil--- either editor specified "no", or "blank" (and default=no), then skip this sister end localsitelink=args.sitelinkorfetchWikidata(args.sisterPrefix,args.qid) ifargs.autoandnotsitelinkandargs[1][2]==nilthen returnnil--- in auto mode, if link is blank and no sitelink, then skip end -- fallback order of sister link: first specified page, then wikidata, then search locallink=args[1][1]orsitelinkor(args.searchand"Special:"..args.search) ifnotlinkthen returnnil--- no link found, just skip end iftrackingthen -- update state for tracking categories ifargs[1][1]andsitelinkthen -- transform supplied page name to be in wiki-format localpage=mw.ustring.gsub(args[1][1],"_"," ") page=mw.ustring.sub(page,1,1):upper()..mw.ustring.sub(page,2) localpageNS=mw.ustring.match(page,"^([^:]+):") localsitelinkNS=mw.ustring.match(sitelink,"^([^:]+):") ifpage==sitelinkthen tracking.wdHidden=args.sisterPrefix elseifpageNS~=sitelinkNSthen tracking.wdNamespace=args.sisterPrefix else tracking.wdMismatch=args.sisterPrefix end -- if no page link, nor a wikidata entry, and search is on, then warn elseifnot(args[1][2]orsitelink)andargs.searchthen tracking.defaultSearch=args.sisterPrefix end end return{prefix=args.sisterPrefix,link=link,logo=args.logo,class=args.class, name=args.name,information=args.information,prep=args.prep} end -- Function to handle special case of commons link localfunctioncommonsLinks(args,commonsPage) -- use [[Module:Commons link]] to determine best commons link localcommonsLink=require('Module:Commons link') localcLink=(notargs.commonscat)andcommonsLink._hasGallery(args.qid) orcommonsLink._hasCategory(args.qid) ifcommonsPage[1]andnotmw.ustring.match(commonsPage[1]:lower(),"^category:")then commonsPage[1]=(args.commonscatand"Category:"or"")..commonsPage[1] end localcommonsSearch="Search/"..(args.commonscatand"Category:"or"")..args[1] return{link=cLink,search=commonsSearch} end -- Function to handle special case for "author" and "cookbook" localfunctionhandleSubtype(args) localns=args.ns localns_len=mw.ustring.len(ns) localresult={} result.sitelink=fetchWikidata(args.prefix,args.qid) localsubtype=false ifargs.pagethen ifmw.ustring.sub(args.page,1,ns_len)==nsthen subtype=true elseifargs.subtypethen result.page=ns..args.page subtype=true end elseifresult.sitelinkthen subtype=mw.ustring.sub(result.sitelink,1,ns_len)==ns elseifargs.subtypethen result.search="Search/"..ns..args.default subtype=true end ifsubtypethen result.info=args.info end returnresult end -- Function to create a sister link, by prefix -- Arguments: -- prefix = sister prefix (e.g., "c" for commons) -- args = arguments for this sister (see p._sisterLink above) -- tracking = tracking table localfunctionsisterLink(prefix,args,tracking) -- determine arguments to genSisterLink according to prefix ifprefix=='species_author'andnotargs.species[1]andargs.species[2]andnotargs.species_author[1]andargs.species_author[2]then returnnil end localdefault=defaultSisters[prefix] ifdefault=='auto'then default=args.auto end -- Handle exceptions by prefix localsearch=((prefix=='d'and"ItemByTitle/enwiki/")or"Search/")..args[1] localsitelink=prefix=='d'andargs.qid localpage=args[prefix] localinfo=sisterInfo[prefix] -- special case handling of author and cookbook localsubtype=nil ifprefix=='s'then subtype=handleSubtype({prefix='s',qid=args.qid,subtype=args.author,page=page[1], ns='Author:',info=nil,default=args[1]}) elseifprefix=='b'then subtype=handleSubtype({prefix='b',qid=args.qid,subtype=args.cookbook,page=page[1], ns='Cookbook:',info='Recipes',default=args[1]}) end ifsubtypethen page[1]=subtype.pageorpage[1] search=subtype.searchorsearch sitelink=subtype.sitelinkorsitelink info=subtype.infoorinfo end ifprefix=='voy'then ifnotargs.barthen info="Travel information" end ifpage[1]then ifmw.ustring.match(page[1],"phrasebook")then info="Phrasebook" end elseifpage[2]orargs.autothen sitelink=sitelinkorfetchWikidata('voy',args.qid) ifsitelinkandmw.ustring.match(sitelink,"phrasebook")then info="Phrasebook" end end end info=args.informationorinfo ifprefix=='c'then localcommons=commonsLinks(args,page) search=commons.search sitelink=commons.link end prefix=(prefix=='species_author'and'species')orprefix locallogo=logo[prefix] localclass="noviewer"..(darkOnLight[prefix]and" skin-invert-image"or"") localname=sisterName[prefix] localprep="from" ifmw.ustring.sub(prefix,1,2)=='iw'then locallang=nil localiw_arg=args[prefix] ifiw_arg[1]then lang=iw_arg[1] elseifiw_arg[2]then localP424=mw.wikibase.getBestStatements(args.qid,"P424")[1] ifP424andP424.mainsnak.datavaluethen lang=P424.mainsnak.datavalue.value end end iflang==nilthen returnnil end prefix=':'..lang page[1]="" page[2]=true locallangname=mw.language.fetchLanguageName(lang,'en') ifnotlangnameor#langname==0then returnnil end info=langname..' '..info prep="of" end returngenSisterLink({ page, auto=args.auto, qid=args.qid, logo=logo, class=class, name=name, prep=prep, sitelink=sitelink, default=default, sisterPrefix=prefix, search=search, information=info},tracking) end localfunctiontemplatestyles_page(is_bar) localsandbox=inSandboxand'sandbox/'or'' ifis_barthen returnmw.ustring.format( 'Module:Sister project links/bar/%sstyles.css', sandbox ) end returnmw.ustring.format( 'Module:Sister project links/%sstyles.css', sandbox ) end -- Function to create html containers for sister project link list -- Arguments: -- args = table of arguments -- args.position: if 'left', position links to left -- args.collapsible: if non-empty, make box collapsible. If 'collapse', start box hidden -- args.style: CSS style string appended to end of default CSS -- args.display: boldface name to display localfunctioncreateSisterBox(sisterList,args) locallist=mw.html.create('ul') fori,linkinipairs(sisterList)do localli=list:tag('li') -- html element for 27px-high logo locallogoSpan=li:tag('span') logoSpan:addClass(sandbox("sister-logo")) logoSpan:wikitext("[[File:"..link.logo.."|class="..link.class.."|27x27px|middle"..suppressLink(link.prefix).."|alt=]]") -- html element for link locallinkspan=li:tag('span') linkspan:addClass(sandbox("sister-link")) locallinkText="[["..link.prefix..":"..link.link.."|"..link.information.."]] "..link.prep.." "..link.name linkspan:wikitext(linkText) end list:allDone() returnsideBox({ role='navigation', labelledby='sister-projects', class=sandbox("sister-box")..' sistersitebox plainlinks', position=args.position, style=args.style, abovestyle=args.collapsibleand'clear: both'ornil, above=mw.ustring.format( "<b>%s</b> at Wikipedia's [[Wikipedia:Wikimedia sister projects|<span id=\"sister-projects\">sister projects</span>]]", args.displayorargs[1] ), text=tostring(list), collapsible=args.collapsible, templatestyles=templatestyles_page() }) end localfunctioncreateSisterBar(sisterList,args) localnav=mw.html.create('div') nav:addClass('noprint') nav:addClass('metadata') nav:addClass(sandbox('sister-bar')) nav:attr('role','navigation') nav:attr('aria-label','sister-projects') localheader=nav:tag('div') header:addClass(sandbox('sister-bar-header')) localpagename=header:tag('b') pagename:wikitext(args.displayorargs[1]) localheaderText=" at Wikipedia's [[Wikipedia:Wikimedia sister projects|" headerText=headerText..'<span id="sister-projects" style="white-space:nowrap;">sister projects</span>]]:' header:wikitext(headerText) if#sisterList==1andargs.trackSinglethen header:wikitext("[[Category:Pages with single-entry sister bar]]") end localcontainer=nav:tag('ul') container:addClass(sandbox('sister-bar-content')) for_,linkinipairs(sisterList)do localitem=container:tag('li') item:addClass(sandbox('sister-bar-item')) locallogoSpan=item:tag('span') logoSpan:addClass(sandbox('sister-bar-logo')) logoSpan:wikitext("[[File:"..link.logo.."|class="..link.class.."|21x19px"..suppressLink(link.prefix).."|alt=]]") locallinkSpan=item:tag('span') linkSpan:addClass(sandbox('sister-bar-link')) linkSpan:wikitext("<b>[["..link.prefix..":"..link.link.."|"..link.information.."]]</b> "..link.prep.." "..link.name) end returnnav end functionp._main(args) localtitleObject=mw.title.getCurrentTitle() localns=titleObject.namespace -- find qid, either supplied with args, from search string, or from current page args.qid=args.qidormw.wikibase.getEntityIdForTitle(args[1]or"")ormw.wikibase.getEntityIdForCurrentPage() args.qid=args.qidandargs.qid:upper() -- search string defaults to PAGENAME args[1]=args[1]ormw.wikibase.getSitelink(args.qidor"")ortitleObject.text -- handle redundant "commons"/"c" prefix args.c=args.corargs.commons -- Canonicalize all sister links (handle yes/no/empty) for_,kinipairs(prefixList)do args[k]=canonicalize(args[k]) end -- Canonicalize cookbook args.cookbook=canonicalize(args.cookbook) args.b=mergeArgs({args.b,args.cookbook}) args.cookbook=args.cookbook[2] -- handle trackSingle parameter ifargs.trackSingle==nilthen args.trackSingle=true end ifns~=0andns~=14then args.trackSingle=false end -- Canonicalize general parameters for_,kinpairs({"auto","commonscat","author","bar","tracking","sandbox","trackSingle"})do args[k]=canonicalize(args[k])[2] end -- Initialize tracking categories if main namespace localtracking=(args.trackingorns==0)and{} localsisterList={} localprefix -- Loop through all sister projects, generate possible links for_,prefixinipairs(prefixList)do locallink=sisterLink(prefix,args,tracking) iflinkthen table.insert(sisterList,link) end end localbox=mw.html.create() ifargs.barand#sisterList>0then box:wikitext(mw.getCurrentFrame():extensionTag{ name='templatestyles',args={src=templatestyles_page(true)} }) box:node(createSisterBar(sisterList,args)) elseif#sisterList==1then -- Use single sister box instead of multi-sister box localsister=sisterList[1] locallink="[["..sister.prefix..":"..sister.link.."|<b><i>"..(args.displayorargs[1]).."</i></b>]]" ifsister.name=='Commons'then sister.name='Wikimedia Commons'-- make single sister commons box look like {{Commons}} end localtext=sister.name.." has "..mw.ustring.lower(sister.information).." related to "..link.."." ifsister.name=='Wikipedia'then-- make single sister interwiki box look like {{InterWiki}} text="[["..sister.prefix..":"..sister.link.."|<b><i>"..sister.information.."</i></b>]] "..sister.prep.." [[Wikipedia]], the free encyclopedia" end box:wikitext(sideBox({ role='navigation', position=args.position, image="[[File:"..sister.logo.."|class="..sister.class.."|40x40px|alt="..suppressLink(sister.prefix).."]]", metadata='no', class='plainlinks sistersitebox', text=text, templatestyles=templatestyles_page() })) elseif#sisterList>0then -- else use sister box if non-empty box:wikitext(createSisterBox(sisterList,args)) end if#sisterList==0andargs.autothen localgenerateWarning=require('Module:If preview')._warning box:wikitext(generateWarning({"No sister project links found in Wikidata. Try auto=0"})) end -- Append tracking categories to container div -- Alpha ordering is by sister prefix iftrackingthen fork,vinpairs(tracking)do box:wikitext("[[Category:"..trackingType[k].."|"..v.."]]") end if#sisterList==0then box:wikitext("[[Category:Pages with empty sister project links]]") end end returntostring(box) end -- Main entry point for generating sister project links box functionp.main(frame) localargs=getArgs(frame,{frameOnly=false,parentOnly=false,parentFirst=false}) returnp._main(args) end -- Lua entry point for generate one sister link functionp._sisterlink(args) localprefix=args.prefix -- Canonicalize all sister links (handle yes/no/empty) for_,kinipairs(prefixList)do args[k]=canonicalize(args[k]) end -- Canonicalize cookbook args.cookbook=canonicalize(args.cookbook) args.b=mergeArgs({args.b,args.cookbook}) args.cookbook=args.cookbook[2] -- Canonicalize general parameters for_,kinpairs({"auto","commonscat","author"})do args[k]=canonicalize(args[k])[2] end args[1]=args[1]ormw.title.getCurrentTitle().text args.qid=args.qidormw.wikibase.getEntityIdForCurrentPage() args.qid=args.qidandargs.qid:upper() locallink=sisterLink(prefix,args,nil) ifnotlinkthen return"" end return"[["..link.prefix..":"..link.link.."|"..link.information.."]] "..link.prep.." "..link.name end -- Template entry point for generating one sister link functionp.link(frame) localargs=getArgs(frame) returnp._sisterlink(args) end returnp