Modul:Vorlage:Anker: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
(2019-12-26) |
(2019-12-27) |
||
Zeile 1: | Zeile 1: | ||
local Anchor = { suite = "AnchorTemplate", | local Anchor = { suite = "AnchorTemplate", | ||
serial = "2019-12- | serial = "2019-12-27", | ||
item = 79414611, | item = 79414611, | ||
globals = { TemplUtl = 52364930 } | globals = { TemplUtl = 52364930 } | ||
Zeile 282: | Zeile 282: | ||
k = false | k = false | ||
elseif s == "string" then | elseif s == "string" then | ||
if k:match( "^x[1-9]%d*" ) then | if k:match( "^[x%-][1-9]%d*" ) then | ||
further( v ) | further( v ) | ||
k = false | k = false |
Version vom 27. Dezember 2019, 16:14 Uhr
Die Dokumentation für dieses Modul kann unter Modul:Vorlage:Anker/Doku erstellt werden
local Anchor = { suite = "AnchorTemplate",
serial = "2019-12-27",
item = 79414611,
globals = { TemplUtl = 52364930 }
}
--[=[
Template:Anchor {{Anker}}
]=]
local Failsafe = Anchor
local GlobalMod = 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 foreignModule = function ( access, advanced, append, alt, alert )
-- Fetch global module
-- Precondition:
-- access -- string, with name of base module
-- advanced -- true, for require(); else mw.loadData()
-- append -- string, with subpage part, if any; or false
-- alt -- number, of wikidata item of root; or false
-- alert -- true, for throwing error on data problem
-- Postcondition:
-- Returns whatever, probably table
-- 2019-10-29
local storage = access
local finer = function ()
if append then
storage = string.format( "%s/%s",
storage,
append )
end
end
local fun, lucky, r, suited
if advanced then
fun = require
else
fun = mw.loadData
end
GlobalMod.globalModules = GlobalMod.globalModules or { }
suited = GlobalMod.globalModules[ access ]
if not suited then
finer()
lucky, r = pcall( fun, "Module:" .. storage )
end
if not lucky then
if not suited and
type( alt ) == "number" and
alt > 0 then
suited = string.format( "Q%d", alt )
suited = mw.wikibase.getSitelink( suited )
GlobalMod.globalModules[ access ] = suited or true
end
if type( suited ) == "string" then
storage = suited
finer()
lucky, r = pcall( fun, storage )
end
if not lucky and alert then
error( "Missing or invalid page: " .. storage, 0 )
end
end
return r
end -- foreignModule()
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 TemplUtl = foreignModule( "TemplUtl",
true,
false,
Anchor.globals.TemplUtl )
local r, scope, style
if type( TemplUtl ) == "table" and
type( TemplUtl.TemplUtl ) == "function" then
TemplUtl = TemplUtl.TemplUtl()
else
TemplUtl = false
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 TemplUtl 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 = add: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 = mw.text.unstripNoWiki( tocheck[ i ] )
if s:match( "^%d" ) or
s:sub( 1, 1 ) == "-" or
s:match( Config.badPattern ) or
s:match( "&#%w+;" ) 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