Module:Navigation

From Wikipedia

Documentation for this module may be created at Module:Navigation/doc

--require "mw.text"
--require "mw.page"

-- This table maps portal names onto image filenames.
-- The one unnamed entry is the default if there is no explicit entry for the portal.
local portal_images = { 
    "Portal-puzzle.svg",
    ["India"] = "Flag of India.svg",
    ["Washington"] = "Flag of Washington.svg",
    ["United States"] = "Flag of the United States.svg",
    ["Television"] = "Television icon.png",
    ["Seattle"] = "SpaceNeedleTopClose.jpg",
    ["Grey's Anatomy"] = "Grey's_Anatomy_Icon.gif"
}

-- Siblings are indexed by a canonical name.
local siblings = {
    commons     = { name = "Commons", logo = "Commons-logo.svg", suffix = "", what = "images and media" },
    meta        = { name = "the Wikimedia Community wiki", logo = "Wikimedia Community Logo.svg", suffix = "", what = "Wikimedia Community pages" },
    wikibooks   = { name = "Wikibooks", logo = "Wikibooks-logo-en-noslogan.svg", suffix = "", what = "textbooks" },
    wikiquote   = { name = "Wikiquote", logo = "Wikiquote-logo-en.svg", suffix = "", what = "quotations" },
    wikipedia   = { name = "Wikipedia", logo = "Wikipedia-logo-v2.svg", suffix = "", what = "encyclopædia articles" },
    wikisource  = { name = "Wikisource", logo = "Wikisource-logo.svg", suffix = "", what = "source documents" },
    wiktionary  = { name = "Wiktionary", logo = "Wiktionary-logo-en.svg", suffix = "#English", what = "definitions" },
    wikinews    = { name = "Wikinews", logo = "Wikinews-logo.svg", suffix = "", what = "news articles" },
    wikispecies = { name = "Wikispecies", logo = "Wikispecies-logo.svg", suffix = "", what = "species directories" },
    wikiversity = { name = "Wikiversity", logo = "Wikiversity-logo.svg", suffix = "", what = "learning resources" },
    mediawiki   = { name = "Mediawiki", logo = "Mediawiki.png", suffix = "", what = "MediaWiki information" },
    outreachwiki= { name = "Wikimedia Outreach",  logo = "Wikimedia Outreach.png", suffix = "", what = "outreach" },
    incubator   = { name = "the Wikimedia Incubator", logo = "Incubator-notext.svg", suffix = "", what = "incubated projects" },
    foundation  = { name = "the Wikimedia Foundation wiki", logo = "Incubator-notext.svg", suffix = "", what = "Wikimedia Foundation stuff" },
    { name = "Wikimedia", logo = "Wikimedia-logo.svg", suffix = "", what = "stuff" },
}

-- The interwiki map maps an interwiki prefix onto a canonical name.
-- The actual interwiki map used by the servers is at [[m:interwiki map]].
-- This map contains the subset of projects that are Wikimedia Foundation projects.
-- It also contains some prefixes that are used in templates but that aren't actually valid interwiki prefixes.
local interwiki_map = {
    commons = "commons",
    meta = "meta",
    m = "meta",
    metawiki = "meta",
    wikibooks = "wikibooks",
    b = "wikibooks",
    wb = "wikibooks",
    wbk = "wikibooks",
    wikiquote = "wikiquote",
    q = "wikiquote",
    wqt = "wikiquote",
    quote = "wikiquote",
    wikipedia = "wikipedia",
    w = "wikipedia",
    wp = "wikipedia",
    wikisource = "wikisource",
    s = "wikisource",
    ws = "wikisource",
    source = "wikisource",
    wiktionary = "wiktionary",
    d = "wiktionary",
    wkt = "wiktionary",
    wikt = "wiktionary",
    wdy = "wiktionary",
    wikinews = "wikinews",
    n = "wikinews",
    wnw = "wikinews",
    news = "wikinews",
    wikispecies = "wikispecies",
    species = "wikispecies",
    wikiversity = "wikiversity",
    v = "wikiversity",
    wvy = "wikiversity",
    mw = "wikiversity",
    outreachwiki = "outreachwiki",
    outreach = "outreachwiki",
}
local wikitext = require "Module:Wikitext"

