Modul:Tutorial
Zur Navigation springen
Zur Suche springen
Die Dokumentation für dieses Modul kann unter Modul:Tutorial/Doku erstellt werden
local Tutorial = { serial = "2018-02-11",
suite = "Tutorial" }
--[=[
Support Tutorial tree
]=]
Tutorial.txt =
{ sequence = "bad page for page@Tutorial",
slot = "''Start of a trail.''",
sole = "''This page got currently no content assigned.''",
sparse = "''Nothing to say.''",
start = "Start",
starter = "Start trail",
suite = "All",
summary0 = "'summary' missing",
superior = "''Below all single pages are merged.''",
survey = "''Start page: [[%s|here]]''"
}
local function faculty( args, arg )
-- Retrieve boolean template arg
-- args -- (table)
-- arg -- (string, number)
local r = args[ arg ]
if r == "" or r == "0" then
r = false
end
return r and true or false
end -- faculty()
local function fault( alert )
-- Report problem
-- alert -- (string) message
-- Returns: string
local cat = Tutorial.errCat or ""
local class = Tutorial.errClass or ""
local style = Tutorial.errStyle or ""
local show = Tutorial.errText or ""
local suffix = type( alert )
local e = mw.html.create( "span" )
:addClass( "error" )
local r
if class ~= "" then
e:addClass( class )
end
if style ~= "" then
e:cssText( style )
end
if show == "" then
show = "Error"
end
if suffix == "string" then
show = string.format( "%s: %s", show, alert )
elseif suffix == "number" then
show = string.format( "%s %d", show, alert )
end
e:wikitext( show )
r = tostring( e )
if cat ~= "" then
r = string.format( "%s[[Category:%s]]", r, cat )
end
return r
end -- fault()
Tutorial.facet = function ( access )
-- Create page link with tooltip, if present
-- access -- (string) subpage
-- Returns: string
local swap = string.format( "%s:%s/%s",
Tutorial.page.nsText,
Tutorial.page.baseText,
access )
local src, show = Tutorial.foreign( access )
if show then
-- TODO plaintext show
show = tostring( mw.html.create( "span" )
:attr( "title", show )
:wikitext( access ) )
else
show = access
end
return string.format( "[[%s|%s]]", swap, show )
end -- Tutorial.facet()
Tutorial.facility = function ( appoint, at )
-- Retrieve base page and subpage name
-- appoint -- module title and base page, page derived else
-- at -- page name, or nil
-- Returns:
-- 1. module title and base page
-- 2. page name
local r1, r2
if appoint then
r1 = appoint
else
local room = mw.site.namespaces[ Tutorial.page.namespace ]
r1 = string.format( "%s:%s",
room.subject.name,
Tutorial.page.baseText )
end
if type( at ) == "string" then
r2 = mw.text.trim( at )
if r2 == "" then
r2 = false
end
end
if not r2 then
r2 = Tutorial.page.subpageText
end
return r1, r2
end -- Tutorial.facility()
Tutorial.fake = function ( album, at )
-- Transclude content
-- album -- number of trail
-- at -- number of section
-- Returns: (string) page content
local trails = Tutorial.def.trails
local sort = Tutorial.page.subpageText
local r
if type( trails ) == "table" then
local trail = trails[ album ]
if type( trail ) == "table" then
local start = trail[ 1 ]
trail = trail[ 2 ]
if type( start ) == "string" and
type( trail ) == "table" then
local single = trail[ at ]
start = mw.text.trim( start )
if type( single ) == "string" and
start ~= "" then
r = Tutorial.feed( start, single, trail, album, at )
end
end
end
end
if r then
sort = "§ " .. sort
else
r = Tutorial.txt.sole
sort = "# " .. sort
end
r = r .. Tutorial.fold( sort )
return r
end -- Tutorial.fake()
Tutorial.father = function ( ancestor )
-- Top page: link all trails
-- ancestor -- (string) supreme page
-- Returns: (mw.html) <dl>, or nil
local r
if type( Tutorial.def.trails ) == "table" then
local dl = mw.html.create( "dl" )
local dd, ea, eg, et, ex, section, src, story, sum, trail
story = string.format( "[[[%s/%%s|%s]]]",
ancestor,
Tutorial.txt.suite )
for i = 1, #Tutorial.def.trails do
trail = Tutorial.def.trails[ i ]
if type( trail ) == "table" then
section = trail[ 1 ]
if type( section ) == "string" then
r = true
dl:newline()
:node( mw.html.create( "dt" )
:wikitext( section ) )
src, sum = Tutorial.foreign( section )
if sum ~= section then
dl:newline()
:node( mw.html.create( "dd" )
:wikitext( sum ) )
end
trail = trail[ 2 ]
if type( trail ) == "table" then
dd = mw.html.create( "dd" )
ea = mw.html.create( "small" )
:wikitext( string.format( story,
section ) )
eg = mw.html.create( "span" )
Tutorial.forward( eg, i, 1, 1,
Tutorial.txt.start,
true )
et, ex = Tutorial.flip( ancestor, trail, i )
if et then
dd:newline()
:node( eg )
:newline()
:node( et )
:newline()
:node( ea )
:newline()
:node( ex )
end
end
dl:newline()
:node( dd )
end
end
end -- i = 1, #Tutorial.def.trails
if r then
r = dl
end
end
return r
end -- Tutorial.father()
Tutorial.features = function ( ancestor, all, album, attribute, ahead )
-- List of direct links to trail subpages
-- ancestor -- (string) supreme page
-- all -- (table) subpages
-- album -- (number) trail
-- attribute -- (boolean) numbered list
-- ahead -- (boolean) show both name and summary
-- Returns: (mw.html)
local n = #all
local r
if n > 0 then
local sequence = string.format( "[[%s/%d-%%d|%%s]]",
ancestor,
album )
local ttips = Tutorial.future( all, at, false, ancestor )
local s, show
if attribute then
s = "ol"
else
s = "ul"
end
r = mw.html.create( s )
for i = 1, #all do
s = ttips[ i ]
if ahead and s then
show = string.format( sequence, i, all[ i ] )
show = string.format( "%s – %s", show, s )
else
show = string.format( sequence, i, s or all[ i ] )
end
r:node( mw.html.create( "li" )
:wikitext( show ) )
end -- i = 1, #all
else
r = mw.html.create( "span" )
:wikitext( Tutorial.txt.sparse )
end
return r
end -- Tutorial.features()
Tutorial.feed = function ( above, access, all, album, at )
-- Equip page transclusion
-- above -- (string) start
-- access -- (string) subpage
-- all -- (table) subpages
-- album -- (number) trail
-- at -- (number) section
-- Returns: (string), or nil
local src, sum = Tutorial.foreign( access )
local r
if src then
local box = Tutorial.further( all, album, at )
local start = Tutorial.facet( above )
r = Tutorial.flat( sum, start, box )
if type( Tutorial.pageSource ) == "table" and
type( Tutorial.pageSource.source ) == "string" then
local e = mw.html.create( "div" )
:css( "clear", "right" )
:css( "float", "right" )
:css( "margin-top", "-1em" )
:css( "margin-bottom", "1em" )
:css( "padding", "2px" )
if type( Tutorial.pageSource.class ) == "string" then
e:addClass( Tutorial.pageSource.class )
end
if Tutorial.pageSource.loose then
e:css( "display", "none" )
end
if type( Tutorial.pageSource.style ) == "string" then
e:cssText( Tutorial.pageSource.style )
end
e:wikitext( string.format( "[[%s:%s/%s|%s]]",
Tutorial.page.nsText,
Tutorial.page.baseText,
access,
Tutorial.pageSource.source ) )
r = string.format( "%s\n%s\n", r, tostring( e ) )
end
r = r .. Tutorial.frame:preprocess( src )
end
return r
end -- Tutorial.feed()
Tutorial.fence = function ( access )
-- Retrieve page protection
-- Precondition:
-- access -- (string) subpage
-- Returns: (string) level sign
local t = mw.title.new( string.format( "%s/%s",
Tutorial.page.baseText,
access ),
Tutorial.page.nsText )
local r
if t.exists then
local p = t.protectionLevels
if type( p ) == "table" then
p = p.edit
if type( p ) == "table" then
for k, v in pairs( p ) do
if v == "editeditorprotected" then
r = "¾"
elseif v == "autoconfirmed" then
r = "½"
elseif v == "sysop" then
r = "1"
end
end -- for k, v
end
end
end
return r or "0"
end -- Tutorial.fence()
Tutorial.fenced = function ( album, at, access )
-- Retrieve page group protection
-- Precondition:
-- album -- number of trail
-- at -- number of section
-- access -- (string) subpage
-- Returns: (string) both levels
return string.format( "%s,%s",
Tutorial.fence( string.format( "%d-%d",
album, at ) ),
Tutorial.fence( access ) )
end -- Tutorial.fenced()
Tutorial.fetch = function ( appoint, allow )
-- Attach config or tree module
-- Precondition:
-- appoint -- module title, "config" if "", page derived else
-- allow -- (boolean) suppress error message
-- Returns: (table) with library, or (string) error message
local suite = appoint
local got, lucky, r, source
if not Tutorial.page then
Tutorial.page = mw.title.getCurrentTitle()
end
if type( suite ) == "string" then
suite = mw.text.trim( suite )
if suite == "" then
suite = false
end
else
suite = string.format( "%s:%s",
Tutorial.page.nsText,
Tutorial.page.baseText )
end
if suite then
source = string.format( "Module:%s/%s",
Tutorial.suite, suite )
lucky, got = pcall( require, source )
if type( got ) == "table" then
r = got
if type( got[ suite ] ) == "function" then
r = got[ suite ]()
end
end
if type( r ) ~= "table" then
if allow then
r = ""
else
r = string.format( "%s invalid", source )
end
end
end
source = string.format( "Module:%s/config", Tutorial.suite )
lucky, got = pcall( require, source )
if type( got ) == "table" then
for k, v in pairs( got ) do
if type( v ) == "table" then
if not Tutorial[ k ] then
Tutorial[ k ] = { }
end
if type( Tutorial[ k ] ) == "table" then
local t = Tutorial[ k ]
for kk, vv in pairs( v ) do
t[ kk ] = vv
end -- for kk, vv
end
else
Tutorial[ k ] = v
end
end -- for k, v
end
return r
end -- Tutorial.fetch()
Tutorial.field = function ( access, add )
-- Create box
-- access -- 2nd headline, string, or nil
-- add -- action area, mw.html <div>, or nil
-- Returns: (string) box
local bas = Tutorial.def
local btm = bas.bottom
local css = bas.style
local f = function ()
local r = mw.html.create( "td" )
if type( css.fgc ) == "string" then
r:css( "border-top-color", "#" .. css.fgc )
:css( "border-top-style", "solid" )
:css( "border-top-width", "1px" )
end
return r
end -- f()
local tbl = mw.html.create( "table" )
:addClass( "wikiTutorial" )
:attr( "role", "navigation" )
:css( "float", "right !important" )
:css( "margin-left", "1em !important" )
-- mobile resets first float table (infobox)
:css( "margin-bottom", "1em" )
local te = mw.html.create( "th" )
if type( css.bgc ) == "string" then
tbl:css( "background-color", "#" .. css.bgc )
end
if type( css.fgc ) == "string" then
tbl:css( "color", "#" .. css.fgc )
end
if type( css.border ) == "table" then
if type( css.fgc ) == "string" then
tbl:css( "border-color", "#" .. css.fgc )
end
if type( css.border.style ) == "string" then
tbl:css( "border-style", css.border.style )
end
if type( css.border.width ) == "string" then
tbl:css( "border-width", css.border.width )
end
end
if type( css.icon ) == "string" then
local size
if type( css.size ) == "string" then
size = css.size:match( "^(%d+)px$" )
if size then
size = tonumber( size ) + 4
size = string.format( "%dpx", size )
else
size = css.size
end
else
size = "15px"
end
te:wikitext( string.format( "[[File:%s|%s]]",
css.icon,
size ) )
end
if type( bas.show ) == "string" then
local e = mw.html.create( "span" )
:css( "margin-left", "5px" )
local s = bas.supreme
if type( s ) == "string" then
s = string.format( "[[%s|%s]]", s, bas.show )
else
s = bas.show
end
e:wikitext( s )
if type( css.size ) == "string" then
e:css( "font-size", css.size )
end
te:node( e )
end
te:css( "padding-left", "4px" )
:css( "padding-right", "4px" )
:css( "text-align", "left" )
tbl:newline()
:node( mw.html.create( "tr" )
:node( te ) )
if type( access ) == "string" then
tbl:newline()
:node( mw.html.create( "tr" )
:node( f():wikitext( access ) ) )
end
if type( add ) == "table" then
tbl:newline()
:node( mw.html.create( "tr" )
:node( f():node( add ) ) )
end
if type( btm ) == "table" then
te = f()
if type( btm.service ) == "string" then
local s
if type( btm.show ) == "string" then
s = "|" .. btm.show
else
s = ""
end
te:wikitext( string.format( "[[%s%s]]",
btm.service,
s ) )
elseif type( btm.show ) == "string" then
te:wikitext( btm.show )
end
tbl:newline()
:node( mw.html.create( "tr" )
:node( te ) )
end
return tostring( tbl )
end -- Tutorial.field()
Tutorial.find = function ( at )
-- Retrieve trail lessons
-- at -- trail name
-- Returns:
-- (table) or nil
-- (number) trail
local r1, r2
for i = 1, #Tutorial.def.trails do
trail = Tutorial.def.trails[ i ]
if type( trail ) == "table" then
if trail[ 1 ] == at then
r1 = trail[ 2 ]
r2 = i
break -- i = 1, #Tutorial.def.trails
end
end
end -- i = 1, #Tutorial.def.trails
return r1, r2
end -- Tutorial.find()
Tutorial.flat = function ( about, above, add )
-- Single content page
-- about -- summary
-- above -- trail start, if in trail
-- add -- action area, mw.html <div>, or nil
-- Returns: (string)
local css = Tutorial.def.style
local e = mw.html.create( "div" )
local r = Tutorial.field( above, add )
e:wikitext( about )
if type( css ) == "table" then
if type( css.bgc ) == "string" then
e:css( "background-color", "#" .. css.bgc )
end
if type( css.fgc ) == "string" then
e:css( "color", "#" .. css.fgc )
end
if type( css.h1 ) == "table" then
for k, v in pairs( css.h1 ) do
e:css( k, v )
end -- for k, v
end
end
r = string.format( "%s\n%s%s",
r,
tostring( e ),
Tutorial.fold( Tutorial.page.subpageText ) )
return r
end -- Tutorial.flat()
Tutorial.flip = function ( ancestor, all, album )
-- Create trail extension for survey
-- ancestor -- (string) supreme page
-- all -- (table) subpages
-- album -- (number) trail
-- Returns:
-- (mw.html) toggle <span>, or nil
-- (mw.html) list <div>, or nil
local r1 = mw.html.create( "span" )
:css( "margin-left", "2em" )
:css( "margin-right", "2em" )
local r2 = mw.html.create( "div" )
Tutorial.flipper( r1, string.format( "tutorial-%d", album ) )
r2:attr( "id",
string.format( "mw-customcollapsible-tutorial-%d", album ) )
:addClass( "mw-collapsible mw-collapsed" )
:css( "display", "none" )
:newline()
:node( Tutorial.features( ancestor, all, album, false, true ) )
return r1, r2
end -- Tutorial.flip()
Tutorial.flipper = function ( apply, assign )
-- Create toggle
-- apply -- (mw.html)
-- assign -- (string) ID
local sel = "nomobile"
-- mobile no collapsible yet
-- derive from .client-nojs display:none
local sign = "mw-customtoggle"
sel = string.format( "%s %s-%s %s-%s-show %s-%s-hide",
sel, sign, assign, sign, assign, sign, assign )
apply:addClass( sel )
:newline()
:node( Tutorial.flipflop( true, assign ) )
:newline()
:node( Tutorial.flipflop( false, assign ) )
end -- Tutorial.flipper()
Tutorial.flipflop = function ( activate, assign )
-- Create single toggle image
-- activate -- (boolean) more (down), or not
-- assign -- (string) ID, or nil
-- Returns: (mw.html), or (string) if not
local j = 16
local support = mw.ustring.char( 43, 47, 8722 )
local sign = "OOjs UI icon caret%s.svg"
local r, s
if activate then
s = "Down"
else
s = "Up"
end
r = string.format( "[[File:%s|%dpx|link=#top|%s]]",
string.format( sign, s ), j, support )
if assign then
if activate then
s = "show"
else
s = "hide"
end
r = mw.html.create( "span" )
:addClass( "mw-collapsible" )
:attr( "id",
string.format( "mw-customcollapsible-%s-%s",
assign, s ) )
:wikitext( r )
if not activate then
r:addClass( "mw-collapsed" )
:css( "display", "none" )
end
end
return r
end -- Tutorial.flipflop()
Tutorial.focus = function ( at, about, appoint )
-- Retrieve page name of particular lesson in trail
-- at -- page name, or nil
-- about -- lesson name, or nil (means first in trail)
-- appoint -- module title and base page, page derived else
-- Returns: (string)
local suite, start = Tutorial.facility( appoint, at )
local r, trail
for i = 1, #Tutorial.def.trails do
trail = Tutorial.def.trails[ i ]
if type( trail ) == "table" and
type( trail[ 2 ] ) == "table" and
( trail[ 1 ] == start or
trail[ 2 ][ 1 ] == start ) then
if about then
trail = trail[ 2 ]
for k = 1, #trail do
if trail[ k ] == about then
r = string.format( "%s/%d-%d", suite, i, k )
break -- k = 1, #trail
end
end -- k = 1, #trail
else
r = string.format( "%s/%d-1", suite, i )
end
break -- i = 1, #Tutorial.def.trails
end
end -- i = 1, #Tutorial.def.trails
if not r then
local t
if about then
t = mw.title.new( string.format( "%s/%s",
Tutorial.page.baseText,
about ),
Tutorial.page.nsText )
if t.exists then
r = t.prefixedText
end
end
if not r then
t = mw.title.new( Tutorial.page.baseText,
Tutorial.page.nsText )
r = t.prefixedText
end
end
return r
end -- Tutorial.focus()
Tutorial.fold = function ( align )
-- Create DEFAULTSORT and Category
-- align -- sortkey
-- Returns:
-- (string) may be empty
local r
if type( Tutorial.def.cat ) == "string" then
local s = Tutorial.frame:callParserFunction( "DEFAULTSORT",
align )
r = string.format( "\n[[Category:%s]]", Tutorial.def.cat )
else
r = ""
end
return r
end -- Tutorial.fold()
Tutorial.folder = function ()
-- Create maintenance survey
-- Returns:
-- (mw.html)
local r
if type( Tutorial.def.trails ) == "table" then
local dl = mw.html.create( "dl" )
local e = mw.html.create( "span" )
local room = mw.site.namespaces[ Tutorial.page.namespace ]
local story = "[[%s:%s/%%s|%%s]]"
local single = "[[%s:%s/%%d-%%d|%%d]]. " .. story .. " %s %%s %s"
local stitch = "[[%s:%s/%%d-%%d|@]]/[[%s:%s/%%s|@]] %%s"
local section, src, strict, sum, trail, ttips
e:css( "font-size", "smaller" )
:css( "margin-left", "2em" )
:newline()
:wikitext( string.format( stitch,
room.talk.name,
Tutorial.page.baseText,
room.talk.name,
Tutorial.page.baseText ) )
single = string.format( single,
Tutorial.page.nsText,
Tutorial.page.baseText,
Tutorial.page.nsText,
Tutorial.page.baseText,
mw.ustring.char( 8211 ),
tostring( e ) )
story = string.format( story,
Tutorial.page.nsText,
Tutorial.page.baseText )
for i = 1, #Tutorial.def.trails do
trail = Tutorial.def.trails[ i ]
if type( trail ) == "table" then
section = trail[ 1 ]
if type( section ) == "string" then
r = true
src = string.format( story, section, section )
e = mw.html.create( "span" )
e:css( "font-size", "smaller" )
:css( "margin-left", "2em" )
:newline()
:wikitext( string.format( "[[%s:%s/%s|@]]",
room.talk.name,
Tutorial.page.baseText,
section ) )
dl:newline()
:node( mw.html.create( "dt" )
:wikitext( src )
:node( e ) )
src, sum = Tutorial.foreign( section )
if sum ~= section then
dl:newline()
:node( mw.html.create( "dd" )
:wikitext( sum ) )
end
trail = trail[ 2 ]
if type( trail ) == "table" then
ttips = Tutorial.future( trail )
for k = 1, #trail do
strict = Tutorial.fenced( i, k, trail[ k ] )
src = string.format( single,
i, k, k,
trail[ k ],
trail[ k ],
ttips[ k ],
k, k,
trail[ k ],
strict )
dl:newline()
:node( mw.html.create( "dd" )
:wikitext( src ) )
end -- k = 1, #trail
end
end
end
end -- i = 1, #Tutorial.def.trails
if r then
r = dl
end
end
return r
end -- Tutorial.folder()
Tutorial.foreign = function ( access, above )
-- Retrieve page and summary
-- access -- (string) subpage
-- above -- (string) supreme page, or nil
-- Returns:
-- (string) source, or nil
-- (string) summary
local page, source, sum, title
if above then
title = mw.title.new( above )
else
title = Tutorial.page
end
page = mw.title.makeTitle( title.nsText,
string.format( "%s/%s",
title.baseText,
access ) )
source = page:getContent()
if source then
if not Tutorial.patSummary then
Tutorial.patSummary = string.format( "%s%s%s%s%s",
"%{%{%s*#invoke:%s*",
"Tutorial%s*",
"|%s*s%l+%s*",
"|%s*summary%s*=%s*",
"([^%}]+)%s*%}%}" )
end
sum = source:match( Tutorial.patSummary )
if sum then
sum = mw.text.trim( sum )
end
end
return source, sum or access
end -- Tutorial.foreign()
Tutorial.forward = function ( apply, album, at, advance, about, alter )
-- Arrow button (horizontal)
-- apply -- (mw.html) section
-- album -- (number) trail, or false
-- at -- (number) target section, or false
-- advance -- (number) 1: rightward -- -1: left -- 0: start
-- about -- (string) tooltip, or false
-- alter -- (boolean) true: small
local e = mw.html.create( "div" )
local j, k, m, s, src
if advance == -1 then
s = " left"
elseif advance == 0 then
s = ""
else
s = " right"
end
if alter then
m = 9
j = 1
k = 2
else
m = 24
j = 3
k = 4
end
apply:css( "margin", string.format( "%dpx", j ) )
s = string.format( "File:White triangle%s.svg", s )
src = string.format( "[[%s|%dpx|link=%%s]]", s, m )
if at then
local btn = mw.html.create( "span" )
btn:addClass( "mw-ui-button mw-ui-progressive" )
:css( "padding", string.format( "%dpx", k ) )
:css( "min-width", "0" )
:wikitext( string.format( src, "" ) )
if album then
local f = function ( allow, at, arrow )
local wrap = mw.html.create( "span" )
wrap:wikitext( string.format( "[%s %s]",
at, arrow ) )
if allow then
wrap:addClass( "nomobile" )
else
wrap:addClass( "mobile" )
:css( "display", "none" )
end
apply:node( wrap )
end
local show
s = string.format( "%d-%d", album, at )
btn:attr( "title", about or s )
s = string.format( "%s:%s/%s",
Tutorial.page.nsText,
Tutorial.page.baseText,
s )
s = tostring( mw.uri.canonicalUrl( s ) )
apply:addClass( "plainlinks" )
:attr( "role", "button" )
show = tostring( btn )
f( true, s, show )
s = s:gsub( "(//%l+%.)", "%1m." )
f( false, s, show )
else
btn:attr( "title", "Demo" )
apply:node( btn )
end
apply:css( "background-color", "#3366CC" ) -- fallback
else
src = string.format( src, "|×" )
apply:css( "background-color", "#B0B0B0" )
:css( "padding", string.format( "%dpx", k ) )
:wikitext( src )
end
end -- Tutorial.forward()
Tutorial.full = function ( at )
-- Collect all trail page contents
-- at -- trail name
-- Returns: (string) collection, or nil
local r, trail
for i = 1, #Tutorial.def.trails do
trail = Tutorial.def.trails[ i ]
if type( trail ) == "table" then
if trail[ 1 ] == at then
if type( trail[ 2 ] ) == "table" then
trail = trail[ 2 ]
if type( trail ) == "table" then
local src, sum = Tutorial.foreign( at )
local e, m, n, s
e = mw.html.create( "div" )
:css( "clear", "both" )
:css( "margin-top", "1em" )
:css( "margin-bottom", "1em" )
:wikitext( Tutorial.txt.superior )
r = string.format( "%s\n%s\n%s\n__TOC__",
Tutorial.flat( at ),
sum,
tostring( e ) )
for k = 1, #trail do
s = trail[ k ]
if type( s ) == "string" then
s2, sum = Tutorial.foreign( s )
if type( s2 ) == "string" then
m, n = s2:find( "}}\n?[^\n]+\n" )
if n then
s = s2:sub( 1, n - 1 )
s2 = s2:sub( n )
else
s = s2
s2 = ""
end
s2 = s:gsub( "'''", "" ) .. s2
s = Tutorial.frame:preprocess( s2 )
e = mw.html.create( "h2" )
:wikitext( sum )
r = string.format( "%s\n%s\n%s",
r,
tostring( e ),
s )
end
end
end -- k = 1, #trail
end
end
break -- i = 1, #all
end
end
end -- i = 1, #Tutorial.def.trails
return r
end -- Tutorial.full()
Tutorial.further = function ( all, album, at )
-- Trail navigation
-- all -- (table) subpages
-- album -- (number) trail
-- at -- (number) section
-- Returns: (mw.html)
local before = mw.html.create( "div" )
local down = mw.html.create( "div" )
local pop = mw.html.create( "div" )
local post = mw.html.create( "div" )
local row = mw.html.create( "div" )
local r = mw.html.create( "div" )
local ul = mw.html.create( "ul" )
local ttips = Tutorial.future( all, at )
local e, m, s, support, t
if at > 1 then
m = at - 1
support = ttips[ m ]
end
before:css( "float", "left" )
Tutorial.forward( before, album, m, -1, support )
if at < #all then
m = at + 1
support = ttips[ m ]
else
m = false
end
post:css( "float", "right" )
Tutorial.forward( post, album, m, 1, support )
row:node( before )
:node( post )
Tutorial.flipper( down, "tutorial" )
if at > 1 then
local beg = mw.html.create( "div" )
:css( "float", "left" )
Tutorial.forward( beg, album, 1, 0, Tutorial.txt.starter, true )
down = mw.html.create( "div" )
:node( beg )
:newline()
:node( down )
end
pop:attr( "id", "mw-customcollapsible-tutorial" )
:addClass( "mw-collapsible mw-collapsed" )
:addClass( "mobile" )
:css( "display", "none" )
:css( "clear", "both" )
:css( "text-align", "left" )
:newline()
for i = 1, #all do
s = all[ i ]
e = mw.html.create( "span" )
if i == at then
e:css( "font-weight", "bold" )
else
t = mw.html.create( "span" )
:attr( "title", ttips[ i ] )
:wikitext( s )
s = string.format( "[[%s:%s/%d-%d|%s]]",
Tutorial.page.nsText,
Tutorial.page.baseText,
album,
i,
tostring( t ) )
end
ul:node( mw.html.create( "li" )
:node( e:wikitext( s ) ) )
:newline()
end -- i = 1, #all
pop:node( ul )
r:css( "text-align", "center" )
:node( row )
:newline()
:node( mw.html.create( "div" )
:css( "clear", "both" ) )
:newline()
:node( down )
:newline()
:node( pop )
return r
end -- Tutorial.further()
Tutorial.future = function ( all, already, another, above )
-- Retrieve tooltips
-- all -- (table) subpages
-- already -- (number) trail
-- another -- (string) text if already, or nil
-- above -- (string) supreme page, or nil
-- Returns: (table)
local r = { }
local d, s, sub
for i = 1, #all do
if i == already then
s = another or "'''<*>'''"
else
sub = all[ i ]
d, s = Tutorial.foreign( sub, above )
end
-- TODO plaintext
table.insert( r, s )
end -- i = 1, #all
return r
end -- Tutorial.future()
-- Export
local p = { }
p.begin = function ( frame )
-- Retrieve page name of first lesson in trail
-- 1 -- title part of trail or first page
-- 2 -- Wikipedia:Tutorial, or derive from page name
local t = frame.args[ 2 ]
local r = Tutorial.fetch( t )
if type( r ) == "table" then
Tutorial.def = r
Tutorial.frame = frame
r = Tutorial.focus( frame.args[ 1 ], false, t )
end
return r
end -- p.begin
p.gadget = function ( frame )
-- Retrieve GUI elements
local def = Tutorial.fetch( frame.args[ 1 ] )
local r = mw.html.create( "span" )
if type( def ) == "table" then
local sel = frame.args[ 2 ]
Tutorial.def = def
if sel == "go" then
Tutorial.forward( r, false, true, 1, false, true )
elseif sel == "top" then
Tutorial.forward( r, false, true, 0, false, true )
elseif sel == "expand" then
r:wikitext( Tutorial.flipflop( true ) )
:wikitext( Tutorial.flipflop( false ) )
end
end
return r
end -- p.gadget
p.index = function ( frame )
-- List all trails or lessons (main or maintenance page)
local r = Tutorial.fetch()
if type( r ) == "table" then
local sel = frame.args[ 1 ]
Tutorial.def = r
Tutorial.frame = frame
if frame.args.mode == "main" or not sel then
sel = sel or Tutorial.page.prefixedText
r = Tutorial.father( sel )
elseif sel == "trail" then
local t2 = Tutorial.page.subpageText:match( "^(%d+)%-%d+$" )
local t1
if t2 then
if type( Tutorial.def.trails ) == "table" then
t2 = tonumber( t2 )
sel = Tutorial.def.trails[ t2 ]
if type( sel ) == "table" and
type( sel[ 2 ] ) == "table" then
t1 = sel[ 2 ]
end
end
else
t1, t2 = Tutorial.find( Tutorial.page.subpageText )
end
if type( t1 ) == "table" then
local less = faculty( frame.args, "less" )
sel = string.format( "%s:%s",
Tutorial.page.nsText,
Tutorial.page.baseText )
r = Tutorial.features( sel, t1, t2, true, not less )
else
local e = mw.html.create( "div" )
e:css( "clear", "both" )
:css( "margin-top", "1em" )
:css( "margin-bottom", "1em" )
:wikitext( string.format( Tutorial.txt.survey,
Tutorial.focus() ) )
r = tostring( e )
end
elseif sel == "maintain" then
r = Tutorial.folder()
end
end
return r or ""
end -- p.index
p.isVirtual = function ()
-- Is this a virtual page?
local r = Tutorial.page.subpageText:find( "^%d+%-%d+$" )
if faculty( frame.args, "not" ) then
r = not r
end
if r then
r = "1"
else
r = ""
end
return r
end -- p.isVirtual
p.page = function ( frame )
-- Virtual lesson page
local r = Tutorial.fetch()
if type( r ) == "table" then
Tutorial.def = r
local k, i = Tutorial.page.subpageText:match( "^(%d+)%-(%d+)$" )
if k then
Tutorial.frame = frame
r = Tutorial.fake( tonumber( k ), tonumber( i ) )
else
r = fault( Tutorial.txt.sequence )
end
else
r = fault( r )
end
return r
end -- p.page
p.redirect = function ( frame )
-- Retrieve page name of particular lesson in trail
-- 1 -- title part of trail or first page
-- 2 -- lesson
-- 3 -- Wikipedia:Tutorial, or derive from page name
local t = frame.args[ 3 ]
local r
if t then
Tutorial.page = mw.title.new( t )
end
r = Tutorial.fetch()
if type( r ) == "table" then
Tutorial.def = r
Tutorial.frame = frame
r = Tutorial.focus( frame.args[ 1 ],
frame.args[ 2 ],
t )
end
return r
end -- p.redirect
p.single = function ( frame )
-- Single content page
local r = Tutorial.fetch( false, true )
if type( r ) == "table" then
Tutorial.def = r
local summary = frame.args.summary or ""
if summary == "" then
r = fault( Tutorial.txt.summary0 )
else
local parent = frame:getParent()
Tutorial.frame = frame
if parent:getTitle() == Tutorial.page.prefixedText then
r = Tutorial.flat( summary )
else
r = ""
end
end
elseif r ~= "" then
r = fault( r )
end
return r
end -- p.single
p.start = function ( frame )
-- Start page of a trail
local r = Tutorial.fetch()
if type( r ) == "table" then
local summary = frame.args.summary or ""
if summary == "" then
r = fault( Tutorial.txt.summary0 )
else
local sort
Tutorial.def = r
Tutorial.frame = frame
if type( Tutorial.def.trails ) == "table" then
r = Tutorial.full( Tutorial.page.subpageText )
end
if r then
sort = "* "
else
r = Tutorial.txt.slot
sort = "? "
end
r = r .. Tutorial.fold( sort .. Tutorial.page.subpageText )
end
else
r = fault( r )
end
return r
end -- p.start
p.style = function ( frame )
-- Retrieve standard style
-- Parameter
-- 1 -- Wikipedia:Tutorial
-- 2 -- bgc, icon, ...
local def = Tutorial.fetch( frame.args[ 1 ] )
local r
if type( def ) == "table" then
def = def[ "style" ]
if type( def ) == "table" then
r = def[ frame.args[ 2 ] ]
end
end
return r or ""
end -- p.style
p.failsafe = function ()
return Tutorial.serial
end -- p.failsafe
return p