Modul:Vorlage:Anker
Zur Navigation springen
Zur Suche springen
Die Dokumentation für dieses Modul kann unter Modul:Vorlage:Anker/Doku erstellt werden
local Anchor = { suite = "AnchorTemplate",
serial = "2019-12-24",
item = 79414611
}
--[=[
Template:Anchor {{Anker}}
]=]
local Failsafe = Anchor
local Config = {
badPattern = "[%%#'\"%[%]<>]",
globalPage = { "bodyContent",
"catlinks",
"centralNotice",
"content",
"contentSub",
"editform",
"editpage-copywarn",
"firstHeading",
"footer",
"fundraising",
"jump-to-nav",
"page-actions",
"siteNotice",
"siteSub",
"toc",
"top" },
globalPatterns = { "^mw%-[%l%-]+$",
"^ca%-[%l%-]+$",
"^n%-[%l%-]+$",
"^pt?%-[%l%-]+$",
"^wp%u" },
errCat = false,
errClass = "error_fragment",
errHide = true,
errNS = false,
errInvalid = { en = "Invalid:",
de = "Ungültig:" },
errModule = { en = "Library module missing:",
de = "Bibliotheksmodul fehlt:" },
errNoFragments = { en = "No fragments given",
de = "Keine Bezeichner angegeben" },
errUnkown = { en = "Unkown parameter:",
de = "Parameter unbekannt:" }
}
local function factory( apply )
-- Localization of messages
-- apply -- string, with message key
-- Returns message text; at least English
local entry = Config[ apply ]
local r
if entry then
-- TODO: page language
r = entry[ mw.language.getContentLanguage():getCode() ]
if not r then
r = entry.en
end
else
r = tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( string.format( "????.%s.????",
apply ) ) )
end
return r
end -- factory()
local function faculty( adjust )
-- Test template arg for boolean
-- adjust -- string or nil
-- Returns boolean
local r = false
if adjust then
r = mw.text.trim( adjust )
if r ~= "" and r ~= "0" then
r = true
end
end
return r
end -- faculty()
local function fair( assembly )
-- Create HTML code for anchors
-- assembly -- sequence table, with identtifiers
-- Returns HTML string
local collection = mw.html.create( "" )
local f = function ( a )
collection:node( mw.html.create( "span" )
:attr( "id", a ) )
end
local s, seen, shift
table.sort( assembly )
for i = 1, #assembly do
s = assembly[ i ]
if s ~= seen then
if not s:match( "^[%w_]+$" ) then
shift = mw.uri.encode( s, "WIKI" )
if shift ~= s then
f( shift:gsub( "%%", "." ) )
end
end
f( s )
seen = s
end
end -- i = 1, #assembly
return tostring( collection )
end -- fair()
local function fault( alert, about )
-- Format message with class="error" or similar
-- alert -- string, with message key
-- about -- string, with explanation
-- Returns message with markup
local scope = Config.errClass
local story = factory( alert )
local lucky, TemplUtl = pcall( require, "Module:TemplUtl" )
local r, scope, style
if type( TemplUtl ) == "table" then
TemplUtl = TemplUtl.TemplUtl()
end
if Config.self then
story = string.format( "%s * %s", Config.self, story )
end
if Config.errClasses then
if scope then
scope = string.format( "%s %s",
scope, Config.errClasses )
else
scope = Config.errClasses
end
end
if about then
story = string.format( "%s %s", story, about )
end
if type( TemplUtl ) == "table" then
r = TemplUtl.failure( story,
not Config.errHide,
scope,
Config.frame )
else
r = tostring( mw.html.create( "span" )
:addClass( scope )
:addClass( "error" )
:wikitext( story ) )
end
if Config.errCat then
if Config.errNS then
local st = type( Config.errNS )
if st == "number" then
st = { }
table.insert( st, Config.errNS )
Config.errNS = st
elseif st == "string" then
Config.errNS = mw.text.split( Config.errNS, "%s+" )
for i = 1, #Config.errNS do
Config.errNS[ i ] = tonumber( Config.errNS[ i ] )
end -- for i
end
if type( Config.errNS ) == "table" then
local ns = mw.title.getCurrentTitle().namespace
for i = 1, #Config.errNS do
if Config.errNS[ i ] == ns then
Config.errNS = false
break -- for i
end
end -- for i
end
end
if not Config.errNS then
r = string.format( "%s[[Category:%s]]", r, Config.errCat )
end
end
return r
end -- fault()
local function main( argsF, argsT )
-- Invocation
-- argsF -- table, with #invoke parameters, or false
-- argsT -- table, with template parameters
-- Returns appropriate string
local r
if argsF then
Config.errCat = argsF.errCat
Config.errClasses = argsF.errClasses
Config.errHide = faculty( argsF.errHide )
Config.errNS = argsF.errNS
if mw.site.server:find( "de.wikipedia.org", 1, true ) then
Config.errClasses = "Linkwartung"
Config.errHide = true
Config.errNS = 0
end
end
if type( argsT ) == "table" then
local checked = { }
local tocheck = { }
local further = function ( add )
local s = mw.text.unstripNoWiki( add )
s = s:gsub( " +", "_" )
:gsub( "_+", "_" )
table.insert( checked, s )
end
local s, unknown
for k, v in pairs( argsT ) do
s = type( k )
if s == "number" then
v = mw.text.trim( v )
if v ~= "" then
table.insert( tocheck, v )
end
k = false
elseif s == "string" then
if k:match( "^x[1-9]%d*" ) then
further( v )
k = false
end
end
if k then
if not unknown then
unknown = { }
end
table.insert( unknown, k )
end
end -- for k, v
if unknown then
local e = mw.html.create( "code" )
:css( "white-space", "nowrap" )
:wikitext( table.concat( unknown, " " ) )
s = string.format( " in [[%s]]",
Config.frame:getTitle() )
e:tag( "span" )
:wikitext( s )
r = fault( "errUnkown", tostring( e ) )
else
local bad, e
local flop = function ( a, alter )
if not bad then
bad = { }
end
e = mw.html.create( "code" )
:wikitext( a )
if alter then
e:css( "white-space", "nowrap" )
end
table.insert( bad, tostring( e ) )
end
local legal, s
for i = 1, #tocheck do
s = tocheck[ i ]
if s:match( "^%d" ) or
s:match( Config.badPattern ) or
s:match( "&#%a+;" ) then
legal = false
else
legal = true
for k = 1, #Config.globalPatterns do
if s:match( Config.globalPatterns[ k ] ) then
legal = false
break -- k = 1, #Config.globalPatterns
end
end -- k = 1, #Config.globalPatterns
end
if not legal then
flop( mw.text.encode( s ), true )
else
further( s )
end
end -- i = 1, #tocheck
for i = 1, #checked do
s = checked[ i ]
for k = 1, #Config.globalPage do
if s == Config.globalPage[ k ] then
flop( s )
break -- k = 1, #Config.globalPage
end
end -- k = 1, #Config.globalPage
end -- i = 1, #checked
if bad then
s = string.format( "%s in [[%s]]",
table.concat( bad, ", " ),
Config.frame:getParent():getTitle() )
r = fault( "errInvalid", s )
elseif #checked == 0 then
r = fault( "errNoFragments" )
else
r = fair( checked )
end
end
end
return r or ""
end -- main()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version or "wikidata" or "~"
-- or false
-- Postcondition:
-- Returns string -- with queried version, also if problem
-- false -- if appropriate
-- 2019-10-15
local last = ( atleast == "~" )
local since = atleast
local r
if last or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local entity = mw.wikibase.getEntity( string.format( "Q%d",
item ) )
if type( entity ) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues( seek )
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
else
r = vsn.value
end
end
end
end
end
if type( r ) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
-- Export
local p = { }
p.f = function ( frame )
local lucky, r
Config.frame = frame
lucky, r = pcall( main, frame.args, frame:getParent().args )
if not lucky then
r = tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( string.format( "%s * %s",
frame:getTitle(),
r ) ) )
end
return r
end -- p.f()
p.flops = function ( frame )
local r = ""
local sep = ""
local e
for k = 1, #Config.globalPage do
e = mw.html.create( "code" )
:css( "white-space", "nowrap" )
:wikitext( Config.globalPage[ k ] )
r = string.format( "%s%s%s", r, sep, tostring( e ) )
sep = ", "
end -- k = 1, #Config.globalPage
return r
end -- p.flops()
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe()
return p