Used primarily byTemplate:Extension andTemplate:Skin. Also defines aisOnGerrit
function that is used byTemplate:Unmaintained extension,Template:ExtensionInstall, andTemplate:SkinInstall. Autofill feature depends onModule:ExtensionJson.
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={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)doifto[n]thento[n][index]=vendendendlocalfunctioncat(title)return'[[Category:'..title..']]'endlocalfunctiontcat(title)returncat(title..translation)endlocalfunctiongetType(str,str2)localstr=mw.ustring.lower(str)iftypeAliases[str]thenstr=typeAliases[str]endlocalcnf=types[str]localresifcnfthenres=cnf[1]..'[[Category:'..cnf[2]..translation..']]'elseifstr=='_missing_'thenres=tcat('Extensions with invalid or missing type')elseifstr=='_demomode_'thenifstr2thenres=lang:ucfirst(str2)elseres="''unknown''"endelseres=(stror'\'\'unknown\'\'')..' [[Special:MyLanguage/Template:Extension#type|(\'\'\'\'\'invalid type\'\'\'\'\')]]'..tcat('Extensions with invalid or missing type')endendreturnresendlocalfunctiongetExtData()localpglocalpframe=mw.getCurrentFrame():getParent()ifpframeandpframe.args.repothenpg=pframe.args.repoelsepg=mw.title.getCurrentTitle().rootPageTitle:partialUrl()-- need to get rid of translation subpage.endreturnmw.loadData('Module:ExtensionJson')[pg]ormw.loadData('Module:ExtensionJson')[pg:gsub("_"," ")]endlocalfunctiongetPopularityData()localpglocalpframe=mw.getCurrentFrame():getParent()ifpframeandpframe.args.repothenpg=pframe.args.repoelsepg=mw.title.getCurrentTitle().rootPageTitle:partialUrl()-- need to get rid of translation subpage.endtype='extensions'ifmw.title.getCurrentTitle().rootPageTitle:inNamespace('skin')thentype="skins"endreturnmw.loadJsonData('Template:Extension/popularity.json')[type][pg]endlocalfunctiongetLicenseString(str)str=mw.text.trim(str)ifstr==""orstr==nilthenlocaldata=getExtData()ifdataanddata["license-name"]thenstr=data["license-name"]elsestr="unspecified"endendreturnstrendlocalfunctiongetLicenseCategory(str)str=getLicenseString(str)ifmw.ustring.sub(str,-1)=='+'thenstr=mw.ustring.sub(str,1,-2)endlocalcnf=licenses[str]ifcnfthenif#cnf>2thenreturntcat(cats[cnf[3]])endelsereturntcat('Extensions with unknown license')endendlocalfunctiongetFormattedLicense(str,orlatertext)localorlater=''locallicense=getLicenseString(str)ifmw.ustring.sub(license,-1)=='+'thenlicense=mw.ustring.sub(license,1,-2)orlater=orlatertextendlocalcnf=licenses[license]ifcnfthenreturn(cnf[1]~=''and('['..cnf[1]..' '..cnf[2]..']')orcnf[2])..orlaterelsereturnlicenseendendlocalp={}functionp.getTypes(frame)setI18n(frame.args,types,1)localargs=frame:getParent().argslocaltypes={}localparams={args.type1orargs['type']or'missing',args.type2,args.type3,args.type4,args.type5,args.type6,}for_,paraminipairs(params)doifparam==nilormw.text.trim(param)==''thenbreakendlocalparam=mw.text.trim(param)ifargs.templatemode=='nocats'thentable.insert(types,getType('_demomode_',param))elsetable.insert(types,getType(param))endendreturntable.concat(types,', ')endfunctionp.getType(frame)setI18n(frame.args,types,1)returngetType(frame.args[1])endfunctionp.getLicenseCategory(frame)returngetLicenseCategory(frame.args[1])endfunctionp.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~=nilthenreturn'yes'endreturn''endfunctionp.getVersion(frame)ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""thenreturnframe.args[1]endlocaldata=getExtData()ifdata~=nilanddata.version~=nilthenreturndata.versionendreturn''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])~=""thenreturnframe.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')thenreturn''end-- Otherwise, look it up from extension.json.localdata=getExtData()ifdataanddata.requiresanddata.requires.MediaWikithenreturndata.requires.MediaWikiendlocalpargs=frame:getParent().argsifpargs.templatemode=="nocats"thenreturn''end-- If neither are given, just categorize.returntcat('Extensions without MediaWiki version')endfunctionp.getPHPRequirement(frame)-- If the first arg is given, it'll be the manual override value.ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""thenreturnframe.args[1]end-- Otherwise, look it up from extension.json.localdata=getExtData()-- unclear if we should somehow return other platform requirementsifdataanddata.requiresanddata.requires.platformanddata.requires.platform.phpthenreturndata.requires.platform.phpend-- Return nothing if unknownreturnend-- ---- Get the Composer name for the extension, with relevant categories.-- --functionp.getComposerName(frame)localname=nillocalhasManualName=false-- If the first arg is given, it'll be the manual override value.ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""thenname=frame.args[1]hasManualName=trueend-- Otherwise, look it up from extension.json.localdata=getExtData()localhasComposerName=falseifdataanddata.composerthenname=data.composerhasComposerName=trueend-- Tracking category for possibly mis-configured packages.ifhasManualNameandnothasComposerNamethencat('Extensions without name in composer.json')endifname~=nilthenreturn'[https://packagist.org/packages/'..name..' '..name..']'..tcat('Extensions supporting Composer')endendfunctionp.getHooks(frame)localhookOutput=frame.args.headerlocalhooks={}localindex=1localpframe=frame:getParent()localfoundLocalHooks=falsewhiletruedolocalargument=pframe.args["hook"..index]ifargumentandmw.text.trim(argument)~=""thenhooks[#hooks+1]=mw.text.trim(argument)foundLocalHooks=trueelsebreakendindex=index+1endifnotfoundLocalHooksthenlocaldata=getExtData()ifdata==nilordata.Hooks==nilthenreturn""endforhook,_inpairs(data.Hooks)dohooks[#hooks+1]=hookendtable.sort(hooks)endlocalfirst=truefor_,hookinipairs(hooks)doiffirstthenfirst=falseelsehookOutput=hookOutput..frame.args.delimendhookOutput=hookOutput..frame:expandTemplate{title="Extension/HookInUse",args={hook,templatemode=pframe.args.templatemode}}endreturnhookOutput..frame.args.footerendfunctionp.getParameters(frame)localdata=getExtData()ifdata==nilthenreturn""endlocalconfig=data.configifconfig==nilthenreturn""endlocalprefix="wg"localskip_prefix=falseifdata.manifest_versionanddata.manifest_version>=2thenifdata.config_prefixthenprefix=data.config_prefixendelseifconfig._prefixthenprefix=config._prefixskip_prefix=trueendendlocalout=""forkey,vinpairs(config)dolocalwrapper='<span>'iftype(v)=='table'andv.description~=nilthenlocaldesc=v.descriptioniftype(desc)=='table'then-- Shallow clone in order to make the table library happy with mw.loadDatadesc=require("Module:TableTools").shallowClone(desc)desc=table.concat(desc," ")endwrapper='<span title="'..mw.text.nowiki(desc)..'">'endifkey~='_prefix'ornotskip_prefixthenout=out.."* "..wrapper.."$"..prefix..key.."</span>\n"endendreturnoutend-- Used by Template:ParameterListfunctionp.makeParametersList(frame)localdata=getExtData()ifdata==nilthenreturn""endlocalconfig=data.configifconfig==nilthenreturn""endlocalprefix="wg"localskip_prefix=falseifdata.manifest_versionanddata.manifest_version>=2thenifdata.config_prefixthenprefix=data.config_prefixendelseifconfig._prefixthenprefix=config._prefixskip_prefix=trueendendlocalout=""forkey,vinpairs(config)dolocalwrapper='<code>'localdesc=niliftype(v)=='table'andv.description~=nilthendesc=v.descriptioniftype(desc)=='table'then-- Shallow clone in order to make the table library happy with mw.loadDatadesc=require("Module:TableTools").shallowClone(desc)desc=table.concat(desc," ")endendifkey~='_prefix'ornotskip_prefixthenout=out.."; "..wrapper.."$"..prefix..key.."</code>\n"ifdescthenout=out..":"..mw.text.nowiki(desc).."\n"endendendreturnoutendfunctionp.getRights(frame)localdata=getExtData()ifdata==nilthenreturn""endlocalrights=data.AvailableRightsifrights==nilthenreturn""endlocalout=""for_,rightinipairs(rights)doout=out.."* "..right.."\n"endreturnoutendfunctionp.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")thenlocalargs={}localpargs=frame:getParent().argsifpargs.templatemode=="nocats"thenargs.nocat="yes"endargs.alternative=pargs.alternativereturnframe:expandTemplate{title="Unmaintained extension",args=args}endendfunctionp.maintenanceLinks(frame)localbase=frame:expandTemplate{title="translatable"}ifbase==mw.title.getCurrentTitle().prefixedTextthenreturnendlocalout=""localcontent=mw.title.new(base):getContent()-- Check if the source page was archived or notifcontent:find("{{[aA]rchived ?[Ee]xtension")orcontent:find("{{TNT|[Aa]rchived ?[Ee]xtension")thenreturn"<span style='display:none'>[[Template:Extension/archived]]</span>"--Check if the source page was deleted or notelseifcontent:find("{{[dD]eleted extension security warning")thenreturn"<span style='display:none'>[[Template:Extension/vulnerabilities]]</span>"endendfunctionp.isOnGerrit(frame)localtitle=mw.title.getCurrentTitle()ifnottitle:inNamespace("Extension")andnottitle:inNamespace("Skin")thenreturn"n/a"endlocalbase=frame:expandTemplate{title="translatable"}localcontent=mw.title.new(base):getContent()ifcontent:find("{{Not on Gerrit")thenreturn""endifcontent:find("{{WikimediaDownload")orcontent:find("TNT|WikimediaDownload")orcontent:find("|repo%s*=")thenreturn"yes"endend-- ---- Get a category if the extension isn't in Module:ExtensionJson.--functionp.getExtensionJsonCategory(frame)ifgetExtData()==nilthenreturntcat('Extensions not in ExtensionJson')endend-- ---- Turn 1 into 1st. Probably bad for i18n.localfunctiongetOrdinal(n)ifn%10==1andn~=11thenreturnn.."<sup>st</sup>"endifn%10==2andn~=12thenreturnn.."<sup>nd</sup>"endifn%10==3andn~=13thenreturnn.."<sup>rd</sup>"endreturnn.."<sup>th</sup>"end-- ---- Get number of downloads this quarterfunctionp.getDownloads(frame)localdata=getPopularityData()ifdata==nilordata.downloads==nilthenreturn''endlocalnum=data.downloads['13w'];ifnum==0thenreturn"0"endlocalout=mw.getContentLanguage():formatNum(num)out=out.." (Ranked "..getOrdinal(data.downloadsRank['13w'])..")"returnoutend-- ---- Get number of downloads this quarterfunctionp.getPublicSites(frame)localdata=getPopularityData()ifdata==nilordata.siteCount==nilthenreturn''endlocalout=mw.getContentLanguage():formatNum(data.siteCount)out=out.." (Ranked "..getOrdinal(data.siteCountRank)..")"returnoutend-- ---- Get sites using this skin as default skinfunctionp.getPublicSitesSkinDefault(frame)localdata=getPopularityData()ifdata==nilordata.siteCountDefault==nilthenreturn''endlocalout=mw.getContentLanguage():formatNum(data.siteCountDefault)returnoutendfunctionp.getAuthor(frame)ifframe.args[1]~=nilandmw.text.trim(frame.args[1])~=""thenreturnframe.args[1]endlocaldata=getExtData()ifdata~=nilanddata.author~=niltheniftype(data.author)=="table"thenres=''fork,vinipairs(data.author)doifres~=''thenres=res..', 'endres=res..vendreturnreselsereturndata.authorendendreturn''endfunctionp.getDownload(frame)localdata=getExtData()ifdata~=nilthenrepo_url=data.repositoryifrepo_url==nilthenrepo_url=data.urlendifrepo_url==nilthenerror("AutoDownload: no repo URL")endaccount,repo=string.match(repo_url,"^https://github.com/([^/]+)/([^/]+)/?$")ifaccountthenreturnframe:expandTemplate{title="GithubDownload",args={account,repo:gsub("%.git","")}}endaccount,repo=string.match(repo_url,"^https://gitlab.com/(.+)/([^/]+)/?$")ifaccountthenreturnframe:expandTemplate{title="GitlabDownload",args={account,repo:gsub("%.git","")}}endaccount,repo=string.match(repo_url,"^https://bitbucket.org/([^/]+)/([^/]+)/?$")ifaccountthenreturnframe:expandTemplate{title="BitbucketDownload",args={account,repo:gsub("%.git","")}}endrepo=string.match(repo_url,"^https://gerrit.wikimedia.org/r/mediawiki/extensions/([^/]+)/?$")ifrepothenreturnframe:expandTemplate{title="WikimediaDownload",args={repo}}endreturnrepo_urlenderror("AutoDownload: Could not find ExtensionJson data")endreturnp