local z = {}

local ucfirst = function (s)
    return s:sub(1,1):upper() .. s:sub(2,-1)
end

local moreatsibling = function (interwiki, pagename)
    local sibling = siblings[interwiki] or siblings[1]
    local what = ucfirst(sibling.what)
    return "[[File:" .. sibling.logo .. "|30x30px|link=|alt=]] [[" .. interwiki .. ":Special:Search/" .. pagename .. sibling.suffix .. "|" .. what .. "]]<br/>From " .. sibling.name
end

local sidebox = function (text, Margin, class)
    local style = "border:solid #aaa 1px; margin:" .. Margin .. ";"
    return mw.text.tag({name="div", contents="\n" .. table.concat(text), params={class=class, style=style}})
end

-- This is used by template {{subject bar}}.
function z.siblingbar(frame)
    local pframe = frame:getParent()
    local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
    local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
    
    local pagename = config.pagename
    local PediaPressBooks = {}
    local Portals = {}
    local Commons = args.commons or config.doc
    local Species = args.species or config.doc
    local News = args.n or args.news or config.doc
    local Wiktionary = args.wikt or args.d or config.doc
    local Books = args.b or args.books or config.doc
    local Quote = args.q or args.quote or config.doc
    local Source = args.s or args.source or config.doc
    local Versity = args.v or args.versity or config.doc
    local index
    
    index = 1
    while true do
        local book = args["book" .. index]
        if ( nil == book ) then break end
        PediaPressBooks[index] = book
        index = index + 1
    end
    if ( #PediaPressBooks < 1 ) then PediaPressBooks[1] = args.book end
    index = 1
    while true do
        local portal = args["portal" .. index]
        if ( nil == portal ) then break end
        Portals[index] = portal
        index = index + 1
    end
    if ( #Portals < 1 ) then Portals[1] = args.portal end
    
    local text = {}
    
    table.insert(text, "{| class=\"noprint navbox\" style=\"background-color: #F9F9F9; border: 1px solid #AAA; clear: both; margin-bottom: 0.5em; margin-top: 0.5em;\"\n")
    if ( #PediaPressBooks > 0 ) then
        local head = "|-\n| width=\"175pt\"|<span style=\"font-size:125%;\">'''[[Project:Books|Books]]'''</span><br><span style=\"font-size:85%;\">View or order collections of articles</span>\n|"
        local body = {}
        for i,v in ipairs(PediaPressBooks) do
            table.insert(body, "[[File:Office-book.svg|30px|link=|alt=]] '''''[[Book:" .. v .. "|" .. v .. "]]'''''")
        end
        table.insert(text, head .. table.concat(body) .. "\n")
    end
    if ( #Portals > 0 ) then
        local head = "|-\n| width=\"175pt\"|<span style=\"font-size:125%;\">'''[[Portal:Contents/Portals|Portals]]'''</span><br><span style=\"font-size:85%;\">Access related topics</span>\n|"
        local body = {}
        for i,v in ipairs(PediaPressBooks) do
            local image = portal_images[v] or portal_images[1]
            table.insert(body, "[[File:" .. image .. "|30px|link=|alt=]] '''''[[Portal:" .. v .. "|" .. v .. "]]'''''")
        end
        table.insert(text, head .. table.concat(body) .. "\n")
    end
    if ( Commons or Species or News or Wiktionary or Books or Quote or Source or Versity ) then
        local head = "|-\n| width=\"175pt\"|<span style=\"font-size:85%;\">Find out more on the</span><br><span style=\"font-size:125%;\">'''[[Project:Wikimedia sister projects|Sibling projects]]'''</span>\n|"
        local body = {}
        if ( Commons ) then 
            local CommonsSearch = args["commons-search"] or pagename
            table.insert(body, moreatsibling("commons", CommonsSearch))
        end
        if ( Species ) then 
            local SpeciesSearch = args["species-search"] or pagename
            table.insert(body, moreatsibling("wikispecies", SpeciesSearch))
        end
        if ( News ) then 
            local NewsSearch = args["n-search"] or args["news-search"] or pagename
            table.insert(body, moreatsibling("wikinews", NewsSearch))
        end
        if ( Wiktionary ) then 
            local WiktionarySearch = args["wikt-search"] or args["d-search"] or pagename
            table.insert(body, moreatsibling("wiktionary", WiktionarySearch))
        end
        if ( Books ) then 
            local BooksSearch = args["b-search"] or args["books-search"] or pagename
            table.insert(body, moreatsibling("wikibooks", BooksSearch))
        end
        if ( Quote ) then 
            local QuoteSearch = args["q-search"] or args["quote-search"] or pagename
            table.insert(body, moreatsibling("wikiquote", QuoteSearch))
        end
        if ( Source ) then 
            local SourceSearch = args["s-search"] or args["source-search"] or pagename
            table.insert(body, moreatsibling("wikisource", SourceSearch))
        end
        if ( Versity ) then 
            local VersitySearch = args["v-search"] or args["versity-search"] or pagename
            table.insert(body, moreatsibling("wikiversity", VersitySearch))
        end
        table.insert(text, head .. table.concat(body) .. "\n")
    end
    table.insert(text, "|}\n")
    
    return table.concat(text)
end

-- This is used by template {{sister project links}}.
function z.siblingbox(frame)
    local pframe = frame:getParent()
    local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
    local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
    
    local pagename = config.pagename
    local Commons = args.commons or config.doc
    local Species = args.species or config.doc
    local News = args.n or args.news or config.doc
    local Wiktionary = args.wikt or args.d or config.doc
    local Books = args.b or args.books or config.doc
    local Quote = args.q or args.quote or config.doc
    local Source = args.s or args.source or config.doc
    local Versity = args.v or args.versity or config.doc
    local Position = args.position
    if ( "left" == Position or "Left" == Position ) then Position = "-left" else Position = "" end
    
    local text = {}
    
    table.insert(text, "{| class=\"noprint metadata plainlinks mbox-small" .. Position .."\" style=\"background-color: #F9F9F9; border: 1px solid #AAA; clear: both; margin-bottom: 0.5em; margin-top: 0.5em;\"\n")
    table.insert(text, "|-\n| align=\"centre\"|Find out more on the '''[[Project:Wikimedia sister projects|sibling projects]]''':\n")
    if ( "no" ~= Commons ) then 
        local CommonsSearch = args["commons-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("commons", CommonsSearch) .. "\n")
    end
    if ( "no" ~= Species ) then 
        local SpeciesSearch = args["species-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wikispecies", SpeciesSearch) .. "\n")
    end
    if ( "no" ~= News ) then 
        local NewsSearch = args["n-search"] or args["news-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wikinews", NewsSearch) .. "\n")
    end
    if ( "no" ~= Wiktionary ) then 
        local WiktionarySearch = args["wikt-search"] or args["d-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wiktionary", WiktionarySearch) .. "\n")
    end
    if ( "no" ~= Books ) then 
        local BooksSearch = args["b-search"] or args["books-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wikibooks", BooksSearch) .. "\n")
    end
    if ( "no" ~= Quote ) then 
        local QuoteSearch = args["q-search"] or args["quote-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wikiquote", QuoteSearch) .. "\n")
    end
    if ( "no" ~= Source ) then 
        local SourceSearch = args["s-search"] or args["source-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wikisource", SourceSearch) .. "\n")
    end
    if ( "no" ~= Versity ) then 
        local VersitySearch = args["v-search"] or args["versity-search"] or pagename
        table.insert(text, "|-\n| " .. moreatsibling("wikiversity", VersitySearch) .. "\n")
    end        
    table.insert(text, "|}\n")
    
    return table.concat(text)
