Modul:PageUtil
| Vorlagenprogrammierung | Diskussionen | Lua | Unterseiten | |||
| Modul | Deutsch | English
|
Modul: | Dokumentation | ||
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
Dies ist die (produktive) Mutterversion eines global benutzten Lua-Moduls.
Wenn die serial-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Wenn die serial-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Versionsbezeichnung auf WikiData:
2025-01-01local PageUtil = { suite = "PageUtil",
serial = "2025-01-01",
item = 89064539 }
--[=[
PageUtil
]=]
local Failsafe = PageUtil
PageUtil.maxPages = 200
local function fault( alert, frame )
-- Format message with class="error"
-- alert -- string, with message
-- frame -- object, if known
-- Returns message with markup
local scream = alert
if frame then
scream = string.format( "%s * %s", frame:getTitle(), scream )
end
return tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( scream ) )
end -- fault()
local function find( area, ask )
-- Check for local page existence without traces
-- area -- number, with namespace number >= 0
-- ask -- string, with title
-- Returns boolean
local r = false
if mw.title.makeTitle( area, ask ).protectionLevels.edit then
r = true
end
return r
end -- find()
local function flat( adjust, assembly )
-- Replace links to pages by inner links
-- adjust -- string, with text
-- assembly -- table, with page infos
-- Returns adjusted string
local r = adjust
local seek, shift, source, subst
for k, v in pairs( assembly ) do
source = v[ 1 ]
shift = v[ 2 ]
source = ":?" .. source:gsub( " ", "[_ ]+" )
:gsub( "[%.%(%)%*%?%+%-]", "%1" )
.. "%s*"
seek = "%[%[%s*" .. source .. "(#[^%]]*%]%])"
subst = "[[%1"
r = r:gsub( seek, subst )
seek = "%[%[%s*" .. source .. "(%|[^%]]*%]%])"
subst = "[[#" .. shift .. "%1"
r = r:gsub( seek, subst )
seek = "%[%[%s*(" .. source .. "%]%])"
subst = "[[#" .. shift .. "|%1"
r = r:gsub( seek, subst )
end -- for k, v
return r
end -- flat()
local function fraction( access, frame )
-- Retrieve text from section
-- access -- string, with request
-- frame -- object
-- Returns content, or false
-- Uses:
-- mw.title.new() .exists
local r
local seek = "^(#lstx?):%s*%[%[([^%[|%]\n]+)%]%]%s*(%S.*)%s*$"
local scope, source, section = access:match( seek )
if source then
local page = mw.title.new( source )
source = page.prefixedText
if page.exists then
section = mw.text.trim( section )
if section ~= "" then
r = frame:callParserFunction{ name = scope,
args = { source,
section } }
end
else
r = tostring( mw.html.create( "div" )
:addClass( "error" )
:wikitext( source ) )
end
end
return r
end -- fraction()
local function full( access, frame, alias, assembly )
-- Retrieve text from page
-- access -- string, with page name
-- frame -- object
-- alias -- number, unique
-- assembly -- table, with page infos
-- Returns string with content, or nil
-- Uses:
-- mw.title.new() .exists
local page = mw.title.new( access )
local r
if page then
if page.exists then
local source = page.prefixedText
local segment = string.format( "PageUtilMerge-%d", alias )
local seed
if page.namespace == 0 then
seed = ":" .. source
else
seed = source
end
r = string.format( "%s\n%s",
tostring( mw.html.create( "span" )
:attr( "id", segment ) ),
frame:expandTemplate( { title = seed } ) )
table.insert( assembly, { source, segment } )
else
r = tostring( mw.html.create( "div" )
:addClass( "error" )
:wikitext( page.prefixedText ) )
end
else
r = string.format( "%s '%s'", "Unknown page", access )
r = tostring( mw.html.create( "div" )
:addClass( "error" )
:wikitext( r ) )
end
return r
end -- full()
PageUtil.exists = function ( area, ask, apply, alert )
-- Check for existence
-- area -- number or string, with namespace specification
-- -- number >= 0 of local namespace
-- -- "media" -- files including commons
-- -- "msg" -- system messages
-- -- "data" -- commons:Data:*.tab
-- ask -- table, with list of titles
-- apply -- table or not, with 0, 1, 2 elements
-- -- [true]: category list on existence
-- -- [false]: category list on non-existence
-- -- category titles, multiple separated by \n
-- alert -- table or not, with 0, 1, 2 elements
-- -- [true]: return value on existence
-- -- [false]: return value on non-existence
-- -- if string then followed by apply categories
-- Returns string, with content, or other element of alert
local got, leg, r
if type( area ) == "number" and
area >= 0 and
math.floor( area ) == area then
for k, v in pairs( ask ) do
if type( v ) == "string" then
got = got or { }
leg = find( area, v )
got[ leg ] = got[ leg ] or { }
table.insert( got[ leg ], v )
end
end -- for k, v
elseif area == "media" then
for k, v in pairs( ask ) do
if type( v ) == "string" then
got = got or { }
leg = find( 6, v )
if not leg then
leg = mw.title.makeTitle( 6, v ).exists
end
got[ leg ] = got[ leg ] or { }
table.insert( got[ leg ], v )
end
end -- for k, v
elseif area == "msg" then
for k, v in pairs( ask ) do
if type( v ) == "string" then
got = got or { }
leg = mw.message.new( v ):exists()
got[ leg ] = got[ leg ] or { }
table.insert( got[ leg ], v )
end
end -- for k, v
elseif area == "data" then
local suffix = "tab"
local data, j, lucky
for k, v in pairs( ask ) do
if type( v ) == "string" then
got = got or { }
if not v:find( ".", 2, true ) then
j = -1 - #suffix
if v:sub( j ) ~= "." .. suffix then
v = string.format( "%s.%s", v, suffix )
end
end
lucky, data = pcall( mw.ext.data.get, v )
if lucky then
leg = true
else
leg = false
end
got[ leg ] = got[ leg ] or { }
table.insert( got[ leg ], v )
end
end -- for k, v
else
r = tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( "exists@PageUtil space error" ) )
end
if got then
local b = { false, true }
local bg, ea, sa, sr
for bk, bv in pairs( b ) do
bg = got[ bv ]
if bg then
sr = type( r )
ea = alert[ bv ]
if ea then
sa = type( ea )
if sr == "string" and
sa == "string" then
r = r .. ea
elseif sr == "nil" then
r = ea
sr = sa
end
if sr == "string" and
r:find( "@@@", 1, true ) then
local space
if type( area ) == "number" then
space = area
elseif area == "media" then
space = 6
elseif area == "msg" then
space = 8
elseif area == "data" then
space = "commons:Data"
end
if type( space ) == "number" then
sa = mw.site.namespaces[ space ].name
if space == 6 or space == 14 then
space = ":" .. sa
else
space = sa
end
end
sa = ""
for k, v in pairs( bg ) do
sa = string.format( "%s [[%s:%s]]",
sa, space, v )
end -- for k, v
r = r:gsub( "@@@", sa )
end
end
ea = apply[ bv ]
if ea then
if sr == "nil" then
r = ""
sr = "string"
end
if sr == "string" then
sa = type( ea )
if sa == "string" then
r = string.format( "%s[[Category:%s]]",
r, sa )
elseif sa == "table" then
for k, v in pairs( ea ) do
r = string.format( "%s[[Category:%s]]",
r, v )
end -- for k, v
end
end
end
end
end -- for bk, bv
end
return r
end -- PageUtil.exists()
PageUtil.getProtection = function ( access, action )
-- Retrieve protection
-- access -- string or title or nil, with page, default: current
-- action -- string or nil, with action, default: edit
-- Returns number: One of: 0, 0.5, 0.75, 1
local t = type( access )
local r = 0
local p
if t == "string" then
t = mw.title.new( access )
elseif t == "table" then
t = access
else
t = mw.title.getCurrentTitle()
end
p = t.protectionLevels
if type( p ) == "table" then
local s
if type( action ) == "string" then
s = mw.text.trim( action )
if s == "" then
s = false
end
end
p = p[ s or "edit" ]
if type( p ) == "table" then
for k, v in pairs( p ) do
if v == "autoconfirmed" then
r = 0.5
elseif v == "editeditorprotected" then
r = 0.75
elseif v == "sysop" then
r = 1
end
end -- for k, v
end
end
return r
end -- PageUtil.getProtection()
PageUtil.merge = function ( args, frame )
-- Retrieve text
-- args -- table, with request
-- frame -- object, if available
-- Returns string, with content
local max = 0
local r = ""
for k, v in pairs( args ) do
if type( k ) == "number" and
k > max then
max = k
end
end -- for k, v
if max > 0 then
local n = 0
local pages = { { mw.title.getCurrentTitle().prefixedText,
"" } }
local mode, s, section, swallow
if not frame then
frame = mw.getCurrentFrame()
end
for i = 1, max do
s = args[ i ]
if s then
swallow = s:match( "^%s*(#lstx?:[^\n]*%S)%s*$" )
if swallow then
s = fraction( swallow, frame )
n = n + 1
else
swallow = s:match( "^%s*%[%[([^%[|%]\n]+)%]%]%s*$" )
if swallow then
s = full( swallow, frame, i, pages )
n = n + 1
end
end
if s then
r = r .. mw.text.trim( s )
end
if n > PageUtil.maxPages then
s = string.format( "'''Too many pages (max. %d)'''",
PageUtil.maxPages )
r = string.format( "%s\n\n%s",
r,
fault( s, frame ) )
break -- for i
end
end
end -- for i
r = flat( r, pages )
end
return r
end -- .merge()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2024-03-01
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )
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
elseif linked then
if mw.title.getCurrentTitle().prefixedText
== mw.wikibase.getSitelink( suited ) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
elseif link then
r = false
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.exists = function ( frame )
local pars = frame:getParent().args
local ns, r
if not pars.ns then
elseif pars.ns:find( "^%d+$" ) then
ns = tonumber( pars.ns )
elseif pars.ns:find( "^%a+$" ) then
ns = pars.ns:lower()
end
if ns then
local coll, t
for k, v in pairs( pars ) do
t = type( k )
if t == "string" then
if t:match( "^%d+$" ) then
k = tonumber( k )
else
k = false
end
end
if k then
v = mw.text.trim( v )
if v ~= "" then
coll = coll or { }
table.insert( coll, v )
end
end
end -- for k, v
if coll then
local loss = ( pars.loss == "1" )
local cat, err
if pars.cat then
t = mw.text.split( pars.cat, "%s*\n%s*" )
if #t > 0 then
cat = { [ loss ] = t }
end
end
if pars.err and pars.err ~= "" then
err = { [ loss ] = pars.err }
end
r = PageUtil.exists( ns, coll, cat, err )
end
end
return r or ""
end -- p.exists
p.getCategories = function ( frame )
local r = ""
local s = frame.args[ 1 ]
local c, t
if s then
s = mw.text.trim( s )
if s == "" then
s = false
end
end
if s then
t = mw.title.new( s )
else
t = mw.title.getCurrentTitle()
end
c = t.categories
if c then
local n = #c
if n > 0 then
for i = 1, n do
if r ~= "" then
r = r .. "|"
end
r = r .. c[ i ]
end -- for i
end
end
return r
end -- p.getCategories
p.getContentModel = function ( frame )
local s = frame.args[ 1 ]
local t
if s then
s = mw.text.trim( s )
if s == "" then
s = false
end
end
if s then
t = mw.title.new( s )
else
t = mw.title.getCurrentTitle()
end
return t.contentModel
end -- p.getContentModel
p.getProtection = function ( frame )
local n = PageUtil.getProtection( frame.args[ 1 ], frame.args[ 2 ] )
local t = { [ 0 ] = "",
[ 0.5 ] = mw.ustring.char( 189 ),
[ 0.75 ] = mw.ustring.char( 190 ),
[ 1 ] = "1" }
return t[ n ]
end -- p.getProtection
p.isRedirect = function ()
return mw.title.getCurrentTitle().isRedirect and "1" or ""
end -- p.isRedirect
p.merge = function ( frame )
local lucky, r = pcall( PageUtil.merge, frame.args, frame )
if not lucky then
r = fault( r, frame )
end
return r
end -- p.merge
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()
function p.PageUtil()
return PageUtil
end
setmetatable( p, { __call = function ( func, ... )
setmetatable( p, nil )
return Failsafe
end } )
return p
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.