|
|
Line 3: |
Line 3: |
| require('Module:No globals') | | require('Module:No globals') |
|
| |
|
| local getImageName = require( 'Module:Portal' ).image | | local portalModule = require('Module:Portal') |
| | local getImageName = portalModule.image |
| | local checkTracking = portalModule._checkTracking |
| | local processPortalArgs = portalModule._processPortalArgs |
| local yesno = require( 'Module:Yesno' ) | | local yesno = require( 'Module:Yesno' ) |
| | local getArgs = require('Module:Arguments').getArgs |
| local p = {} | | local p = {} |
|
| |
|
| local function checkPortalExists(portal) | | local function sandbox(args, s) |
| return not (mw.title.makeTitle(100, portal).id == 0) | | return args.sandbox and s.."-sand" or s |
| end
| |
| | |
| -- Check whether to do tracking in this namespace
| |
| -- Returns true unless the page is one of the banned namespaces
| |
| local function isTrackedNamespace()
| |
| local thisPageNS = mw.title.getCurrentTitle().namespace
| |
| return thisPageNS ~= 1 -- Talk
| |
| and thisPageNS ~= 2 -- User
| |
| and thisPageNS ~= 3 -- User talk
| |
| and thisPageNS ~= 5 -- Wikipedia talk
| |
| and thisPageNS ~= 7 -- File talk
| |
| and thisPageNS ~= 11 -- Template talk
| |
| and thisPageNS ~= 15 -- Category talk
| |
| and thisPageNS ~= 101 -- Portal talk
| |
| and thisPageNS ~= 118 -- Draft
| |
| and thisPageNS ~= 119 -- Draft talk
| |
| and thisPageNS ~= 829 -- Module talk
| |
| end
| |
| | |
| -- Check whether to do tracking on this pagename
| |
| -- Returns false if the page title matches one of the banned strings
| |
| -- Otherwise returns true
| |
| local function isTrackedPagename()
| |
| local thisPageLC = mw.ustring.lower(mw.title.getCurrentTitle().text)
| |
| local match = string.match
| |
| return match(thisPageLC, "/archive") == nil
| |
| and match(thisPageLC, "/doc") == nil
| |
| and match(thisPageLC, "/test") == nil
| |
| end | | end |
|
| |
|
Line 43: |
Line 19: |
| | | |
| -- Don't display a blank navbox if no portals were specified. | | -- Don't display a blank navbox if no portals were specified. |
| if #portals < 1 then return '' end | | if (not portals) or (#portals < 1) then return '' end |
| | | |
| local nav = mw.html.create( 'ul' ) | | -- check for sensible args |
| :addClass( 'portal-bar noprint metadata' )
| | args = type(args) == "table" and args or {} |
| :attr( 'role', 'navigation' )
| |
| :attr( 'aria-label' , 'Portals' )
| |
| if yesno( args.border ) == false then | |
| nav
| |
| :addClass('portal-bar-unbordered')
| |
| else
| |
| nav
| |
| :addClass( 'portal-bar-bordered' )
| |
| end
| |
| | | |
| local trackingEnabled = true | | -- Normalize arguments |
| local tracking = args.tracking | | for key, default in pairs({border=true,redlinks=false,sandbox=false,tracking=true}) do |
| if (tracking == 'no' or tracking == 'n' or tracking == 'false') or
| | if args[key] == nil then args[key] = default end |
| not isTrackedNamespace() or not isTrackedPagename() then | | args[key] = yesno(args[key], default) |
| trackingEnabled = false | |
| end | | end |
|
| |
|
| -- TODO: This used to say 'if no portals are specified', but we return early | | local nav = mw.html.create( 'div' ) |
| -- above. Someone should check whether this is really 'portals[1]' or #portals < 0.
| | :addClass(sandbox(args,'portal-bar')) |
| -- I don't believe the block in the conditional is reachable currently
| | :addClass( 'noprint metadata noviewer' ) |
| -- because if it were we would probably get a Lua script error because
| | :attr( 'role', 'navigation' ) |
| -- warning was previously undefined
| | :attr( 'aria-label' , 'Portals' ) |
| | :addClass(sandbox(args,args.border and 'portal-bar-bordered' or 'portal-bar-unbordered')) |
| | | |
| -- If the first portal is not specified, | | local trackingEnabled = args.tracking and checkTracking() |
| -- display an error and add the page to a tracking category.
| |
| if not portals[1] then
| |
| local nominimum = args.nominimum
| |
| local warning = mw.html.create()
| |
| if nominimum ~= 'yes' and nominimum ~= 'y' and nominimum ~= 'true' then
| |
| warning:tag('strong')
| |
| :addClass('error')
| |
| :wikitext('No portals specified: please specify at least one portal')
| |
| end
| |
| if trackingEnabled then
| |
| warning:wikitext('[[Category:Portal templates without a parameter]]')
| |
| end
| |
| return tostring(warning)
| |
| end
| |
|
| |
|
| -- scan for nonexistent portals, if they exist remove them from the portals | | -- scan for nonexistent portals, if they exist remove them from the portals |
| -- table. If redlinks=yes, then don't remove | | -- table. If redlinks=yes, then don't remove |
| local portallen = #portals | | local trackingCats = '' |
| -- traverse the list backwards to ensure that no portals are missed | | if not args.redlinks or trackingEnabled then |
| -- (table.remove also moves down the portals in the list, so that the next
| | local existingPortals = {} |
| -- portal isn't checked if going fowards. going backwards allows us to
| | for _, portal in ipairs(portals) do |
| -- circumvent this issue
| | local portalTitle = mw.title.new(portal,"Portal") |
| for i=portallen,1,-1 do
| | if portalTitle and portalTitle.exists then |
| -- the use of pcall here catches any errors that may occour when | | table.insert(existingPortals,portal) |
| -- attempting to locate pages when the page name is invalid. if pcall
| | elseif trackingEnabled then |
| -- returns true, then rerun the function to find if the page exists
| | trackingCats = "[[Category:Portal templates with redlinked portals]]" |
| if not pcall(checkPortalExists, portals[i]) or not checkPortalExists(portals[i]) then
| |
| -- Getting here means a redlinked portal has been found
| |
| local redlinks = args.redlinks | |
| if redlinks == 'yes' or redlinks == 'y' or redlinks == 'true' or redlinks == 'include' then | |
| -- if redlinks as been set to yes (or similar), add the cleanup | |
| -- category and then break the loop before the portal is removed
| |
| -- from the list
| |
| if trackingEnabled then
| |
| nav:wikitext('[[Category:Portal templates with redlinked portals]]')
| |
| end
| |
| -- TODO: This looks buggy given the comment above; we will always
| |
| -- break if redlinks are yes, whether or not tracking is enabled
| |
| break
| |
| end | | end |
| -- remove the portal (this does not happen if redlinks=yes)
| |
| table.remove(portals,i)
| |
| end | | end |
| end
| | portals = args.redlinks and portals or existingPortals |
|
| |
| -- if the length of the table is different, then rows were removed from the
| |
| -- table, so portals were removed. If this is the case add the cleanup category
| |
| if portallen ~= #portals then
| |
| if #portals == 0 then | | if #portals == 0 then |
| if trackingEnabled then
| | return trackingEnabled and "[[Category:Portal templates with all redlinked portals]]" or "" |
| return '[[Category:Portal templates with all redlinked portals]]'
| |
| else
| |
| return ""
| |
| end
| |
| end
| |
| if trackingEnabled then
| |
| nav:wikitext('[[Category:Portal templates with redlinked portals]]')
| |
| end | | end |
| end | | end |
| | | |
| | local header = nav:tag('span') |
| | header:addClass(sandbox(args,'portal-bar-header')) |
| | header:wikitext('[[Wikipedia:Contents/Portals|Portal]]') |
| | if #portals > 1 then |
| | header:wikitext('s') |
| | end |
| | header:wikitext(':') |
| | local container = nav:tag('div') |
| | container:addClass(sandbox(args,'portal-bar-content')) |
| for _, portal in ipairs( portals ) do | | for _, portal in ipairs( portals ) do |
| nav | | container |
| :tag( 'li' ) | | :tag( 'div' ) |
| | :addClass(sandbox(args,'portal-bar-item')) |
| :tag( 'span' ) | | :tag( 'span' ) |
| | :addClass(sandbox(args,'portal-bar-logo')) |
| :wikitext( string.format( | | :wikitext( string.format( |
| '[[File:%s|24x21px|alt=]]', getImageName{ portal } | | '[[File:%s|21x19px|alt=]]', getImageName{ portal } |
| ) ) | | ) ) |
| :done() | | :done() |
| :wikitext( string.format( | | :tag('span') |
| '[[Portal:%s|%s portal]]', portal, portal
| | :addClass(sandbox(args,'portal-bar-link')) |
| ) )
| | :wikitext( string.format('[[Portal:%s|%s]]', portal, portal)) |
| end | | end |
| | | |
| | local styleFile = 'Module:Portal bar/' |
| | styleFile = styleFile..(args.sandbox and 'sandbox/' or '') |
| | styleFile = styleFile..'styles.css' |
| return mw.getCurrentFrame():extensionTag{ | | return mw.getCurrentFrame():extensionTag{ |
| name = 'templatestyles', args = { src = 'Module:Portal bar/styles.css' } | | name = 'templatestyles', args = { src = styleFile } |
| } .. tostring( nav ) | | } .. tostring( nav ) .. trackingCats |
| end | | end |
|
| |
|
| -- Processes external arguments and sends them to the other functions. | | -- Processes external arguments and sends them to the other functions. |
| function p.main( frame ) | | function p.main( frame ) |
| -- If called via #invoke, use the args passed into the invoking template, or
| | local origArgs = getArgs(frame) |
| -- the args passed to #invoke if any exist. Otherwise assume args are being
| | local portals, args = processPortalArgs(origArgs) |
| -- passed directly in from the debug console or from another Lua module.
| |
| local origArgs | |
| if type( frame.getParent ) == 'function' then
| |
| origArgs = frame:getParent().args
| |
| for k, v in pairs( frame.args ) do
| |
| origArgs = frame.args
| |
| break
| |
| end
| |
| else
| |
| origArgs = frame
| |
| end
| |
| -- Process the args to make an array of portal names that can be used with
| |
| -- ipairs. We need to use ipairs because we want to list all the portals in
| |
| -- the order they were passed to the template, but we also want to be able
| |
| -- to deal with positional arguments passed explicitly, for example
| |
| -- {{portal|2=Politics}}. The behaviour of ipairs is undefined if nil values
| |
| -- are present, so we need to make sure they are all removed.
| |
| local portals, args = {}, {} | |
| for k, v in pairs( origArgs ) do
| |
| -- Make sure we have no non-string portal names.
| |
| if type( k ) == 'number' and type( v ) == 'string' then
| |
| if mw.ustring.find( v, '%S' ) then -- Remove blank values.
| |
| table.insert( portals, k )
| |
| end
| |
| elseif type( k ) ~= 'number' then -- Separate named arguments from portals.
| |
| if type( v ) == 'string' then
| |
| v = mw.text.trim( v )
| |
| end
| |
| args[ k ] = v
| |
| end
| |
| end
| |
| table.sort( portals )
| |
| for i, v in ipairs( portals ) do
| |
| -- Swap keys with values, trimming whitespace.
| |
| portals[ i ] = mw.text.trim( origArgs[ v ] )
| |
| end
| |
| return p._main( portals, args ) | | return p._main( portals, args ) |
| end | | end |
|
| |
|
| return p | | return p |