Importer, Bürokraten, Moderatoren (CommentStreams), Strukturierte-Diskussionen-Bots, Oberflächenadministratoren, Push-Abonnementverwalter, Oversighter, Administratoren, Kampagnenbearbeiter (Hochladeassistent)
855
Bearbeitungen
K (24 Versionen von w:Modul:PageTree importiert) |
K (27 Versionen von wikivoyage:Modul:PageTree importiert) |
||
| (2 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
--[=[ | local PageTree = { suite = "PageTree", | ||
Module: | serial = "2018-09-13", | ||
item = 56033297, | |||
maxSub = 10, | |||
strings = { "segment", | |||
"self", | |||
"stamped", | |||
"subpager", | |||
"suppress" }, | |||
toggles = { "lazy", | |||
"level", | |||
"lineup", | |||
"light", | |||
"linked", | |||
"limit", | |||
"list" } } | |||
--[=[ | |||
Module:PageTree | |||
Rendering and administration of hierarchical wiki page structures | |||
]=] | ]=] | ||
| Zeile 39: | Zeile 47: | ||
local lucky, r | local lucky, r | ||
if s:byte( 1, 1 ) == 47 then -- "/" | if s:byte( 1, 1 ) == 47 then -- "/" | ||
if | if PageTree.suite then | ||
s = | s = PageTree.suite .. s | ||
end | end | ||
end | end | ||
| Zeile 49: | Zeile 57: | ||
return r | return r | ||
end -- facility() | end -- facility() | ||
local function factory( apply ) | |||
-- Clone read-only table | |||
-- apply -- table, with basic data elements, read-only | |||
-- Returns message with markup | |||
local r = { } | |||
for k, v in pairs( apply ) do | |||
r[ k ] = v | |||
end -- for k, v | |||
return r | |||
end -- factory() | |||
| Zeile 57: | Zeile 78: | ||
-- Returns true if to be hidden | -- Returns true if to be hidden | ||
local r = false | local r = false | ||
for k, v in pairs( | for k, v in pairs( PageTree.hide ) do | ||
if ask:match( v ) then | if ask:match( v ) then | ||
r = true | r = true | ||
| Zeile 65: | Zeile 86: | ||
return r | return r | ||
end -- fade() | end -- fade() | ||
| Zeile 87: | Zeile 95: | ||
local r, s, title | local r, s, title | ||
local n = 0 | local n = 0 | ||
for k, v in pairs( | for k, v in pairs( PageTree.pages ) do | ||
n = n + 1 | n = n + 1 | ||
s = v.seed | s = v.seed | ||
| Zeile 100: | Zeile 108: | ||
"(-)" .. s ) | "(-)" .. s ) | ||
end | end | ||
elseif | elseif PageTree.linked and | ||
title.isRedirect then | title.isRedirect then | ||
table.insert( redirect, | table.insert( redirect, | ||
| Zeile 139: | Zeile 147: | ||
local r | local r | ||
if adopt:byte( 1, 1 ) == 47 then -- "/" | if adopt:byte( 1, 1 ) == 47 then -- "/" | ||
r = | r = PageTree.start .. adopt:sub( 2 ) | ||
else | else | ||
r = adopt | r = adopt | ||
| Zeile 217: | Zeile 225: | ||
-- Find parent page | -- Find parent page | ||
-- ancestor -- string, with page name | -- ancestor -- string, with page name | ||
-- Returns page name of parent, or | -- Returns page name of parent, or PageTree.series | ||
local r = ancestor:match( "^(.+)/[^/]+$" ) | local r = ancestor:match( "^(.+)/[^/]+$" ) | ||
if not r then | if not r then | ||
r = ancestor:match( "^([^:]+:).+$" ) | r = ancestor:match( "^([^:]+:).+$" ) | ||
if not r then | if not r then | ||
r = | r = PageTree.series | ||
end | end | ||
end | end | ||
| Zeile 240: | Zeile 248: | ||
local function features( apply, access ) | local function features( apply, access ) | ||
-- Fill | -- Fill PageTree.pages with elements | ||
-- apply -- table, with definitions, read-only | -- apply -- table, with definitions, read-only | ||
-- access -- string, with relative path of module | -- access -- string, with relative path of module | ||
| Zeile 258: | Zeile 266: | ||
if type( v.seed ) == "string" then | if type( v.seed ) == "string" then | ||
s = v.seed | s = v.seed | ||
e = | e = factory( v ) | ||
end | end | ||
end | end | ||
| Zeile 264: | Zeile 272: | ||
if type( v ) == "table" then | if type( v ) == "table" then | ||
s = k | s = k | ||
e = | e = factory( v ) | ||
end | end | ||
elseif k == true then -- root | elseif k == true then -- root | ||
if | if PageTree.pages[ true ] then | ||
bad[ "true" ] = "duplicated" | bad[ "true" ] = "duplicated" | ||
elseif type( v ) == "table" then | elseif type( v ) == "table" then | ||
if type( v.seed ) == "string" then | if type( v.seed ) == "string" then | ||
PageTree.pages[ true ] = factory( v ) | |||
PageTree.pages[ true ].children = { } | |||
else | else | ||
bad[ "true" ] = "seed missing" | bad[ "true" ] = "seed missing" | ||
| Zeile 288: | Zeile 296: | ||
end | end | ||
if s then | if s then | ||
if not | if not PageTree.pages[ s ] then | ||
e.seed = s | e.seed = s | ||
if e.super then | if e.super then | ||
| Zeile 298: | Zeile 306: | ||
end | end | ||
e.children = { } | e.children = { } | ||
PageTree.pages[ s ] = e | |||
end | end | ||
end | end | ||
| Zeile 322: | Zeile 330: | ||
local function feed( access ) | local function feed( access ) | ||
-- Fill | -- Fill PageTree with data, if not yet set | ||
-- access -- string, with relative path of module | -- access -- string, with relative path of module | ||
-- Returns error message, if failed, or false, if fine | -- Returns error message, if failed, or false, if fine | ||
| Zeile 329: | Zeile 337: | ||
local s | local s | ||
if type( r.maxSub ) == "number" then | if type( r.maxSub ) == "number" then | ||
PageTree.maxSub = r.maxSub | |||
end | end | ||
if type( r.stamp ) == "string" then | if type( r.stamp ) == "string" then | ||
if | if PageTree.stamp then | ||
if | if PageTree.stamp < r.stamp then | ||
PageTree.stamp = r.stamp | |||
end | end | ||
else | else | ||
PageTree.stamp = r.stamp | |||
end | end | ||
end | end | ||
| Zeile 343: | Zeile 351: | ||
s = mw.text.trim( r.start ) | s = mw.text.trim( r.start ) | ||
if s ~= "" then | if s ~= "" then | ||
PageTree.start = s | |||
end | end | ||
end | end | ||
if not | if not PageTree.pages then | ||
PageTree.pages = { } | |||
end | end | ||
if type( r.pages ) == "table" then | if type( r.pages ) == "table" then | ||
if not | if not PageTree.pages then | ||
PageTree.pages = { } | |||
end | end | ||
s = features( r.pages, access ) | s = features( r.pages, access ) | ||
| Zeile 394: | Zeile 402: | ||
r = string.format( "%s %s", r, about.suffix ) | r = string.format( "%s %s", r, about.suffix ) | ||
end | end | ||
if | if PageTree.linked and type( about.shift ) == "string" then | ||
r = string.format( "%s <small>→[[%s]]</small>", | r = string.format( "%s <small>→[[%s]]</small>", | ||
r, fair( about.shift ) ) | r, fair( about.shift ) ) | ||
end | end | ||
if | if PageTree.limit and type( about.protection ) == "string" then | ||
r = string.format( "%s %s", | r = string.format( "%s %s", | ||
r, fasten( about.protection ) ) | r, fasten( about.protection ) ) | ||
| Zeile 411: | Zeile 419: | ||
-- adjust -- string, to be standardized | -- adjust -- string, to be standardized | ||
-- Returns string with key | -- Returns string with key | ||
if not Sort then | if not PageTree.Sort then | ||
r, Sort = pcall( require, "Module:Sort" ) | r, PageTree.Sort = pcall( require, "Module:Sort" ) | ||
if type( Sort ) == "table" then | if type( PageTree.Sort ) == "table" then | ||
Sort = Sort.Sort() | PageTree.Sort = PageTree.Sort.Sort() | ||
else | else | ||
error( "Module:Sort not ready" ) | error( "Module:Sort not ready" ) | ||
end | end | ||
end | end | ||
return string.upper( Sort.lex( adjust, "latin", false ) ) | return string.upper( PageTree.Sort.lex( adjust, "latin", false ) ) | ||
end -- filter() | end -- filter() | ||
| Zeile 466: | Zeile 474: | ||
-- a2 -- string, with page name | -- a2 -- string, with page name | ||
-- Returns true if a1 < a2 | -- Returns true if a1 < a2 | ||
local e1 = | local e1 = PageTree.pages[ a1 ] | ||
local e2 = | local e2 = PageTree.pages[ a2 ] | ||
local r | local r | ||
if e1.index then | if e1.index then | ||
| Zeile 489: | Zeile 497: | ||
-- ahead -- string, with syntax in case of .lazy | -- ahead -- string, with syntax in case of .lazy | ||
local r | local r | ||
if | if PageTree.lazy then | ||
r = ":" | r = ":" | ||
else | else | ||
| Zeile 515: | Zeile 523: | ||
table.sort( above.children, firstly ) | table.sort( above.children, firstly ) | ||
for i = 1, n do | for i = 1, n do | ||
e = | e = PageTree.pages[ above.children[ i ] ] | ||
if e.list == false then | if e.list == false then | ||
let = | let = PageTree.list | ||
elseif | elseif PageTree.hide then | ||
let = not fade( e.seed ) | let = not fade( e.seed ) | ||
else | else | ||
| Zeile 524: | Zeile 532: | ||
end | end | ||
if let then | if let then | ||
local s | |||
if not e.less then | if not e.less then | ||
PageTree.item = PageTree.item + 1 | |||
serial | serial = string.format( "%s_%d", | ||
PageTree.serial, | |||
PageTree.item ) | |||
r = string.format( "%s\n<div %s %s %s>", | if table.maxn( e.children ) > 0 then | ||
s = "mw-collapsible" | |||
if amount >= already then | |||
s = s .. " mw-collapsed" | |||
end | |||
r = string.format( "%s\n<div class='%s' %s %s>", | |||
r, | |||
s, | |||
"data-expandtext='[+]'", | |||
"data-collapsetext='[-]'" ) | |||
s = "</div>" | |||
else | |||
s = "" | |||
end | |||
end | end | ||
r = string.format( "%s\n%s%s", | r = string.format( "%s\n%s%s", | ||
r, | r, | ||
string.rep( ahead, amount ), | |||
field( e, false ) ) | |||
if not e.less then | if not e.less then | ||
r = string.format( "%s\n<div %s>\n%s\n%s", | local style | ||
if amount >= already then | |||
style = " style='display:none'" | |||
else | |||
style = "" | |||
end | |||
r = string.format( "%s\n<div %s%s>\n%s\n</div>%s", | |||
r, | r, | ||
-- span, | -- span, | ||
"class='mw-collapsible-content'", | "class='mw-collapsible-content'", | ||
flip( ahead, | style, | ||
flip( already, | |||
ahead, | |||
amount + 1, | amount + 1, | ||
e | e ), | ||
s ) | |||
end | end | ||
end | end | ||
| Zeile 560: | Zeile 587: | ||
-- acquire -- string, with page name | -- acquire -- string, with page name | ||
if type( acquire ) == "string" then | if type( acquire ) == "string" then | ||
local e = | local e = PageTree.pages[ acquire ] | ||
local s = false | local s = false | ||
if e then | if e then | ||
| Zeile 574: | Zeile 601: | ||
e = { children = { }, | e = { children = { }, | ||
seed = acquire } | seed = acquire } | ||
PageTree.pages[ acquire ] = e | |||
end | end | ||
e.super = s | e.super = s | ||
| Zeile 593: | Zeile 620: | ||
local let = true | local let = true | ||
local e | local e | ||
for k, v in pairs( | for k, v in pairs( PageTree.pages ) do | ||
if v.super == nil then | if v.super == nil then | ||
flow( k ) | flow( k ) | ||
elseif not | elseif not PageTree.pages[ v.super ] then | ||
flow( v.super ) | flow( v.super ) | ||
end | end | ||
end -- for k, v | end -- for k, v | ||
for k, v in pairs( | for k, v in pairs( PageTree.pages ) do | ||
if | if PageTree.level then | ||
let = ( not v.seed:find( "/" ) ) | let = ( not v.seed:find( "/" ) ) | ||
end | end | ||
if let and v.super then | if let and v.super then | ||
e = | e = PageTree.pages[ v.super ] | ||
if e then | if e then | ||
table.insert( e.children, k ) | table.insert( e.children, k ) | ||
| Zeile 630: | Zeile 657: | ||
table.sort( above.children, firstly ) | table.sort( above.children, firstly ) | ||
for i = 1, n do | for i = 1, n do | ||
e = | e = PageTree.pages[ above.children[ i ] ] | ||
lift = ( all or above.long ) | lift = ( all or above.long ) | ||
if e.list == false then | if e.list == false then | ||
let = | let = PageTree.list | ||
elseif | elseif PageTree.hide then | ||
let = not fade( e.seed ) | let = not fade( e.seed ) | ||
else | else | ||
| Zeile 658: | Zeile 685: | ||
local n = 0 | local n = 0 | ||
local r, let | local r, let | ||
for k, v in pairs( | for k, v in pairs( PageTree.pages ) do | ||
let = true | let = true | ||
if v.list == false and | if v.list == false and | ||
( not | ( not PageTree.list or v.loose or k == true ) then | ||
let = false | let = false | ||
elseif | elseif PageTree.level and v.seed:find( "/" ) then | ||
let = false | let = false | ||
elseif | elseif PageTree.hide then | ||
let = not fade( v.seed ) | let = not fade( v.seed ) | ||
end | end | ||
| Zeile 672: | Zeile 699: | ||
v.show = nil | v.show = nil | ||
end | end | ||
if | if PageTree.light then | ||
local j, k = v.seed:find( | local j, k = v.seed:find( PageTree.start ) | ||
if j == 1 then | if j == 1 then | ||
v.show = v.seed:sub( k + 1 ) | v.show = v.seed:sub( k + 1 ) | ||
| Zeile 684: | Zeile 711: | ||
if n > 0 then | if n > 0 then | ||
local start | local start | ||
local long = ( not | local long = ( not PageTree.light ) | ||
if | if PageTree.lineup then | ||
start = " * " | start = " * " | ||
else | else | ||
| Zeile 717: | Zeile 744: | ||
r = true | r = true | ||
end | end | ||
r = | r = PageTree.pages[ r ] | ||
if r then | if r then | ||
if type( | if type( PageTree.init ) == "number" then | ||
init = | init = PageTree.init | ||
if | if PageTree.init < 1 then | ||
init = 1 | init = 1 | ||
end | end | ||
| Zeile 727: | Zeile 754: | ||
init = 1 | init = 1 | ||
end | end | ||
if type( | if type( PageTree.serial ) ~= "string" | ||
or | or PageTree.serial == "" then | ||
PageTree.serial = "pageTree" | |||
end | end | ||
PageTree.item = 0 | |||
r = flip( init, flag( " | r = flip( init, flag( "*" ), 1, r ) | ||
else | else | ||
r = false | r = false | ||
| Zeile 745: | Zeile 772: | ||
-- ancestor -- string, with name of root element, or false | -- ancestor -- string, with name of root element, or false | ||
-- Returns string with story | -- Returns string with story | ||
local sup = | local sup = PageTree.self | ||
local higher, i, r | local higher, i, r | ||
if ancestor then | if ancestor then | ||
higher = | higher = PageTree.pages[ ancestor ] | ||
if type( higher ) == "table" then | if type( higher ) == "table" then | ||
higher.super = false | higher.super = false | ||
end | end | ||
else | else | ||
local point = | local point = PageTree.pages[ sup ] | ||
if not point then | if not point then | ||
sup = true | sup = true | ||
elseif point.list == false then | elseif point.list == false then | ||
higher = | higher = PageTree.pages[ sup ] | ||
if type( higher ) == "table" then | if type( higher ) == "table" then | ||
if not higher.loose then | if not higher.loose then | ||
| Zeile 767: | Zeile 794: | ||
end | end | ||
end | end | ||
for i = | for i = PageTree.maxSub, 0, -1 do | ||
higher = | higher = PageTree.pages[ sup ] | ||
if type( higher ) == "table" then | if type( higher ) == "table" then | ||
higher.long = true | higher.long = true | ||
| Zeile 798: | Zeile 825: | ||
local n = 1 | local n = 1 | ||
local reverse = { } | local reverse = { } | ||
local sup = | local sup = PageTree.self | ||
local r | local r | ||
if type( sup ) == "string" and not sup:find( "/", 1, true ) then | if type( sup ) == "string" and not sup:find( "/", 1, true ) then | ||
flow( sup ) | flow( sup ) | ||
repeat | repeat | ||
higher = | higher = PageTree.pages[ sup ] | ||
if type( higher ) == "table" then | if type( higher ) == "table" then | ||
sup = higher.super | sup = higher.super | ||
| Zeile 812: | Zeile 839: | ||
elseif sup then | elseif sup then | ||
n = n + 1 | n = n + 1 | ||
if n > | if n > PageTree.maxSub then | ||
reverse[ n ] = { seed = "???????" } | reverse[ n ] = { seed = "???????" } | ||
break -- repeat | break -- repeat | ||
| Zeile 867: | Zeile 894: | ||
r = true | r = true | ||
end | end | ||
r = | r = PageTree.pages[ r ] | ||
if r then | if r then | ||
r = follow( flag( "#" ), 1, r, true ) | r = follow( flag( "#" ), 1, r, true ) | ||
| Zeile 886: | Zeile 913: | ||
type( args.service ) == "string" and | type( args.service ) == "string" and | ||
type( args.suite ) == "string" then | type( args.suite ) == "string" then | ||
PageTree.series = args.series | |||
PageTree.service = args.service | |||
PageTree.suite = args.suite | |||
if type( args.hide ) == "table" then | if type( args.hide ) == "table" then | ||
PageTree.hide = args.hide | |||
elseif type( args.suppress ) == "string" then | elseif type( args.suppress ) == "string" then | ||
PageTree.hide = { } | |||
table.insert( | table.insert( PageTree.hide, args.suppress ) | ||
end | end | ||
if | if PageTree.series:match( "[:/]$" ) then | ||
PageTree.start = args.series | |||
else | else | ||
PageTree.start = args.series .. "/" | |||
end | end | ||
r = feed( "/" .. | r = feed( "/" .. PageTree.series ) | ||
if r then | if r then | ||
r = fault( r ) | r = fault( r ) | ||
else | else | ||
local life = true | local life = true | ||
if | if PageTree.service == "path" or | ||
PageTree.service == "subpages" then | |||
if args.self then | if args.self then | ||
PageTree.self = args.self | |||
else | else | ||
PageTree.page = mw.title.getCurrentTitle() | |||
PageTree.self = PageTree.page.prefixedText | |||
end | end | ||
if not | if not PageTree.pages[ PageTree.self ] then | ||
if type( | if type( PageTree.pages[ true ] ) == "table" then | ||
PageTree.self = true | |||
else | else | ||
life = false | life = false | ||
| Zeile 922: | Zeile 949: | ||
end | end | ||
if life then | if life then | ||
if | if PageTree.service == "subpages" then | ||
r = formatSub( args.subpager, args.frame ) | r = formatSub( args.subpager, args.frame ) | ||
elseif | elseif PageTree.service == "check" then | ||
PageTree.linked = args.linked | |||
r = failures() | r = failures() | ||
else | else | ||
for k, v in pairs( | for k, v in pairs( PageTree.toggles ) do | ||
PageTree[ v ] = args[ v ] | |||
end -- for k, v | end -- for k, v | ||
if | if PageTree.service == "all" then | ||
r = formatAll() | r = formatAll() | ||
else | else | ||
| Zeile 937: | Zeile 964: | ||
if type( args.segment ) == "string" then | if type( args.segment ) == "string" then | ||
segment = fair( args.segment ) | segment = fair( args.segment ) | ||
if not | if not PageTree.pages[ segment ] then | ||
PageTree.pages[ segment ] = | |||
{ seed = segment, | { seed = segment, | ||
children = { }, | children = { }, | ||
| Zeile 946: | Zeile 973: | ||
end | end | ||
fluent() | fluent() | ||
if | if PageTree.service == "path" then | ||
r = formatPath( segment ) | r = formatPath( segment ) | ||
elseif | elseif PageTree.service == "expand" then | ||
r = formatExpand( segment, args ) | r = formatExpand( segment, args ) | ||
else | else | ||
if args.limit == "1" or | if args.limit == "1" or | ||
args.limit == true then | args.limit == true then | ||
PageTree.limit = true | |||
end | end | ||
r = formatTree( segment ) | r = formatTree( segment ) | ||
end | end | ||
end | end | ||
if r and args.stamped and | if r and args.stamped and PageTree.stamp then | ||
local babel = mw.language.getContentLanguage() | local babel = mw.language.getContentLanguage() | ||
local stamp = babel:formatDate( args.stamped, | local stamp = babel:formatDate( args.stamped, | ||
PageTree.stamp ) | |||
r = stamp .. r | r = stamp .. r | ||
end | end | ||
| Zeile 991: | Zeile 1.018: | ||
local lucky | local lucky | ||
params.frame = frame | params.frame = frame | ||
for k, v in pairs( | for k, v in pairs( PageTree.strings ) do | ||
if pars[ v ] and pars[ v ] ~= "" then | if pars[ v ] and pars[ v ] ~= "" then | ||
params[ v ] = pars[ v ] | params[ v ] = pars[ v ] | ||
end | end | ||
end -- for k, v | end -- for k, v | ||
for k, v in pairs( | for k, v in pairs( PageTree.toggles ) do | ||
if pars[ v ] then | if pars[ v ] then | ||
params[ v ] = ( pars[ v ] == "1" ) | params[ v ] = ( pars[ v ] == "1" ) | ||
| Zeile 1.013: | Zeile 1.040: | ||
return r | return r | ||
end -- framed() | end -- framed() | ||
PageTree.failsafe = function ( assert ) | |||
-- Retrieve versioning and check for compliance | |||
-- Precondition: | |||
-- assert -- string, with required version or "wikidata", | |||
-- or false | |||
-- Postcondition: | |||
-- Returns string with appropriate version, or false | |||
local r | |||
local since = assert | |||
if since == "wikidata" then | |||
local item = PageTree.item | |||
since = false | |||
if type( item ) == "number" and item > 0 then | |||
local ent = mw.wikibase.getEntity( string.format( "Q%d", | |||
item ) ) | |||
if type( ent ) == "table" then | |||
local vsn = ent:formatPropertyValues( "P348" ) | |||
if type( vsn ) == "table" and | |||
type( vsn.value ) == "string" and | |||
vsn.value ~= "" then | |||
r = vsn.value | |||
end | |||
end | |||
end | |||
end | |||
if not r then | |||
if not since or since <= PageTree.serial then | |||
r = PageTree.serial | |||
else | |||
r = false | |||
end | |||
end | |||
return r | |||
end -- PageTree.failsafe() | |||
| Zeile 1.058: | Zeile 1.122: | ||
-- .limit -- show restrictions | -- .limit -- show restrictions | ||
local lucky, r = pcall( forward, args ) | local lucky, r = pcall( forward, args ) | ||
return r or | return r or PageTree | ||
end -- p.test() | end -- p.test() | ||
p.failsafe = function ( frame ) | |||
-- Check or retrieve version information | |||
-- Precondition: | |||
-- frame -- object; #invoke environment | |||
-- Postcondition: | |||
-- Return string with error message or "" | |||
-- Uses: | |||
-- PageTree.failsafe() | |||
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 PageTree.failsafe( since ) or "" | |||
end -- p.failsafe() | |||
return p | return p | ||