Module:Extension
Appearance
From mediawiki.org
Used primarily by Template:Extension and Template:Skin. Also defines a isOnGerrit function that is used by Template:Unmaintained extension, Template:ExtensionInstall, and Template:SkinInstall. Autofill feature depends on Module:ExtensionJson.
The above documentation is transcluded from Module:Extension/doc. (edit | history)
Editors can experiment in this module’s sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.
Editors can experiment in this module’s sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.
locallang=mw.language.getContentLanguage() localtranslation=mw.getCurrentFrame():callParserFunction{name='#translation',args="1"} localaddr={ GNU='//www.gnu.org/licenses/', OSI='//opensource.org/licenses/', CC='//creativecommons.org/licenses/', Mozilla='//www.mozilla.org/' } localcats={ GPL='GPL licensed extensions', FDL='FDL licensed extensions', LGPL='LGPL licensed extensions', AGPL='AGPL licensed extensions', MIT='MIT licensed extensions', ISC='ISC licensed extensions', BSD='BSD licensed extensions', MPL='MPL licensed extensions', WTFPL='WTFPL licensed extensions', Apache='Apache licensed extensions', PD='Public domain licensed extensions', CC='Creative Commons licensed extensions', ECL='Educational Community licensed extensions', Unlicense='The Unlicense licensed extensions', BLANK='Extensions with no license specified' } locallicenses={ ['AGPL-3.0']={addr.GNU..'agpl-3.0.html','GNU Affero General Public License 3.0','AGPL'}, ['AGPL-3.0-only']={addr.GNU..'agpl-3.0.html','GNU Affero General Public License 3.0','AGPL'}, ['AGPL-3.0-or-later']={addr.GNU..'agpl-3.0.html','GNU Affero General Public License 3.0 or later','AGPL'}, ['Apache-2.0']={'//www.apache.org/licenses/LICENSE-2.0','Apache License 2.0','Apache'}, ['BSD-2-Clause']={addr.OSI..'BSD-2-Clause','BSD 2-clause "Simplified" License','BSD'}, ['BSD-3-Clause']={addr.OSI..'BSD-3-Clause','BSD 3-clause "Modified" License','BSD'}, ['BSD-4-Clause']={addr.GNU..'license-list.html#OriginalBSD','BSD 4-clause "Original" License','BSD'}, ['CC-BY-3.0']={addr.CC..'by/3.0/','Creative Commons Attribution 3.0','CC'}, ['CC-BY-3.0-US']={addr.CC..'by/3.0/us/','Creative Commons Attribution 3.0 United States','CC'}, ['CC-BY-NC-3.0']={addr.CC..'by-nc/3.0/','Creative Commons Attribution NonCommercial 3.0','CC'}, ['CC-BY-NC-SA-2.5']={addr.CC..'by-nc-sa/2.5/','Creative Commons Attribution NonCommercial Share Alike 2.5','CC'}, ['CC-BY-NC-SA-3.0']={addr.CC..'by-nc-sa/3.0/','Creative Commons Attribution NonCommercial Share Alike 3.0','CC'}, ['CC-BY-NC-SA-4.0']={addr.CC..'by-nc-sa/4.0/','Creative Commons Attribution NonCommercial Share Alike 4.0','CC'}, ['CC-BY-SA-2.0']={addr.CC..'by-sa/2.0/','Creative Commons Attribution Share Alike 2.0','CC'}, ['CC-BY-SA-2.0-UK']={addr.CC..'by-sa/2.0/uk/','Creative Commons Attribution Share Alike 2.0 England and Wales','CC'}, ['CC-BY-SA-2.5']={addr.CC..'by-sa/2.5/','Creative Commons Attribution Share Alike 2.5','CC'}, ['CC-BY-SA-3.0']={addr.CC..'by-sa/3.0/','Creative Commons Attribution Share Alike 3.0','CC'}, ['CC-BY-SA-4.0']={addr.CC..'by-sa/4.0/','Creative Commons Attribution Share Alike 4.0','CC'}, ['CC0-1.0']={'//creativecommons.org/publicdomain/zero/1.0/','Creative Commons Zero v1.0 Universal','PD'}, ['ECL-2.0']={'','[[wikipedia:Educational Community License|Educational Community License 2.0]]','ECL'}, ['FDL']={addr.GNU..'fdl.html','GNU Free Documentation License','FDL'}, ['GPL-2.0']={addr.GNU..'old-licenses/gpl-2.0-standalone.html','GNU General Public License 2.0','GPL'}, ['GPL-2.0-only']={addr.GNU..'old-licenses/gpl-2.0-standalone.html','GNU General Public License 2.0 only','GPL'}, ['GPL-2.0-or-later']={addr.GNU..'old-licenses/gpl-2.0-standalone.html','GNU General Public License 2.0 or later','GPL'}, ['GPL-3.0']={addr.GNU..'gpl-3.0-standalone.html','GNU General Public License 3.0','GPL'}, ['GPL-3.0-only']={addr.GNU..'gpl-3.0-standalone.html','GNU General Public License 3.0 only','GPL'}, ['GPL-3.0-or-later']={addr.GNU..'gpl-3.0-standalone.html','GNU General Public License 3.0 or later','GPL'}, ['ISC']={addr.OSI..'ISC','ISC License','ISC'}, ['LGPL-2.0-only']={addr.GNU..'old-licenses/lgpl-2.0-standalone.html','GNU Library General Public License v2 only','LGPL'}, ['LGPL-2.1']={addr.GNU..'old-licenses/lgpl-2.1-standalone.html','GNU Lesser General Public License 2.1','LGPL'}, ['LGPL-2.1-only']={addr.GNU..'old-licenses/lgpl-2.1-standalone.html','GNU Lesser General Public License 2.1 only','LGPL'}, ['LGPL-2.1-or-later']={addr.GNU..'old-licenses/lgpl-2.1-standalone.html','GNU Lesser General Public License 2.1 or later','LGPL'}, ['LGPL-3.0']={addr.GNU..'lgpl-3.0-standalone.html','GNU Lesser General Public License 3.0','LGPL'}, ['LGPL-3.0-only']={addr.GNU..'lgpl-3.0-standalone.html','GNU Lesser General Public License 3.0 only','LGPL'}, ['LGPL-3.0-or-later']={addr.GNU..'lgpl-3.0-standalone.html','GNU Lesser General Public License 3.0 or later','LGPL'}, ['MIT']={addr.OSI..'mit-license.php','MIT License','MIT'}, ['MPL-1.0']={addr.Mozilla..'MPL/1.0/','Mozilla Public License 1.0','MPL'}, ['MPL-2.0']={addr.Mozilla..'MPL/2.0/','Mozilla Public License 2.0','MPL'}, ['PD']={'','[[wikipedia:Public domain|Public domain]]','PD'}, ['Unlicense']={'https://unlicense.org/','The Unlicense','Unlicense'}, ['WTFPL']={'http://www.wtfpl.net','WTFPL 2.0','WTFPL'}, ['Zlib']={addr.OSI..'Zlib','zlib License'}, ['unspecified']={'','No license specified','BLANK'} } localtypes={ ai={'[[w:Artificial intelligence|Artificial intelligence]]','Artificial intelligence extensions'}, ajax={'[[w:AJAX|Ajax]]','Ajax extensions'}, api={'[[API:Action API|API]]','API extensions'}, ['beta feature']={'[[Beta Features|Beta Feature]]','Beta Feature extensions'}, contenthandler={'[[Manual:ContentHandler|ContentHandler]]','ContentHandler extensions'}, database={'[[Manual:Database layout|Database]]','Database extensions'}, ['data extraction']={'Data extraction','Data extraction extensions'}, example={'Example','Extension examples'}, ['extended syntax']={'[[Manual:Extending wiki markup|Extended syntax]]','Extended syntax extensions'}, filerepo={'File repository','File repository extensions'}, hook={'[[Manual:Hooks|Hook]]','Hook extensions'}, interface={'User interface','User interface extensions'}, link={'[[Manual:Extending wiki markup|Link markup]]','Link markup extensions'}, media={'Media','Media handling extensions'}, mywiki={'[[Manual:Personalization|MyWiki]]','Personalization extensions'}, notify={'Notify','Notification extensions'}, ['page action']={'[[Manual:Parameters to index.php#Actions|Page action]]','Page action extensions'}, parser={'[[Manual:Extending wiki markup|Parser extension]]','Parser extensions'}, ['parser function']={'[[Manual:Parser functions|Parser function]]','Parser function extensions'}, php={'PHP','PHP extensions'}, search={'Search','Search extensions'}, skin={'[[Manual:Skins|Skin]]','Skin extensions'}, ['special page']={'[[Manual:Special pages|Special page]]','Special page extensions'}, locale={'[[Manual:Localization|Locale]]','Internationalization extensions'}, tag={'[[Manual:Tag extensions|Tag]]','Tag extensions'}, ['user access']={'[[Manual:Security|User access]]','User access extensions'}, ['user identity']={'[[Manual:Security|User identity]]','User identity extensions'}, ['user rights']={'[[Manual:Security|User rights]]','User rights extensions'}, ['user activity']={'[[Manual:Security|User activity]]','User activity extensions'}, variable={'[[Manual:Variables|Variable]]','Variable extensions'}, } localtypeAliases={ db='database', pfunc='parser function', special='special page', } localfunctionsetI18n(from,to,index) forn,vinpairs(from)do ifto[n]then to[n][index]=v end end end localfunctioncat(title) return'[[Category:'..title..']]' end localfunctiontcat(title) returncat(title..translation) end localfunctiongetType(str,str2) localstr=mw.ustring.lower(str) iftypeAliases[str]then str=typeAliases[str] end localcnf=types[str] localres ifcnfthen res=cnf[1]..'[[Category:'..cnf[2]..translation..']]' else ifstr=='_missing_'then res=tcat('Extensions with invalid or missing type') elseifstr=='_demomode_'then ifstr2then res=lang:ucfirst(str2) else res="''unknown''" end else res=(stror'\'\'unknown\'\'').. ' [[Special:MyLanguage/Template:Extension#type|(\'\'\'\'\'invalid type\'\'\'\'\')]]'.. tcat('Extensions with invalid or missing type') end end returnres end localfunctiongetExtData() localpg localpframe=mw.getCurrentFrame():getParent() ifpframeandpframe.args.repothen pg=pframe.args.repo else pg=mw.title.getCurrentTitle().rootPageTitle:partialUrl()-- need to get rid of translation subpage. end localdataTitle=mw.title.new('ExtensionJson/'..pg..'.json','Module') ifdataTitleanddataTitle.existsanddataTitle.contentModel=='json'then returnmw.loadJsonData(dataTitle.prefixedText)['master'] end returnnil end localfunctiongetPopularityData() localpg localpframe=mw.getCurrentFrame():getParent() ifpframeandpframe.args.repothen pg=pframe.args.repo else pg=mw.title.getCurrentTitle().rootPageTitle:partialUrl()-- need to get rid of translation subpage. end type='extensions' ifmw.title.getCurrentTitle().rootPageTitle:inNamespace('skin')then type="skins" end returnmw.loadJsonData('Template:Extension/popularity.json')[type][pg] end localfunctiongetLicenseString(str) str=mw.text.trim(str) ifstr==""orstr==nilthen localdata=getExtData() ifdataanddata["license-name"]then str=data["license-name"] else str="unspecified" end end returnstr end localfunctiongetLicenseCategory(str) str=getLicenseString(str) ifmw.ustring.sub(str,-1)=='+'then str=mw.ustring.sub(str,1,-2) end localcnf=licenses[str] ifcnfthen if#cnf>2then returntcat(cats[cnf[3]]) end else returntcat('Extensions with unknown license') end end localfunctiongetFormattedLicense(str,orlatertext) localorlater='' locallicense=getLicenseString(str) ifmw.ustring.sub(license,-1)=='+'then license=mw.ustring.sub(license,1,-2) orlater=orlatertext end localcnf=licenses[license] ifcnfthen return(cnf[1]~=''and('['..cnf[1]..' '..cnf[2]..']')orcnf[2])..orlater else returnlicense end end localp={} functionp.getTypes(frame) setI18n(frame.args,types,1) localargs=frame:getParent().args localtypes={} localparams={ args.type1orargs['type']or'missing', args.type2, args.type3, args.type4, args.type5, args.type6, } for_,paraminipairs(params)do ifparam==nilormw.text.trim(param)==''then break end localparam=mw.text.trim(param) ifargs.templatemode=='nocats'then table.insert(types,getType('_demomode_',param)) else table.insert(types,getType(param)) end end returntable.concat(types,', ') end functionp.getType(frame) setI18n(frame.args,types,1) returngetType(frame.args[1]) end functionp.getLicenseCategory(frame) returngetLicenseCategory(frame.args[1]) end functionp.getFormattedLicense(frame) setI18n(frame.args,licenses,2) returngetFormattedLicense(frame.args[1],frame.args['+']or' or later') end -- Return if the extension does schema updates -- Only answer yes. For now be silent on no or unknown, as its unclear -- if this info should be in infobox if the answer is not yes. functionp.getNeedsUpdates(frame) localdata=getExtData() ifdata~=nilanddata.Hooks~=nilanddata.Hooks.LoadExtensionSchemaUpdates~=nilthen return'yes' end return'' end functionp.getVersion(frame) ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""then returnframe.args[1] end localdata=getExtData() ifdata~=nilanddata.version~=nilthen returndata.version end return'' end -- -- -- Get the requires.MediaWiki value from extension.json -- @link https://www.mediawiki.org/wiki/Manual:Extension.json/Schema#requires -- -- functionp.getMediaWikiRequirement(frame) -- If the first arg is given, it'll be the manual override value. ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""then returnframe.args[1]..tcat('Extensions with manual MediaWiki version') end -- If the compatibility policy is rel or ltsrel, then don't display something -- here because it likely disagrees with the compatibility policy. ifframe.args[2]~=nilandmw.ustring.find(frame.args[2],'rel')then return'' end -- Otherwise, look it up from extension.json. localdata=getExtData() ifdataanddata.requiresanddata.requires.MediaWikithen returndata.requires.MediaWiki end localpargs=frame:getParent().args ifpargs.templatemode=="nocats"then return'' end -- If neither are given, just categorize. returntcat('Extensions without MediaWiki version') end functionp.getPHPRequirement(frame) -- If the first arg is given, it'll be the manual override value. ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""then returnframe.args[1] end -- Otherwise, look it up from extension.json. localdata=getExtData() -- unclear if we should somehow return other platform requirements ifdataanddata.requiresanddata.requires.platformanddata.requires.platform.phpthen returndata.requires.platform.php end -- Return nothing if unknown return end -- -- -- Get the Composer name for the extension, with relevant categories. -- -- functionp.getComposerName(frame) localname=nil localhasManualName=false -- If the first arg is given, it'll be the manual override value. ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""then name=frame.args[1] hasManualName=true end -- Otherwise, look it up from extension.json. localdata=getExtData() localhasComposerName=false ifdataanddata.composerthen name=data.composer hasComposerName=true end -- Tracking category for possibly mis-configured packages. ifhasManualNameandnothasComposerNamethen cat('Extensions without name in composer.json') end ifname~=nilthen return'[https://packagist.org/packages/'..name..' '..name..']' ..tcat('Extensions supporting Composer') end end functionp.getHooks(frame) localhookOutput=frame.args.header localhooks={} localindex=1 localpframe=frame:getParent() localfoundLocalHooks=false whiletruedo localargument=pframe.args["hook"..index] ifargumentandmw.text.trim(argument)~=""then hooks[#hooks+1]=mw.text.trim(argument) foundLocalHooks=true else break end index=index+1 end ifnotfoundLocalHooksthen localdata=getExtData() ifdata==nilordata.Hooks==nilthen return"" end forhook,_inpairs(data.Hooks)do hooks[#hooks+1]=hook end table.sort(hooks) end localfirst=true for_,hookinipairs(hooks)do iffirstthen first=false else hookOutput=hookOutput..frame.args.delim end hookOutput=hookOutput..frame:expandTemplate{title="Extension/HookInUse",args={hook,templatemode=pframe.args.templatemode}} end returnhookOutput..frame.args.footer end functionp.getParameters(frame) localdata=getExtData() ifdata==nilthen return"" end localconfig=data.config ifconfig==nilthen return"" end localprefix="wg" localskip_prefix=false ifdata.manifest_versionanddata.manifest_version>=2then ifdata.config_prefixthen prefix=data.config_prefix end else ifconfig._prefixthen prefix=config._prefix skip_prefix=true end end localout="" forkey,vinpairs(config)do localwrapper='<span class="configvariable">' iftype(v)=='table'andv.description~=nilthen localdesc=v.description iftype(desc)=='table'then -- Shallow clone in order to make the table library happy with mw.loadData desc=require("Module:TableTools").shallowClone(desc) desc=table.concat(desc," ") end wrapper='<span class="configvariable" title="'..mw.text.nowiki(desc)..'">' end ifkey~='_prefix'ornotskip_prefixthen out=out.."* "..wrapper.."$"..prefix..key.."</span>\n" end end returnout end -- Used by Template:ParameterList functionp.makeParametersList(frame) localdata=getExtData() ifdata==nilthen return"" end localconfig=data.config ifconfig==nilthen return"" end localprefix="wg" localskip_prefix=false ifdata.manifest_versionanddata.manifest_version>=2then ifdata.config_prefixthen prefix=data.config_prefix end else ifconfig._prefixthen prefix=config._prefix skip_prefix=true end end localout="" forkey,vinpairs(config)do localwrapper='<code class="configvariablevar">' localdesc=nil iftype(v)=='table'andv.description~=nilthen desc=v.description iftype(desc)=='table'then -- Shallow clone in order to make the table library happy with mw.loadData desc=require("Module:TableTools").shallowClone(desc) desc=table.concat(desc," ") end end ifkey~='_prefix'ornotskip_prefixthen out=out.."; "..wrapper.."$"..prefix..key.."</code>\n" ifdescthen out=out..":"..mw.text.nowiki(desc).."\n" end end end returnout end functionp.getRights(frame) localdata=getExtData() ifdata==nilthen return"" end localrights=data.AvailableRights ifrights==nilthen return"" end localout="" for_,rightinipairs(rights)do out=out.."* "..right.."\n" end returnout end functionp.unmaintained(frame) localcontent=mw.title.getCurrentTitle():getContent() ifnotcontent:find("{{[uU]nmaintained extension")andnotcontent:find("{{TNT|[uU]nmaintained extension") andnotcontent:find("{{User:Jeroen[ _]De[ _]Dauw/unmaintained")then localargs={} localpargs=frame:getParent().args ifpargs.templatemode=="nocats"then args.nocat="yes" end args.alternative=pargs.alternative returnframe:expandTemplate{title="Unmaintained extension",args=args} end end functionp.maintenanceLinks(frame) localbase=frame:expandTemplate{title="translatable"} ifbase==mw.title.getCurrentTitle().prefixedTextthen return end localout="" localcontent=mw.title.new(base):getContent() -- Check if the source page was archived or not ifcontent:find("{{[aA]rchived ?[Ee]xtension")orcontent:find("{{TNT|[Aa]rchived ?[Ee]xtension")then return"<span style='display:none'>[[Template:Extension/archived]]</span>" --Check if the source page was deleted or not elseifcontent:find("{{[dD]eleted extension security warning")then return"<span style='display:none'>[[Template:Extension/vulnerabilities]]</span>" end end functionp.isOnGerrit(frame) localtitle=mw.title.getCurrentTitle() ifnottitle:inNamespace("Extension")andnottitle:inNamespace("Skin")then return"n/a" end localbase=frame:expandTemplate{title="translatable"} localcontent=mw.title.new(base):getContent() ifcontent:find("{{Not on Gerrit")then return"" end ifcontent:find("{{WikimediaDownload")orcontent:find("TNT|WikimediaDownload")orcontent:find("|repo%s*=")then return"yes" end end -- -- -- Get a category if the extension isn't in Module:ExtensionJson. -- functionp.getExtensionJsonCategory(frame) ifgetExtData()==nilthen returntcat('Extensions not in ExtensionJson') end end -- -- -- Turn 1 into 1st. Probably bad for i18n. localfunctiongetOrdinal(n) ifn%10==1andn~=11then returnn.."<sup>st</sup>" end ifn%10==2andn~=12then returnn.."<sup>nd</sup>" end ifn%10==3andn~=13then returnn.."<sup>rd</sup>" end returnn.."<sup>th</sup>" end -- -- -- Get number of downloads this quarter functionp.getDownloads(frame) localdata=getPopularityData() ifdata==nilordata.downloads==nilthen return'' end localnum=data.downloads['13w']; ifnum==0then return"0" end localout=mw.getContentLanguage():formatNum(num) out=out.." (Ranked "..getOrdinal(data.downloadsRank['13w'])..")" returnout end -- -- -- Get number of downloads this quarter functionp.getPublicSites(frame) localdata=getPopularityData() ifdata==nilordata.siteCount==nilthen return'' end localout=mw.getContentLanguage():formatNum(data.siteCount) out=out.." (Ranked "..getOrdinal(data.siteCountRank)..")" returnout end -- -- -- Get sites using this skin as default skin functionp.getPublicSitesSkinDefault(frame) localdata=getPopularityData() ifdata==nilordata.siteCountDefault==nilthen return'' end localout=mw.getContentLanguage():formatNum(data.siteCountDefault) returnout end functionp.getAuthor(frame) ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""then returnframe.args[1] end localdata=getExtData() ifdata~=nilanddata.author~=nilthen iftype(data.author)=="table"then res='' fork,vinipairs(data.author)do ifres~=''then res=res..', ' end res=res..v end returnres else returndata.author end end return'' end functionp.getDownload(frame) localdata=getExtData() ifdata~=nilthen repo_url=data.repository ifrepo_url==nilthen repo_url=data.url end ifrepo_url==nilthen error("AutoDownload: no repo URL") end account,repo=string.match(repo_url,"^https://github.com/([^/]+)/([^/]+)/?$") ifaccountthen returnframe:expandTemplate{title="GithubDownload",args={account,repo:gsub("%.git","")}} end account,repo=string.match(repo_url,"^https://gitlab.com/(.+)/([^/]+)/?$") ifaccountthen returnframe:expandTemplate{title="GitlabDownload",args={account,repo:gsub("%.git","")}} end account,repo=string.match(repo_url,"^https://bitbucket.org/([^/]+)/([^/]+)/?$") ifaccountthen returnframe:expandTemplate{title="BitbucketDownload",args={account,repo:gsub("%.git","")}} end repo=string.match(repo_url,"^https://gerrit.wikimedia.org/r/mediawiki/extensions/([^/]+)/?$") ifrepothen returnframe:expandTemplate{title="WikimediaDownload",args={repo}} end returnrepo_url end error("AutoDownload: Could not find ExtensionJson data") end returnp