end

-- This is used by templates {{wiktionary}}, {{wikibooks}}, {{wikisource}}, {{commons}}, {{wikiquote}}, {{meta}}, {{wikispecies}}, and {{wikinews}}.
-- It entirely replaces template {{sister}}, which is now obsolete.
function z.sibling(frame)
    local pframe = frame:getParent()
    local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
    local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
    
    local pagename = config.pagename
    local wiki = config.interwiki
    local interwiki = interwiki_map[wiki] or interwiki_map[1]
    local Position = args.position or "right"
    local sibling = siblings[interwiki] or siblings[1]

    local index = 1
    local links = {}
    while true do
        local arg = args[index]
        if nil == arg then break end
        local link = "[[" .. interwiki .. ":Special:Search/" .. arg .. sibling.suffix .. "|" .. arg .. "]]"
        table.insert(links, link)
        index = index + 1
    end
    if index < 2 then
        local arg = args.search or pagename
        local link = "[[" .. interwiki .. ":Special:Search/" .. arg .. sibling.suffix .. "|" .. arg .. "]]"
        table.insert(links, link)
    end
    
    local text = {}
    local icon = "[[File:" .. sibling.logo .. "|30x30px|left|link=|alt=]] " 
    table.insert(text, icon)
    local linksdiv = mw.text.tag({name="div",params={style="margin-left:10px;"},contents=wikitext.oxfordlist(links,",","and")})
    local div = mw.text.tag({name="div",params={style="margin-left:30px;"},contents=sibling.name .. " has " .. sibling.what .. " for: " .. linksdiv})
    table.insert(text, div)

    local Margin = "0.5em 0.5em 0.5em 0"
    local Left = "t" .. Position
    return sidebox(text, Margin, "infobox " .. Left .. " sisterproject")
