Modul:Hilfe:VisualEditor
Erscheinungsbild
Dokumentation für das Modul Hilfe:VisualEditor[Ansicht] [Bearbeiten] [Versionsgeschichte] [ ]
Dieses Modul wurde am 19. Mai 2019 von Hilfe:VisualEditor der deutschen Wikipedia importiert. Statt Änderungen hier auf Wikivoyage vorzunehmen, sollte eine neuer Import vorgezogen werden, falls im originalen Wiki neue Funktionen hinzugekommen sind. Stimme dich dazu bitte mit der Community in der Vorlagenwerkstatt ab. |
Das Modul sollte aktualisiert werden! |
Dieses Modul ist getestet und für den projektweiten Gebrauch geeignet. Es kann in Vorlagen benutzt und auf Hilfeseiten erläutert werden. Entwicklungen an dem Modul sollten auf VisualEditor/Test und die Anwendung auf der Spielwiese getestet werden, da wiederholte Trial-and-Error-Edits die Resourcen stark belasten können. |
Hinweise
- Die obige Dokumentation wurde aus der Seite Modul:Hilfe:VisualEditor/Doku eingefügt. (bearbeiten | Versionsgeschichte) Die Kategorien für dieses Modul sollten in der Dokumentation eingetragen werden. Die Interwiki-Links sollten auf Wikidata eingepflegt werden.
- Liste der Unterseiten
local HelpVisualEditor = { suite = "HelpVisualEditor",
serial = "2019-05-16",
item = 63383133 }
--[=[
Unterstützung für Vorlagen/Hilfeseiten Hilfe:VisualEditor/***
]=]
local lucky, Data = pcall( mw.loadData,
"Module:Hilfe:VisualEditor/config" )
if type( Data ) ~= "table" then
error( "[[Module:Hilfe:VisualEditor/config]] fehlt" )
end
local Config = Data.config
local Widgets = { }
local Frame
local Title
local Tree
local function facet( activate )
return activate:gsub( "%.svg$", "-progressive.svg" )
end -- facet()
local function factory( ancestor, array, all )
-- Clone a table
-- Parameter:
-- ancestor -- table, to be copied
-- array -- true, if sequence; number: copy first elements
-- all -- true, if deep elements to be copied also
-- Returns:
-- new table
local r = { }
if array then
local n
if type( array ) == "number" then
n = array
else
n = table.maxn( ancestor )
if n == 0 then
for k, v in pairs( ancestor ) do
n = n + 1
end -- for k, v
end
end
for i = 1, n do
table.insert( r, ancestor[ i ] )
end -- for i
if all then
local e
for i = 1, n do
e = r[ i ]
if type( e ) == "table" then
r[ i ] = factory( e, false, true )
end
end -- for i
end
else
for k, v in pairs( ancestor ) do
r[ k ] = v
end -- for k, v
if all then
local e
for k, v in pairs( r ) do
e = r[ k ]
if type( e ) == "table" then
r[ k ] = factory( e, false, true )
end
end -- for k, v
end
end
return r
end -- factory()
local function faculty( adjust )
-- Test template arg for boolean
-- adjust -- string or nil
-- Returns boolean
local s = type( adjust )
local r
if s == "string" then
r = mw.text.trim( adjust )
r = ( r ~= "" and r ~= "0" )
elseif s == "boolean" then
r = adjust
else
r = false
end
return r
end -- faculty()
local function fallback( ask )
-- Create similar item
-- ask -- string, with ID
-- Returns table
local insertFew = 4
local kurzSchrift = 4
local r
if ask:sub( 1, 10 ) == "CodeMirror" and #ask > 10 then
r = { menu = 3,
show = Tree.CodeMirror.show,
slot = Tree.CodeMirror.slot,
icon = Tree.CodeMirror.icon,
start = Tree.CodeMirror.start,
lowered = false }
if ask == "CodeMirrorAktiv" then
r.icon = facet( r.icon )
end
elseif ask == "InsertFew" then
r = { menu = -2,
show = Tree.InsertAll.show,
slot = Tree.InsertAll.slot,
icon = Tree.InsertAll.icon,
start = Tree.InsertAll.start,
entries = factory( Tree.InsertAll.entries, insertFew ) }
r.entries[ insertFew ] = "Mehr"
elseif ask:sub( 1, 7 ) == "Schrift" then
local entries, k
if ask:sub( 1, 11 ) == "SchriftKurz" then
k = kurzSchrift
else
k = true
end
entries = factory( Tree.SchriftAlle.entries, k )
r = { menu = -2,
icon = Tree.SchriftAlle.icon,
slot = Tree.SchriftAlle.slot,
entries = entries }
if k == kurzSchrift then
r.entries[ kurzSchrift ] = "Mehr"
if ask == "SchriftKurz" then
r.entries[ kurzSchrift - 1 ] = "Gestaltlos"
else
r.entries[ kurzSchrift - 1 ] = "GestaltlosNix"
end
else
r.entries[ #r.entries - 1 ] = "GestaltlosNix"
end
elseif ask:sub( 1, 14 ) == "Seitenoptionen" and #ask > 14 then
local sub
r = factory( Tree.Seitenoptionen, false, true )
for i = 2, #r.entries do
sub = r.entries[ i ]
if i <= 5 then
Tree[ sub ] = factory( Tree[ sub ] )
Tree[ sub ].lowered = true
elseif sub == "CodeMirror" then
if ask:sub( 20 ) == "" then
r.entries[ i ] = "CodeMirrorInaktiv"
else
r.entries[ i ] = sub .. ask:sub( 20 )
end
break -- for i
end
end -- for i
end
return r
end -- fallback()
local function fault( a )
-- Formatiere Fehler mit class=error
-- Parameter:
-- a -- string, mit Fehlermeldung
-- Rückgabewert:
-- string, mit HTML-Element
local e = mw.html.create( "span" )
e:addClass( "error" )
:wikitext( "FEHLER * " .. a )
return tostring( e )
end -- fault()
local function fetch( access )
-- Retrieve static tree entry; else on the fly
-- Parameter:
-- access -- string, mit ID
-- Rückgabewert:
-- tree entry
local r = Tree[ access ]
if not r then
r = fallback( access )
end
return r
end -- fetch()
local function fill( apply, assume )
-- Beschriftung ermitteln
-- Parameter:
-- apply -- table
-- assume -- string, mit Rückfallwert
-- Rückgabewert:
-- string
local r
if apply.slot then
r = mw.message.new( apply.slot:gsub( "^@", "visualeditor-" ) )
if not r:exists() then
r = false
end
end
if r then
r = r:plain()
elseif apply.show then
r = apply.show
else
r = assume
end
return r
end -- fill()
local function flat( a )
-- Eingabewert trimmen; leeren Wert ignorieren
-- Parameter:
-- a -- string oder nil
-- Rückgabewert:
-- string oder nil oder false
local r
if a then
r = mw.text.trim( a )
if r == "" then
r = false
end
end
return r
end -- flat()
Widgets.dropdown2 = function ( all, accessed, aim, above, active, align )
local r
if all.entries then
local cssT = { "background-color:#FFFFFF",
"border-collapse:collapse",
"margin-left:.5em",
"margin-bottom:.5em" }
local high = { }
local low = ( all.menu < 0 )
local e, entry, launch, show, short, sign, space, strong, style
if aim then
e = mw.text.split( aim, "+", true )
for k, v in pairs( e ) do
high[ v ] = true
end -- for k, v
end
if above then
if type( above ) == "string" then
table.insert( cssT, "min-width:" .. above )
end
else
table.insert( cssT, "width:100%" )
end
style = table.concat( cssT, ";" )
r = "\n{|"
if above then
local pars = { background = "#" .. Config.bgMainSel,
div = true }
local sep = "style='border%%s: #%s 1px solid;%%s'"
sep = string.format( sep, Config.borderDd )
style = style .. ";box-shadow: 0 2px 2px 0 rgba(0,0,0,0.25)"
r = string.format( "%s %s\n|%s|%s",
r,
string.format( sep, "", style ),
string.format( sep, "-bottom", "" ),
Widgets.toolItem( accessed, pars ) )
else
cssT = { style,
"font-size:90%" }
r = string.format( "%s style='%s'",
r,
table.concat( cssT, ";" ) )
end
space = false
for k, v in pairs( all.entries ) do
entry = fetch( v )
launch = high[ v ]
if not entry then
return fault( "dropdown: Bad entry " .. v )
end
if launch then
if low or Config.itemSel == 1 then
strong = "background-color: #" .. Config.bgItemSel
else
strong = "border: 2px solid #" .. Config.borderSel
end
high[ v ] = false
elseif entry.lowered then
strong = "opacity:0.5"
else
strong = ""
end
if strong ~= "" then
strong = string.format( "style='%s'|", strong )
end
if entry.icon then
sign = entry.icon
if launch and not entry.lock and
sign:match( "^OOjs UI .+%.svg$" ) then
sign = facet( sign )
end
elseif launch and all.leader then
sign = "OOjs UI icon check-progressive.svg"
else
sign = false
end
if sign then
sign = string.format( "[[File:%s|%dpx|icon]]",
sign,
entry.px or Config.icon )
else
if not space then
space = string.format( "%dpx", Config.icon )
e = mw.html.create( "span" )
e:css( { ["display"] = "inline-block",
["width"] = space } )
:wikitext( " " )
space = tostring( e )
end
sign = space
end
show = fill( entry, v )
if active and entry.smart then
local s
e = mw.html.create( "span" )
if launch then
s = "#3366CC"
else
s = "#444444"
end
e:css( "color", s )
:wikitext( show )
show = string.format( "[[#%s|%s]]",
entry.smart,
tostring( e ) )
launch = false
end
if entry.style or launch then
e = mw.html.create( "span" )
if entry.style then
e:cssText( entry.style )
end
if launch then
e:css( "color", "#3366CC" )
end
e:wikitext( show )
show = tostring( e )
end
e = mw.html.create( "div" )
e:css( { ["float"] = "left",
["padding-right"] = "3px",
["white-space"] = "pre" } )
:wikitext( string.format( "%s %s", sign, show ) )
show = tostring( e )
if entry.shortcut then
if not Title then
Title = mw.title.getCurrentTitle()
end
if Title.text == Config.single then
short = "#VEshortcuts"
else
short = string.format( "%s:%s",
mw.site.namespaces[12].name,
Config.shortcut )
end
e = mw.html.create( "div" )
e:css( { ["float"] = "right",
["opacity"] = "0.5",
["margin-left"] = "0.8em",
["margin-right"] = "0.3em",
["white-space"] = "nowrap" } )
:wikitext( string.format( "[[%s|%s]]",
short,
entry.shortcut ) )
short = tostring( e )
elseif entry.iconRight then
e = mw.html.create( "div" )
e:css( { ["float"] = "right",
["margin-left"] = "0.8em",
["margin-right"] = "0.3em" } )
:wikitext( string.format( "[[File:%s|%dpx]]",
entry.iconRight,
entry.pxR or Config.icon ) )
short = tostring( e )
else
short = ""
end
r = string.format( "%s\n|-\n|%s %s %s",
r, strong, show, short )
end -- for k, v
r = r .. "\n|}"
if aim then
show = false
for k, v in pairs( e ) do
if high[ v ] then
if show then
show = string.format( "%s+%s", show, k )
else
show = k
end
end
end -- for k, v
if show then
r = r .. fault( "dropdown: Auswahl fehlt: " .. show )
end
end
else
r = fault( "dropdown: Keine .entries" )
end
return r
end -- Widgets.dropdown2()
Widgets.progressive = function ( about, adjust )
local e = mw.html.create( "span" )
local size = "1em"
local r
if adjust.div or adjust.mini then
size = "0.8em"
e:css( { ["border-radius"] = "0",
["font-size"] = "75%" } )
end
e:addClass( "mw-ui-button mw-ui-progressive" )
:css( { ["color"] = "#FFFFFF",
["line-height"] = size,
["min-width"] = "none" } )
:wikitext( about )
r = tostring( e )
if Config.tstyleUI then
r = Frame:extensionTag( "templatestyles",
nil,
{ src = Config.tstyleUI } )
.. r
end
return r
end -- Widgets.progressive()
Widgets.toolbar = function ( ahead, after )
local div = { div = true,
["line-height"] = "1em" }
local element = mw.html.create( "div" )
local entries = factory( Tree.TOOLBAR.entries, true )
local n = #entries
local surround = "1px solid #" .. Config.borderBar
local entry, s
element:css( { ["background"] = "#FFFFFF",
["border"] = surround,
["float"] = "left",
["margin"] = "0" } )
if ahead >= 1 and after >= 1 then
element:css( { ["width"] = "100%" } )
end
if after > 0 then
local rechts = mw.html.create( "div" )
rechts:css( { ["float"] = "right",
["margin-left"] = "1em",
["white-space"] = "nowrap" } )
if ahead > 0 then
rechts:css( { ["border-left"] = surround } )
end
for i = 5, n do
s = entries[ i ]
entry = Tree[ s ]
if entry.rechts then
rechts:wikitext( Widgets.toolItem( s, div ) )
end
end -- for i
element:wikitext( tostring( rechts ) )
end
if ahead > 0 then
for i = 1, n do
s = entries[ i ]
entry = Tree[ s ]
if entry.links and ahead >= entry.links then
element:wikitext( Widgets.toolItem( s, div ) )
end
end -- for i
end
entry = mw.html.create( "div" )
entry:css( { ["clear"] = "both" } )
element:wikitext( tostring( entry ) )
return tostring( element )
end -- Widgets.toolbar()
Widgets.toolItem = function ( access, adjust )
local details = factory( fetch( access ), false )
local element, low, r, shift, show, smart
if adjust then
for k, v in pairs( adjust ) do
details[ k ] = v
end -- for k, v
end
low = ( details.border or details.menu ~= 2 )
and not details.div
if low then
element = "span"
else
element = "div"
end
element = mw.html.create( element )
if details.border and details.icon then
show = ""
else
show = fill( details, access )
if not low then
local height = adjust["line-height"]
element:css( { ["float"] = "left" } )
if height then
element:css( { ["line-height"] = height } )
end
end
if not Title then
Title = mw.title.getCurrentTitle()
end
if Title.text == Config.single then
if details.swift then
shift = "#" .. details.swift
end
elseif details.start then
shift = string.format( "%s:%s",
mw.site.namespaces[12].name,
details.start )
if shift == Title.prefixedText then
shift = false
end
end
if details.progressive then
show = Widgets.progressive( show, details )
end
if shift then
show = string.format( "[[%s|%s]]", shift, show )
end
end
if details.smart then
smart = details.smart
if details.shortcut then
smart = string.format( "%s %s %s",
smart,
mw.ustring.char( 8211 ),
details.shortcut )
end
elseif details.shortcut then
smart = details.shortcut
end
element:css( { ["white-space"] = "nowrap" } )
if not details.progressive then
local graphics = details.icon or details.before
if details.border then
element:css( { ["border"] = "1px solid #"
.. Config.borderBar,
["padding"] = "2px 5px" } )
else
element:css( { ["padding"] = "0 5px" } )
if type( details.borderR ) ~= "boolean" then
details.borderR = true
end
if details.background then
element:css( { ["background"] = details.background } )
end
if details.borderR then
element:css( { ["border-right"] = "1px solid #"
.. Config.borderBar } )
end
end
if graphics then
local k, s
if type( graphics ) == "table" then
details.px = graphics.px
details.top = graphics.top
graphics = graphics.img or "example.svg"
else
show = ""
end
if type( details.px ) == "number" then
k = details.px
else
k = Config.mainPX
end
-- if details.align == "right" then
-- s = "|right"
-- end
if details.top then
s = "|top"
end
show = string.format( "[[File:%s|%dpx%s|link=%s|%s]]%s",
graphics,
k,
s or "",
shift or "",
smart or "icon",
show )
end
if details.div and not details.icon then
element:css( { ["padding-bottom"] = "3px",
["padding-top"] = "2px" } )
end
if details.entries and not details.less then
show = string.format( "%s [[File:%s|%dpx|link=|%s]]",
show,
Config.openDown.src,
Config.openDown.px,
smart or "Dropdown-Menü" )
end
end
if smart then
element:attr( "title", smart )
end
element:wikitext( show )
if details.name then
show = fill( details, access )
if math.abs( details.name ) > 1 then
show = string.format( "'''%s'''", show )
end
if details.name > 0 then
r = string.format( "%s %s", tostring( element ), show )
else
r = string.format( "%s %s", show, tostring( element ) )
end
else
r = tostring( element )
end
return r
end -- Widgets.toolItem()
Tree = factory( Data.tree )
HelpVisualEditor.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version or "wikidata",
-- or false
-- Postcondition:
-- Returns string with appropriate version, or false
local since = atleast
local r
if since == "wikidata" then
local item = HelpVisualEditor.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 vsn = entity: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 <= HelpVisualEditor.serial then
r = HelpVisualEditor.serial
else
r = false
end
end
return r
end -- HelpVisualEditor.failsafe()
-- Export
local p = { }
p.dropdown = function ( frame )
-- Tropfrunter
local params = frame:getParent().args
local scope = flat( params[ 1 ] )
local r
if scope then
local path = fetch( scope )
if path then
local leader = not faculty( params.nohead )
or faculty( params.head )
local link = faculty( params.link )
local widget = string.format( "dropdown%d",
math.abs( path.menu ) )
Frame = frame
if leader and params.head and
params.head:match( "^%d+%l+$" ) then
leader = params.head
end
r = Widgets[ widget ]( path,
scope,
flat( params[ 2 ] ),
leader,
link,
flat( params.float ) )
else
r = fault( "dropdown * Menü unbekannt: " .. scope )
end
else
r = fault( "dropdown: Kein Menü" )
end
return r
end -- p.dropdown()
p.headline = function ( frame )
-- Dynamische Überschrift
local pages = { }
local params = frame:getParent().args
local parts = { }
local e, m, s, show
Title = mw.title.getCurrentTitle()
for k, v in pairs( params ) do
s = type( k )
if s == "number" then
if k == 1 then
if v:match( "^%s*[1-6]%s*$" ) then
m = tonumber( v )
else
show = fault( "h-Zahl ungültig:" .. v )
end
elseif k == 2 and not show then
v = mw.text.trim( v )
if v ~= "" then
show = v
end
end
elseif s == "string" then
if k == "Gesamt" then
k = Config.single
end
if k:find( "/", 2, true ) then
pages[ k:gsub( "^%./", "" ) ] = v
elseif k:sub( 1, 5 ) == "Anker" then
if v ~= "" then
table.insert( parts, v )
end
end
end
end -- for k, v
if not m then
m = 2
end
if not pages[ Config.single ] then
pages[ Config.single ] = tostring( m + 1 )
end
if Title.namespace == 12 then
s = pages[ Title.text ]
if s then
if s:match( "^[1-6]$" ) then
m = tonumber( s )
else
show = fault( "h-Zahl ungültig:" .. s )
end
end
end
if not show then
show = fault( "Überschrift fehlt" )
end
e = mw.html.create( string.format( "h%d", m ) )
m = table.maxn( parts )
if m > 0 then
e:attr( "id", mw.uri.anchorEncode( parts[ 1 ] ) )
if m > 1 then
local el
for i = 2, m do
el = mw.html.create( "span" )
el:attr( "id", mw.uri.anchorEncode( parts[ i ] ) )
show = tostring( el ) .. show
end -- for i
end
end
e:wikitext( show )
return tostring( e )
end -- p.headline()
p.icon = function ( frame )
-- Icon per ID
local params = frame:getParent().args
local sketch = flat( params[ 1 ] )
local r
if sketch then
local entry = Tree[ sketch ]
if entry then
r = entry.icon
if r then
local icon = flat( params[ 2 ] )
if icon then
icon = tonumber( icon ) or 1
else
icon = Config.icon
end
if icon > 7 then
r = string.format( "[[File:%s|%dpx|icon]]",
r, icon )
else
r = fault( "icon * zu klein: " .. tostring( icon ) )
end
else
r = fault( "icon * unbebildert: " .. sketch )
end
else
r = fault( "icon * unbekannt: " .. sketch )
end
else
r = fault( "icon: Keine ID" )
end
return r
end -- p.icon()
p.progressive = function ( frame )
-- Button auf blau
local params = frame:getParent().args
Frame = frame
return Widgets.progressive( params[ 1 ] or "??????????????",
{ mini = faculty( params.mini ) } )
end -- p.progressive()
p.toolbar = function ( frame )
-- Hauptmenü
local params = frame:getParent().args
local links = flat( params.links ) or 1
local rechts = flat( params.rechts ) or 1
local r
if links == "½" then
links = 0.5
elseif links == "¾" then
links = 0.75
elseif links == mw.ustring.char( 8540 ) then -- 3/8
links = 0.375
else
links = tonumber( links ) or 0
end
rechts = tonumber( rechts ) or 0
if links > 0 or rechts > 0 then
Frame = frame
r = Widgets.toolbar( links, rechts )
else
r = fault( "toolbar: links und rechts 0" )
end
return r
end -- p.toolbar()
p.toolitem = function ( frame )
-- Hauptmenü-Element
local params = frame:getParent().args
local scope = flat( params[ 1 ] )
local r
if scope then
local branch = Tree[ scope ]
if branch then
local name = params.name
local pars = { }
if branch.menu == 2 then
pars.border = true
else
pars.borderR = false
end
if name and name:match( "^[-+]?[12]$" ) then
pars.name = tonumber( name )
end
Frame = frame
r = Widgets.toolItem( scope, pars )
else
r = fault( "toolitem * Item unbekannt: " .. scope )
end
else
r = fault( "toolitem: Kein Item" )
end
return r
end -- p.toolitem()
p.failsafe = function ( frame )
-- Check or retrieve version information
-- Precondition:
-- frame -- object; #invoke environment
-- Postcondition:
-- Return string with error message or ""
-- Uses:
-- HelpVisualEditor.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 HelpVisualEditor.failsafe( since ) or ""
end -- p.failsafe()
p.HelpVisualEditor = function ()
-- Module interface
return HelpVisualEditor
end
return p