end

-- This is used by template {{portal}}.
function z.portal(frame)
    local pframe = frame:getParent()
    local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
    local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
    
    local DefaultImage = config["default-image"] or portal_images[1]
    local Break = args["break"]
    local Left = args.left
    local Margin = args.margin
    local BoxSize = args.boxsize
    
    if ( Break ) then Break = "<br/>" else Break = " " end
    if ( Margin == nil ) then 
        if ( Left ) then
            Margin = "0.5em 0.5em 0.5em 0"
        else
            Margin = "0.5em 0 0.5em 0.5em"
        end
    end
    if ( Left ) then Left = "tleft" else Left = "tright" end
    if ( BoxSize ) then BoxSize = " width:" .. BoxSize .. "px;" else BoxSize = "" end

    local text = {}
    table.insert(text, "{| style=\"background:#f9f9f9; font-size:85%; line-height:110%; max-width:175px;" .. BoxSize .. "\"\n")
    local index = 1
    while true do
        local arg = args[index]
        if ( nil == arg ) then break end
        local image = portal_images[arg] or DefaultImage
        local col1 = "| style=\"text-align: center;\" | [[File:" .. image .. "|32x28px|alt=Portal icon|link=]]\n"
        local col2 = "| style=\"padding: 0 0.2em; vertical-align: middle; font-style: italic; font-weight: bold\" | [[Portal:" .. arg .. "|" .. arg .. Break .. "portal" .. "]]\n"
        table.insert(text, "|- valign=middle\n")
        table.insert(text, col1)
        table.insert(text, col2)
        index = index + 1
    end
    table.insert(text, "|}\n")
    
    return sidebox(text, Margin, "noprint " .. Left .. " portal")
end

-- This is used by template {{portal bar}}.
function z.portalbar(frame)
    local pframe = frame:getParent()
    local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
    local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
    
    local DefaultImage = config["default-image"] or portal_images[1]
    
    local items = {}
    local index = 1
    while true do
        local arg = args[index]
        if ( nil == arg ) then break end
        local image = portal_images[arg] or DefaultImage
        local file = "[[File:" .. image .. "|32x28px|alt=Portal icon|link=]]"
        local filespan = mw.text.tag({name="span",contents=file,params={style="margin:auto 1.5em; margin-right:0.5em;"}})
        local port = "'''''[[Portal:" .. arg .. "|" .. arg .. "&nbsp;portal]]'''''"
        local portspan = mw.text.tag({name="span",contents=port,params={style="font-weight:bold;"}})
        local item = mw.text.tag({name="li",contents=filespan .. portspan,params={style="white-space:nowrap;"}})
        table.insert(items, item)
        index = index + 1
    end
    
    local list = mw.text.tag({name="ul",contents=table.concat(items),params={class="hlist"}})    
    return mw.text.tag({name="div",contents=list,params={class="noprint",style="background-color:#F9F9F9; border:1px solid #AAA; clear:both; margin-left:0px; margin-top:0.5em; padding:4px; text-align:center;"}})
end

return z