Modul:Vorlage:Phab: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
wp>Mabschaaf K (Schützte „Modul:Vorlage:Phab“: Häufig eingebundenes Modul ([Bearbeiten=Nur angemeldete, nicht neue Benutzer] (unbeschränkt) [Verschieben=Nur Administratoren] (unbeschränkt))) |
K (15 Versionen importiert: Lua) |
||
(17 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
--[=[ | local Serial = "2018-07-15" | ||
--[=[ | |||
{{Template:Phab}} | {{Template:Phab}} | ||
]=] | ]=] | ||
-- local globals | |||
local Sick = "Category:Wikipedia:Vorlagenfehler/Vorlage:Phab" | |||
local Site = "https://phabricator.wikimedia.org/" | |||
Zeile 27: | Zeile 34: | ||
-- Precondition: | -- Precondition: | ||
-- args -- table; assignments | -- args -- table; assignments | ||
-- .File | |||
-- .Show | |||
-- .style | |||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with bracketed external link, if fine | -- Returns string with bracketed external link, if fine | ||
-- Throws error on failure | -- Throws error on failure | ||
local r = args. | local r = args.File | ||
local j = r:find( ",", 1, true ) | local j = r:find( ",", 1, true ) | ||
local n, params, show | local n, params, show | ||
Zeile 47: | Zeile 57: | ||
error( r, 0 ) | error( r, 0 ) | ||
end | end | ||
if args.style then | |||
if | if args.Show then | ||
show = args.Show | |||
else | |||
show = string.format( "F%d", n ) | |||
end | |||
show = string.format( "<span style='%s'>%s</span>", | |||
args.style, show ) | |||
end | |||
if show then | |||
r = string.format( "[[phab:F%d|%s]]", n, show ) | |||
else | else | ||
r = string.format( "[[phab:F%d]]", n ) | |||
end | end | ||
return r | return r | ||
end -- file() | end -- file() | ||
Zeile 89: | Zeile 106: | ||
r = r .. "/" .. mw.uri.encode( assembly ) .. "/" .. adopt | r = r .. "/" .. mw.uri.encode( assembly ) .. "/" .. adopt | ||
if attach then | if attach then | ||
r = r .. "/" .. mw.uri.encode( attach ) | r = r .. "/" .. mw.uri.encode( attach, "PATH" ) | ||
end | end | ||
if anchor then | if anchor then | ||
Zeile 121: | Zeile 138: | ||
-- Return table with sequence of matching elements, or false | -- Return table with sequence of matching elements, or false | ||
local r = { } | local r = { } | ||
local i | local i | ||
for k, v in pairs( args ) do | for k, v in pairs( args ) do | ||
for i = 1, #alone do | for i = 1, #alone do | ||
Zeile 166: | Zeile 183: | ||
-- Precondition: | -- Precondition: | ||
-- args -- table; assignments | -- args -- table; assignments | ||
-- .Mock | |||
-- .Show | |||
-- .style | |||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with bracketed external link, if fine | -- Returns string with bracketed external link, if fine | ||
-- Throws error on failure | -- Throws error on failure | ||
local r = args. | local r = args.Mock | ||
local n = r:match( "^[Mm]?([0-9]+)$" ) | local n = r:match( "^[Mm]?([0-9]+)$" ) | ||
local show | local show | ||
Zeile 178: | Zeile 198: | ||
error( r, 0 ) | error( r, 0 ) | ||
end | end | ||
if args.style then | |||
if | if args.Show then | ||
show = args.Show | |||
else | |||
show = string.format( "M%d", n ) | |||
end | |||
show = string.format( "<span style='%s'>%s</span>", | |||
args.style, show ) | |||
end | |||
if show then | |||
r = string.format( "[[phab:M%d|%s]]", n, show ) | |||
else | else | ||
r = string.format( "[[phab:M%d]]", n ) | |||
end | end | ||
return r | return r | ||
end -- mock() | end -- mock() | ||
Zeile 190: | Zeile 217: | ||
local function sourcing( args ) | local function phabAssigned( frame ) | ||
-- Retrieve table with callsign assignments | |||
-- Precondition: | |||
-- frame -- object or nil | |||
-- Postcondition: | |||
-- Return table or nil | |||
-- Throws error on failure | |||
-- Uses: | |||
-- mw.getCurrentFrame() | |||
-- mw.loadData() | |||
local got, lucky, r, s | |||
if not frame then | |||
frame = mw.getCurrentFrame() | |||
end | |||
s = frame:getTitle() .. "/callsigns" | |||
lucky, got = pcall( mw.loadData, s ) | |||
if type( got ) == "table" then | |||
r = got | |||
else | |||
error( "Invalid: " .. s, 0 ) | |||
end | |||
return r | |||
end -- phabAssigned() | |||
local function phabBoards( args ) | |||
-- Link to a board, project, team: tag | |||
-- Precondition: | |||
-- args -- table; assignments | |||
-- .Engage | |||
-- .Show | |||
-- .style | |||
-- string; single ID | |||
-- Postcondition: | |||
-- Returns string URL, if fine | |||
local s = type( args ) | |||
local n, r, show, tags | |||
if s == "table" then | |||
if type( args.Engage ) == "string" then | |||
tags = args.Engage | |||
end | |||
if args.Show and ( args.Show ~= "" ) then | |||
show = args.Show | |||
end | |||
elseif s == "string" then | |||
tags = args | |||
end | |||
if not tags or tags == "" then | |||
tags = "MediaWiki-General-or-Unknown" | |||
end | |||
tags = mw.text.split( tags, "%s+" ) | |||
n = #tags | |||
if show and n > 1 then | |||
show = false | |||
end | |||
for i = 1, n do | |||
s = tags[ i ] | |||
if r then | |||
r = r .. " | " | |||
else | |||
r = "" | |||
end | |||
if not show then | |||
show = "#" .. s | |||
end | |||
if args.style then | |||
show = string.format( "<span style='%s'>%s</span>", | |||
args.style, show ) | |||
end | |||
r = string.format( "%s[[phab:tag/%s|%s]]", | |||
r, s, show ) | |||
end -- for i | |||
return r | |||
end -- phabBoards() | |||
local function phabCallsigns( args, frame ) | |||
-- Create wikitable of all callsigns | |||
-- Precondition: | |||
-- args -- table; options | |||
-- frame -- object or nil | |||
-- Uses: | |||
-- phabAssigned() | |||
local connect = phabAssigned( frame ) | |||
local r | |||
if connect then | |||
local limit = ( args.callsigns == "0" ) | |||
local callsigns = { } | |||
local order = { } | |||
local sub = "phab:diffusion/" | |||
local details, pages, s, sign, support | |||
r = "{| class='wikitable sortable'\n" .. | |||
"|- class='hintergrundfarbe6'\n" .. | |||
"! Callsign !! ''repository'' !!class='unsortable'| Infos\n" | |||
for k, v in pairs( connect ) do | |||
if k:find( "/", 3, true ) then | |||
-- GIT legacy | |||
v = false | |||
elseif limit and type( v ) == "string" then | |||
details = connect[ v ] | |||
if type( details ) == "table" and | |||
type( details.list ) == "boolean" and | |||
not details.list then | |||
v = false | |||
end | |||
end | |||
if type( v ) == "string" then | |||
s = callsigns[ v ] | |||
if s then | |||
if #s < #k then | |||
callsigns[ v ] = k | |||
end | |||
else | |||
callsigns[ v ] = k | |||
table.insert( order, v ) | |||
end | |||
end | |||
end -- for k, v | |||
table.sort( order ) | |||
for i = 1, #order do | |||
sign = order[ i ] | |||
show = callsigns[ sign ] | |||
r = string.format( "%s|- id='%s'\n|[[%s%s|%s]]||%s\n", | |||
r, sign, sub, sign, sign, show ) | |||
pages = { } | |||
details = connect[ sign ] | |||
if type( details ) ~= "table" then | |||
details = { } | |||
end | |||
if details.say then | |||
table.insert( pages, details.say ) | |||
end | |||
if details.support then | |||
table.insert( pages, | |||
string.format( "[[%s]]", | |||
details.support ) ) | |||
end | |||
if type( details.tags ) == "table" then | |||
for k, v in pairs( details.tags ) do | |||
table.insert( pages, phabBoards( v ) ) | |||
end -- for k, v | |||
end | |||
support = details.mwPage | |||
if not support then | |||
s = show:match( "^extension%-([%w_]+)$" ) | |||
if s then | |||
support = "Extension:" .. s | |||
end | |||
end | |||
if support and support ~= "" then | |||
table.insert( pages, | |||
string.format( "[[mw:%s]]", support ) ) | |||
end | |||
if #pages > 0 then | |||
r = string.format( "%s|%s\n", | |||
r, table.concat( pages, "<br>" ) ) | |||
end | |||
end -- for i | |||
r = string.format( "%s|}\n%d ", | |||
r, #order ) | |||
end | |||
return r | |||
end -- phabCallsigns() | |||
local function phabDiffusion( action, assembly, adopt, attach, | |||
anchor, against, as, frame ) | |||
-- Create path for Phabricator Diffusion since 2015-03 | |||
-- Precondition: | |||
-- action -- string; kind of request | |||
-- assembly -- string; project | |||
-- adopt -- string; branch | |||
-- attach -- string; file or directory (or empty) | |||
-- anchor -- string; line number (or empty) | |||
-- against -- string; diff ./. previous ID (or empty) | |||
-- as -- string; s = query | |||
-- frame -- object or nil | |||
-- Postcondition: | |||
-- Return 1 -- URL, if identified, or nil | |||
-- 2 -- callsign, or nil | |||
-- Uses: | |||
-- phabAssigned() | |||
local translate = phabAssigned( frame ) | |||
local r, shortcut | |||
if translate then | |||
if assembly:match( "^%u%u%u?%u?$" ) then | |||
shortcut = assembly | |||
else | |||
shortcut = translate[ assembly ] | |||
if not shortcut and assembly:find( "/", 3, true ) then | |||
-- GIT legacy | |||
local s = assembly:gsub( "mediawiki/extensions/", | |||
"extension-" ) | |||
shortcut = translate[ s ] | |||
end | |||
end | |||
if shortcut then | |||
local state, sub, swift | |||
if adopt ~= "master" and adopt ~= "HEAD" then | |||
state = adopt | |||
end | |||
if attach and not state then | |||
state = "master" | |||
end | |||
if state then | |||
if action then | |||
if action == "commit" or | |||
action == "commitdiff" then | |||
if attach then | |||
if action == "commit" then | |||
swift = "browse" | |||
else | |||
swift = "change" | |||
end | |||
state = "master" | |||
else | |||
sub = string.format( "r%s%s", | |||
shortcut, state ) | |||
end | |||
elseif action == "history" then | |||
swift = action | |||
else | |||
swift = "browse" | |||
end | |||
else | |||
swift = "browse" | |||
end | |||
end | |||
if not sub then | |||
sub = "diffusion/" .. shortcut | |||
if swift then | |||
sub = string.format( "%s/%s", sub, swift ) | |||
end | |||
if state then | |||
local sep | |||
if state == "master" then | |||
sep = "/" | |||
else | |||
sep = "" | |||
end | |||
sub = string.format( "%s%s%s", sub, sep, state ) | |||
end | |||
if attach then | |||
sub = string.format( "%s/%s", sub, attach ) | |||
if adopt | |||
and adopt ~= "HEAD" | |||
and state ~= adopt then | |||
sub = string.format( "%s;%s", sub, adopt ) | |||
end | |||
if anchor then | |||
sub = string.format( "%s$%s", sub, anchor ) | |||
end | |||
end | |||
if as then | |||
sub = string.format( "%s?%s", sub, as ) | |||
end | |||
end | |||
r = Site .. sub:gsub( " ", "%%20" ) | |||
end | |||
end | |||
return r, shortcut | |||
end -- phabDiffusion() | |||
local function phabUser( args, frame ) | |||
-- Link to a user | |||
-- Precondition: | |||
-- args -- table; assignments | |||
-- .User | |||
-- .Show | |||
-- .style | |||
-- frame -- object or nil | |||
-- Postcondition: | |||
-- Returns string URL, if fine | |||
-- Uses: | |||
-- mw.text.trim() | |||
local r | |||
local single = args.User | |||
if type( single ) == "string" then | |||
single = mw.text.trim( single ) | |||
end | |||
if type( single ) == "string" and single ~= "" then | |||
local show = args.Show | |||
if not show or show == "" then | |||
show = "@" .. single | |||
end | |||
if not frame then | |||
frame = mw.getCurrentFrame() | |||
end | |||
if args.style then | |||
show = string.format( "<span style='%s'>%s</span>", | |||
args.style, show ) | |||
end | |||
r = string.format( "[[phab:p/%s|%s]]", | |||
frame:callParserFunction( "urlencode", | |||
single ), | |||
show ) | |||
else | |||
r = string.format( "Missing User :-(" ) | |||
error( r, 0 ) | |||
end | |||
return r | |||
end -- phabUser() | |||
local function sourcing( args, frame ) | |||
-- Link to a code source, directory, branch or related | -- Link to a code source, directory, branch or related | ||
-- Precondition: | -- Precondition: | ||
-- args -- table; assignments | -- args -- table; assignments | ||
-- frame -- object or nil | |||
-- Postcondition: | -- Postcondition: | ||
-- Returns string, if fine | -- Returns string, if fine | ||
Zeile 200: | Zeile 538: | ||
-- lonely() | -- lonely() | ||
-- id40() | -- id40() | ||
-- | -- phabDiffusion() | ||
-- git() | -- git() | ||
local jump = false | local jump = false | ||
local last = false | local last = false | ||
local | local query = false | ||
local scope = "mediawiki/core" | local scope = "mediawiki/core" | ||
local show | local show | ||
Zeile 211: | Zeile 549: | ||
local source = false | local source = false | ||
local swift = "dir" | local swift = "dir" | ||
local | local lapsus, load, r | ||
r = lonely( args, | r = lonely( args, | ||
{ "branch", "commit", "commitdiff", "diff" } ) | { "branch", "commit", "commitdiff", "diff" } ) | ||
Zeile 217: | Zeile 555: | ||
slot = args[ r ] | slot = args[ r ] | ||
end | end | ||
r = lonely( args, | r = lonely( args, { "dir", "file", "plain" } ) | ||
if r then | |||
swift = r | |||
source = args[ swift ] | |||
if args.file then | |||
local suffix = args.file:match( "%.(%l+)$" ) | |||
if suffix then | |||
if suffix == "svg" then | |||
query = "as=source&highlight=xml&" | |||
elseif suffix == "json" or | |||
suffix == "txt" or | |||
suffix == "xml" then | |||
query = "?" | |||
end | |||
if query then | |||
query = query .. "blame=off" | |||
end | |||
if suffix == "md" then | |||
query = "as=remarkup" | |||
end | |||
end | |||
end | |||
end | |||
r = lonely( args, { "commit", "commitdiff" } ) | |||
if r then | if r then | ||
swift = r | swift = r | ||
load = true | |||
end | end | ||
if args.history then | if args.history then | ||
Zeile 241: | Zeile 602: | ||
end | end | ||
error( r, 0 ) | error( r, 0 ) | ||
elseif args.line then | |||
if args.diff then | if args.diff then | ||
r = "No ''line'' on ''diff'' page available" | r = "No ''line'' on ''diff'' page available" | ||
Zeile 250: | Zeile 610: | ||
end | end | ||
end | end | ||
if load then | if load then | ||
id40( slot ) | if scope == "SVN" then | ||
r = "Invalid SVN identifier: " | |||
if slot:match( "^[0-9]+$" ) then | |||
slot = tonumber( slot ) | |||
if slot >= 1 and slot <= 115794 then | |||
r = false | |||
end | |||
slot = string.format( "%d", slot ) | |||
end | |||
if r then | |||
local e = r .. slot | |||
error( e, 0 ) | |||
end | |||
else | |||
id40( slot ) | |||
end | |||
elseif args.diff then | elseif args.diff then | ||
since = args.diff | since = args.diff | ||
id40( since ) | id40( since ) | ||
elseif last then | |||
swift = "history" | |||
end | end | ||
if args.title then | r, show = phabDiffusion( swift, scope, slot, source, jump, since, | ||
query, frame ) | |||
if args.title and ( args.title ~= "" ) then | |||
show = args.title | show = args.title | ||
elseif last then | elseif last and source then | ||
show = "history: " .. source | show = "history: " .. source | ||
elseif source then | elseif source then | ||
show = source | show = source | ||
if args.diff then | if args.diff then | ||
show = | show = string.format( "%s ./.%s", show, since:sub( 1, 7 ) ) | ||
elseif load then | |||
show = string.format( "%s;%s", show, slot:sub( 1, 7 ) ) | |||
end | end | ||
elseif load then | elseif load then | ||
show = "GIT:" .. slot:sub( 1, 7 ) | if show then | ||
show = "r" .. show | |||
else | |||
show = "GIT:" | |||
end | |||
show = show .. slot:sub( 1, 7 ) | |||
else | else | ||
show = scope .. "/*" | show = scope .. "/*" | ||
end | end | ||
r = git( swift, scope, slot, source, jump, since ) | if r then | ||
r = string.format( "[%s %s]", r, show ) | |||
else | |||
if not scope:find( "/", 3, true ) then | |||
error( "Unknown project: " .. scope, 0 ) | |||
end | |||
lonely( args, | |||
{ "commit", "commitdiff", "dir", "file", "plain" } ) | |||
r = git( swift, scope, slot, source, jump, since ) | |||
r = string.format( "[%s %s]", r, show ) | |||
lapsus = true | |||
end | |||
if lapsus then | |||
r = string.format( "%s[[%s/Diffusion]]", | |||
r, Sick ) | |||
end | |||
return r | |||
end -- sourcing() | end -- sourcing() | ||
Zeile 286: | Zeile 681: | ||
-- Precondition: | -- Precondition: | ||
-- args -- table; assignments | -- args -- table; assignments | ||
-- .Task | |||
-- .Anchor | |||
-- .Show | |||
-- .style | |||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with bracketed external link, if fine | -- Returns string with bracketed external link, if fine | ||
-- Throws error on failure | -- Throws error on failure | ||
local r = args.Task | local r = args.Task | ||
local j = r:find( "#", 1, true ) | local j = r:find( "#", 1, true ) | ||
local sub = args.Anchor | |||
local n, show | local n, show | ||
if j then | if j then | ||
Zeile 296: | Zeile 696: | ||
r = r:sub( 1, j - 1 ) | r = r:sub( 1, j - 1 ) | ||
scroll = scroll:match( "^([0-9]+)$" ) | scroll = scroll:match( "^([0-9]+)$" ) | ||
if scroll and not | if scroll and not sub then | ||
sub = scroll | |||
end | end | ||
end | end | ||
Zeile 307: | Zeile 707: | ||
error( r, 0 ) | error( r, 0 ) | ||
end | end | ||
if sub then | |||
if | sub = string.format( "#anchor-%s", sub ) | ||
else | |||
sub = "" | |||
end | end | ||
if args.Show then | if args.Show then | ||
Zeile 319: | Zeile 720: | ||
end | end | ||
end | end | ||
r = string.format( "[%s %s]", | if args.style then | ||
show = string.format( "<span style='%s'>%s</span>", | |||
args.style, show ) | |||
end | |||
r = string.format( "[[phab:T%d%s|%s]]", n, sub, show ) | |||
return r | return r | ||
end -- task() | end -- task() | ||
Zeile 348: | Zeile 753: | ||
if n then | if n then | ||
n = tonumber( n ) -- discard leading zeros | n = tonumber( n ) -- discard leading zeros | ||
if n < | if n <= 73681 then | ||
args.Task = tostring( n + 2000 ) | args.Task = tostring( n + 2000 ) | ||
else | else | ||
Zeile 366: | Zeile 771: | ||
end | end | ||
r = string.format( "[%s %s]", r, show ) | r = string.format( "[%s %s]", r, show ) | ||
r = string.format( "%s %s", task( args ), r ) | r = string.format( "%s <small style=\"font-weight:normal\">(%s)</small>", | ||
task( args ), r ) | |||
return r | return r | ||
end -- taskBugzilla() | end -- taskBugzilla() | ||
Zeile 372: | Zeile 778: | ||
local function unified( args ) | local function unified( args, frame ) | ||
-- Link to a management issue | -- Link to a management issue | ||
-- Precondition: | -- Precondition: | ||
Zeile 383: | Zeile 789: | ||
-- taskBugzilla() | -- taskBugzilla() | ||
-- task() | -- task() | ||
-- phabBoards() | |||
-- phabUser() | |||
local r | local r | ||
lonely( args, | lonely( args, | ||
{ "Bugzilla", "Countdown", "Differential", "File", "Gerrit", | { "Bugzilla", "Countdown", "Differential", "Engage", | ||
"File", "Gerrit", "Join", "Mock", "Paste", "Review", | |||
"Task", "User" } ) | |||
if args.Bugzilla then | if args.Bugzilla then | ||
r = taskBugzilla( args ) | r = taskBugzilla( args ) | ||
elseif args.Engage then | |||
r = phabBoards( args ) | |||
elseif args.File then | elseif args.File then | ||
r = file( args ) | r = file( args ) | ||
Zeile 395: | Zeile 806: | ||
elseif args.Task then | elseif args.Task then | ||
r = task( args ) | r = task( args ) | ||
elseif args.User then | |||
r = phabUser( args, frame ) | |||
else | else | ||
r = "NOT YET READY" | r = "NOT YET READY" | ||
Zeile 405: | Zeile 818: | ||
-- Paste | -- Paste | ||
-- Review | -- Review | ||
-- Leerzeichen-getrennte Liste | |||
return r | return r | ||
end -- unified() | end -- unified() | ||
Zeile 410: | Zeile 824: | ||
local function main( args ) | local function main( args, frame ) | ||
-- Do the job | -- Do the job | ||
-- Precondition: | -- Precondition: | ||
-- args -- table; assignments | -- args -- table; assignments | ||
-- frame -- object or nil | |||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with link, if fine | -- Returns string with link, if fine | ||
Zeile 420: | Zeile 835: | ||
-- unified() | -- unified() | ||
-- sourcing() | -- sourcing() | ||
local defaults = { Bugzilla = "", | |||
Engage = true, | |||
User = true } | |||
local got = { } | local got = { } | ||
local mode = 0 | local mode = 0 | ||
local params = { Anchor = 1, | local params = { style = 0, | ||
Anchor = 1, | |||
Anchor = 1, | |||
Bugzilla = 1, | Bugzilla = 1, | ||
Countdown = 1, | Countdown = 1, | ||
Differential = 1, | Differential = 1, | ||
Engage = 1, | |||
File = 1, | File = 1, | ||
-- Gerrit = 1, | -- Gerrit = 1, | ||
Zeile 434: | Zeile 855: | ||
Show = 1, | Show = 1, | ||
Task = 1, | Task = 1, | ||
User = 1, | |||
branch = 2, | branch = 2, | ||
commit = 2, | commit = 2, | ||
Zeile 444: | Zeile 866: | ||
plain = 2, | plain = 2, | ||
project = 2, | project = 2, | ||
title = 2 } | title = 2, | ||
local | callsigns = 3 } | ||
local gr, s | |||
for k, v in pairs( args ) do | for k, v in pairs( args ) do | ||
mode = params[ k ] | mode = params[ k ] | ||
Zeile 458: | Zeile 881: | ||
r = got[ -1 ] | r = got[ -1 ] | ||
if r then | if r then | ||
if #r == 1 then | if #r == 1 then | ||
s = "" | s = "" | ||
Zeile 473: | Zeile 895: | ||
error( r, 0 ) | error( r, 0 ) | ||
else | else | ||
local procs = { unified, sourcing } | local procs = { unified, sourcing, phabCallsigns } | ||
if mode == 0 then | if mode == 0 then | ||
mode = 2 | mode = 2 | ||
got[ 2 ] = { } | got[ 2 ] = { } | ||
end | |||
if got[ 0 ] then | |||
for k, v in pairs( got[ 0 ] ) do | |||
got[ mode ][ k ] = v | |||
end -- for k, v | |||
end | end | ||
got = got[ mode ] | got = got[ mode ] | ||
for k, v in pairs( got ) do | for k, v in pairs( got ) do | ||
if v | s = type( v ) | ||
if s == "number" then | |||
v = tostring( v ) | |||
elseif s == "string" then | |||
if #v == 0 then | |||
v = defaults[ k ] | |||
end | |||
elseif v == true then | |||
v = defaults[ k ] | |||
else | |||
v = nil | |||
end | |||
if v then | |||
got[ k ] = v | |||
else | |||
got[ k ] = nil | got[ k ] = nil | ||
end | end | ||
end -- for k, v | end -- for k, v | ||
r = procs[ mode ]( got ) | r = procs[ mode ]( got, frame ) | ||
end | end | ||
return r | return r | ||
Zeile 500: | Zeile 941: | ||
function p.f( frame ) | function p.f( frame ) | ||
local lucky, r = pcall( main, frame:getParent().args ) | local lucky, r = pcall( main, frame:getParent().args, frame ) | ||
if not lucky then | if not lucky then | ||
r = string.format( "<span class=\"error\">%s</span>", r ) | r = string.format( "<span class=\"error\">%s</span>[[%s]]", | ||
r, Sick ) | |||
end | end | ||
return r | return r | ||
end | |||
function p.failsafe() | |||
return Serial | |||
end | end | ||
return p | return p |
Aktuelle Version vom 27. Juli 2018, 21:51 Uhr
Modul:Vorlage:LuaModuleDoc:142: attempt to index field 'wikibase' (a nil value)
local Serial = "2018-07-15"
--[=[
{{Template:Phab}}
]=]
-- local globals
local Sick = "Category:Wikipedia:Vorlagenfehler/Vorlage:Phab"
local Site = "https://phabricator.wikimedia.org/"
local function concatKeys( args )
-- Concatenate keys
-- Precondition:
-- args -- table; assignments
local r
for k in pairs( args ) do
if r then
r = r .. " "
else
r = ""
end
r = r .. tostring( k )
end -- for k
return r
end -- concatKeys()
local function file( args )
-- Link to a File
-- Precondition:
-- args -- table; assignments
-- .File
-- .Show
-- .style
-- Postcondition:
-- Returns string with bracketed external link, if fine
-- Throws error on failure
local r = args.File
local j = r:find( ",", 1, true )
local n, params, show
if j then
params = r:sub( j + 1 )
r = r:sub( 1, j - 1 )
-- params = mw.text.split( split, "%s*,%s*" )
-- , width=, height=, size=
-- , layout, float, alt
end
n = r:match( "^[Ff]?([0-9]+)%s*$" )
if n then
n = tonumber( n ) -- discard leading zeros
else
r = string.format( "Invalid format: 'File=%s'", r )
error( r, 0 )
end
if args.style then
if args.Show then
show = args.Show
else
show = string.format( "F%d", n )
end
show = string.format( "<span style='%s'>%s</span>",
args.style, show )
end
if show then
r = string.format( "[[phab:F%d|%s]]", n, show )
else
r = string.format( "[[phab:F%d]]", n )
end
return r
end -- file()
local function git( action, assembly, adopt, attach, anchor, against )
-- Create URL for mediawiki GIT since 2013-06-06
-- Precondition:
-- action -- string; kind of request
-- assembly -- string; project
-- adopt -- string; branch
-- attach -- string; file or directory (or empty)
-- anchor -- string; line number (or empty)
-- against -- string; diff ./. previous ID (or empty)
-- Postcondition:
-- Return URL
-- Uses:
-- mw.uri.encode()
local r = "https://git.wikimedia.org/"
if action == "file" then
r = r .. "blob"
if against then
r = r .. "diff"
end
elseif action == "dir" then
r = r .. "tree"
elseif action == "plain" then
r = r .. "raw"
elseif action == "commit" or
action == "commitdiff" or
action == "history" then
r = r .. action
end
r = r .. "/" .. mw.uri.encode( assembly ) .. "/" .. adopt
if attach then
r = r .. "/" .. mw.uri.encode( attach, "PATH" )
end
if anchor then
r = r .. "#L" .. anchor
end
return r
end -- git()
local function id40( ask )
-- Check for 40 hex lowercase id
-- Precondition:
-- ask -- string; project
-- Postcondition:
-- Throws error, if failed
if #ask ~= 40 or ask:match( "^[0-9a-f]+$" ) ~= ask then
local e = "Invalid identifier: " .. ask
error( e, 0 )
end
end -- id40()
local function intersect( args, alone )
-- Find elements occurring in both args and alone
-- Precondition:
-- args -- table; assignments
-- alone -- table (sequence)
-- Postcondition:
-- Return table with sequence of matching elements, or false
local r = { }
local i
for k, v in pairs( args ) do
for i = 1, #alone do
if k == alone[ i ] then
table.insert( r, k )
end
end -- for i
end -- for k, v
if #r == 0 then
r = false
end
return r
end -- intersect()
local function lonely( args, alone )
-- Find elements occurring in both args and alone
-- Precondition:
-- args -- table; assignments
-- alone -- table (sequence)
-- Postcondition:
-- Throws error, if occurring in both
-- Return single matching element, or false
-- Uses:
-- intersect()
-- mw.text.listToText()
local r = intersect( args, alone )
if r then
if #r > 1 then
r = "Must not be used together: ''"
.. mw.text.listToText( r, ", ", " " ) .. "''"
error( r, 0 )
end
r = r[ 1 ]
end
return r
end -- lonely()
local function mock( args )
-- Link to a Mock
-- Precondition:
-- args -- table; assignments
-- .Mock
-- .Show
-- .style
-- Postcondition:
-- Returns string with bracketed external link, if fine
-- Throws error on failure
local r = args.Mock
local n = r:match( "^[Mm]?([0-9]+)$" )
local show
if n then
n = tonumber( n ) -- discard leading zeros
else
r = string.format( "Invalid format: 'Mock=%s'", r )
error( r, 0 )
end
if args.style then
if args.Show then
show = args.Show
else
show = string.format( "M%d", n )
end
show = string.format( "<span style='%s'>%s</span>",
args.style, show )
end
if show then
r = string.format( "[[phab:M%d|%s]]", n, show )
else
r = string.format( "[[phab:M%d]]", n )
end
return r
end -- mock()
local function phabAssigned( frame )
-- Retrieve table with callsign assignments
-- Precondition:
-- frame -- object or nil
-- Postcondition:
-- Return table or nil
-- Throws error on failure
-- Uses:
-- mw.getCurrentFrame()
-- mw.loadData()
local got, lucky, r, s
if not frame then
frame = mw.getCurrentFrame()
end
s = frame:getTitle() .. "/callsigns"
lucky, got = pcall( mw.loadData, s )
if type( got ) == "table" then
r = got
else
error( "Invalid: " .. s, 0 )
end
return r
end -- phabAssigned()
local function phabBoards( args )
-- Link to a board, project, team: tag
-- Precondition:
-- args -- table; assignments
-- .Engage
-- .Show
-- .style
-- string; single ID
-- Postcondition:
-- Returns string URL, if fine
local s = type( args )
local n, r, show, tags
if s == "table" then
if type( args.Engage ) == "string" then
tags = args.Engage
end
if args.Show and ( args.Show ~= "" ) then
show = args.Show
end
elseif s == "string" then
tags = args
end
if not tags or tags == "" then
tags = "MediaWiki-General-or-Unknown"
end
tags = mw.text.split( tags, "%s+" )
n = #tags
if show and n > 1 then
show = false
end
for i = 1, n do
s = tags[ i ]
if r then
r = r .. " | "
else
r = ""
end
if not show then
show = "#" .. s
end
if args.style then
show = string.format( "<span style='%s'>%s</span>",
args.style, show )
end
r = string.format( "%s[[phab:tag/%s|%s]]",
r, s, show )
end -- for i
return r
end -- phabBoards()
local function phabCallsigns( args, frame )
-- Create wikitable of all callsigns
-- Precondition:
-- args -- table; options
-- frame -- object or nil
-- Uses:
-- phabAssigned()
local connect = phabAssigned( frame )
local r
if connect then
local limit = ( args.callsigns == "0" )
local callsigns = { }
local order = { }
local sub = "phab:diffusion/"
local details, pages, s, sign, support
r = "{| class='wikitable sortable'\n" ..
"|- class='hintergrundfarbe6'\n" ..
"! Callsign !! ''repository'' !!class='unsortable'| Infos\n"
for k, v in pairs( connect ) do
if k:find( "/", 3, true ) then
-- GIT legacy
v = false
elseif limit and type( v ) == "string" then
details = connect[ v ]
if type( details ) == "table" and
type( details.list ) == "boolean" and
not details.list then
v = false
end
end
if type( v ) == "string" then
s = callsigns[ v ]
if s then
if #s < #k then
callsigns[ v ] = k
end
else
callsigns[ v ] = k
table.insert( order, v )
end
end
end -- for k, v
table.sort( order )
for i = 1, #order do
sign = order[ i ]
show = callsigns[ sign ]
r = string.format( "%s|- id='%s'\n|[[%s%s|%s]]||%s\n",
r, sign, sub, sign, sign, show )
pages = { }
details = connect[ sign ]
if type( details ) ~= "table" then
details = { }
end
if details.say then
table.insert( pages, details.say )
end
if details.support then
table.insert( pages,
string.format( "[[%s]]",
details.support ) )
end
if type( details.tags ) == "table" then
for k, v in pairs( details.tags ) do
table.insert( pages, phabBoards( v ) )
end -- for k, v
end
support = details.mwPage
if not support then
s = show:match( "^extension%-([%w_]+)$" )
if s then
support = "Extension:" .. s
end
end
if support and support ~= "" then
table.insert( pages,
string.format( "[[mw:%s]]", support ) )
end
if #pages > 0 then
r = string.format( "%s|%s\n",
r, table.concat( pages, "<br>" ) )
end
end -- for i
r = string.format( "%s|}\n%d ",
r, #order )
end
return r
end -- phabCallsigns()
local function phabDiffusion( action, assembly, adopt, attach,
anchor, against, as, frame )
-- Create path for Phabricator Diffusion since 2015-03
-- Precondition:
-- action -- string; kind of request
-- assembly -- string; project
-- adopt -- string; branch
-- attach -- string; file or directory (or empty)
-- anchor -- string; line number (or empty)
-- against -- string; diff ./. previous ID (or empty)
-- as -- string; s = query
-- frame -- object or nil
-- Postcondition:
-- Return 1 -- URL, if identified, or nil
-- 2 -- callsign, or nil
-- Uses:
-- phabAssigned()
local translate = phabAssigned( frame )
local r, shortcut
if translate then
if assembly:match( "^%u%u%u?%u?$" ) then
shortcut = assembly
else
shortcut = translate[ assembly ]
if not shortcut and assembly:find( "/", 3, true ) then
-- GIT legacy
local s = assembly:gsub( "mediawiki/extensions/",
"extension-" )
shortcut = translate[ s ]
end
end
if shortcut then
local state, sub, swift
if adopt ~= "master" and adopt ~= "HEAD" then
state = adopt
end
if attach and not state then
state = "master"
end
if state then
if action then
if action == "commit" or
action == "commitdiff" then
if attach then
if action == "commit" then
swift = "browse"
else
swift = "change"
end
state = "master"
else
sub = string.format( "r%s%s",
shortcut, state )
end
elseif action == "history" then
swift = action
else
swift = "browse"
end
else
swift = "browse"
end
end
if not sub then
sub = "diffusion/" .. shortcut
if swift then
sub = string.format( "%s/%s", sub, swift )
end
if state then
local sep
if state == "master" then
sep = "/"
else
sep = ""
end
sub = string.format( "%s%s%s", sub, sep, state )
end
if attach then
sub = string.format( "%s/%s", sub, attach )
if adopt
and adopt ~= "HEAD"
and state ~= adopt then
sub = string.format( "%s;%s", sub, adopt )
end
if anchor then
sub = string.format( "%s$%s", sub, anchor )
end
end
if as then
sub = string.format( "%s?%s", sub, as )
end
end
r = Site .. sub:gsub( " ", "%%20" )
end
end
return r, shortcut
end -- phabDiffusion()
local function phabUser( args, frame )
-- Link to a user
-- Precondition:
-- args -- table; assignments
-- .User
-- .Show
-- .style
-- frame -- object or nil
-- Postcondition:
-- Returns string URL, if fine
-- Uses:
-- mw.text.trim()
local r
local single = args.User
if type( single ) == "string" then
single = mw.text.trim( single )
end
if type( single ) == "string" and single ~= "" then
local show = args.Show
if not show or show == "" then
show = "@" .. single
end
if not frame then
frame = mw.getCurrentFrame()
end
if args.style then
show = string.format( "<span style='%s'>%s</span>",
args.style, show )
end
r = string.format( "[[phab:p/%s|%s]]",
frame:callParserFunction( "urlencode",
single ),
show )
else
r = string.format( "Missing User :-(" )
error( r, 0 )
end
return r
end -- phabUser()
local function sourcing( args, frame )
-- Link to a code source, directory, branch or related
-- Precondition:
-- args -- table; assignments
-- frame -- object or nil
-- Postcondition:
-- Returns string, if fine
-- Throws error on failure
-- Uses:
-- lonely()
-- id40()
-- phabDiffusion()
-- git()
local jump = false
local last = false
local query = false
local scope = "mediawiki/core"
local show
local since = false
local slot = "HEAD"
local source = false
local swift = "dir"
local lapsus, load, r
r = lonely( args,
{ "branch", "commit", "commitdiff", "diff" } )
if r then
slot = args[ r ]
end
r = lonely( args, { "dir", "file", "plain" } )
if r then
swift = r
source = args[ swift ]
if args.file then
local suffix = args.file:match( "%.(%l+)$" )
if suffix then
if suffix == "svg" then
query = "as=source&highlight=xml&"
elseif suffix == "json" or
suffix == "txt" or
suffix == "xml" then
query = "?"
end
if query then
query = query .. "blame=off"
end
if suffix == "md" then
query = "as=remarkup"
end
end
end
end
r = lonely( args, { "commit", "commitdiff" } )
if r then
swift = r
load = true
end
if args.history then
last = true
end
if args.project then
scope = args.project
end
if args.line or args.diff then
if not args.file then
r = " valid for ''file'' only."
if args.line then
r = "Number ''line''" .. r
if args.diff then
r = " / " .. r
end
end
if args.diff then
r = "Version ''diff''" .. r
end
error( r, 0 )
elseif args.line then
if args.diff then
r = "No ''line'' on ''diff'' page available"
error( r, 0 )
end
jump = args.line
end
end
if load then
if scope == "SVN" then
r = "Invalid SVN identifier: "
if slot:match( "^[0-9]+$" ) then
slot = tonumber( slot )
if slot >= 1 and slot <= 115794 then
r = false
end
slot = string.format( "%d", slot )
end
if r then
local e = r .. slot
error( e, 0 )
end
else
id40( slot )
end
elseif args.diff then
since = args.diff
id40( since )
elseif last then
swift = "history"
end
r, show = phabDiffusion( swift, scope, slot, source, jump, since,
query, frame )
if args.title and ( args.title ~= "" ) then
show = args.title
elseif last and source then
show = "history: " .. source
elseif source then
show = source
if args.diff then
show = string.format( "%s ./.%s", show, since:sub( 1, 7 ) )
elseif load then
show = string.format( "%s;%s", show, slot:sub( 1, 7 ) )
end
elseif load then
if show then
show = "r" .. show
else
show = "GIT:"
end
show = show .. slot:sub( 1, 7 )
else
show = scope .. "/*"
end
if r then
r = string.format( "[%s %s]", r, show )
else
if not scope:find( "/", 3, true ) then
error( "Unknown project: " .. scope, 0 )
end
lonely( args,
{ "commit", "commitdiff", "dir", "file", "plain" } )
r = git( swift, scope, slot, source, jump, since )
r = string.format( "[%s %s]", r, show )
lapsus = true
end
if lapsus then
r = string.format( "%s[[%s/Diffusion]]",
r, Sick )
end
return r
end -- sourcing()
local function task( args )
-- Link to a Task
-- Precondition:
-- args -- table; assignments
-- .Task
-- .Anchor
-- .Show
-- .style
-- Postcondition:
-- Returns string with bracketed external link, if fine
-- Throws error on failure
local r = args.Task
local j = r:find( "#", 1, true )
local sub = args.Anchor
local n, show
if j then
local scroll = r:sub( j + 1 )
r = r:sub( 1, j - 1 )
scroll = scroll:match( "^([0-9]+)$" )
if scroll and not sub then
sub = scroll
end
end
n = r:match( "^[Tt]?([0-9]+)%s*$" )
if n then
n = tonumber( n ) -- discard leading zeros
else
r = string.format( "Invalid format: 'Task=%s'", r )
error( r, 0 )
end
if sub then
sub = string.format( "#anchor-%s", sub )
else
sub = ""
end
if args.Show then
show = args.Show
else
show = string.format( "phab:T%d", n )
if args.Anchor then
show = string.format( "%s #%s", show, args.Anchor )
end
end
if args.style then
show = string.format( "<span style='%s'>%s</span>",
args.style, show )
end
r = string.format( "[[phab:T%d%s|%s]]", n, sub, show )
return r
end -- task()
local function taskBugzilla( args )
-- Link to an old Bugzilla ticket
-- Precondition:
-- args -- table; assignments
-- Postcondition:
-- Returns string, if fine
-- Throws error on failure
-- Uses:
-- task()
local r = args.Bugzilla
local j = r:find( "#", 1, true )
local item, n, show
if j then
local scroll = r:sub( j + 1 )
r = r:sub( 1, j - 1 )
scroll = scroll:match( "^[cC]?([0-9]+)$" )
if scroll then
item = tonumber( scroll )
end
end
n = r:match( "^([0-9]+)%s*$" )
if n then
n = tonumber( n ) -- discard leading zeros
if n <= 73681 then
args.Task = tostring( n + 2000 )
else
n = false
end
end
if not n then
r = string.format( "Invalid number: 'Bugzilla=%s'", r )
error( r, 0 )
end
r = string.format( "https://old-bugzilla.wikimedia.org/%s%d",
"show_bug.cgi?id=", n )
show = string.format( "Bugzilla:%d", n )
if item then
r = string.format( "%s#c%d", r, item )
show = string.format( "%s #c%d", show, item )
end
r = string.format( "[%s %s]", r, show )
r = string.format( "%s <small style=\"font-weight:normal\">(%s)</small>",
task( args ), r )
return r
end -- taskBugzilla()
local function unified( args, frame )
-- Link to a management issue
-- Precondition:
-- args -- table; assignments
-- Postcondition:
-- Returns string, if fine
-- Throws error on failure
-- Uses:
-- lonely()
-- taskBugzilla()
-- task()
-- phabBoards()
-- phabUser()
local r
lonely( args,
{ "Bugzilla", "Countdown", "Differential", "Engage",
"File", "Gerrit", "Join", "Mock", "Paste", "Review",
"Task", "User" } )
if args.Bugzilla then
r = taskBugzilla( args )
elseif args.Engage then
r = phabBoards( args )
elseif args.File then
r = file( args )
elseif args.Mock then
r = mock( args )
elseif args.Task then
r = task( args )
elseif args.User then
r = phabUser( args, frame )
else
r = "NOT YET READY"
error( r, 0 )
end
-- Countdown
-- Differential
-- Gerrit
-- Join
-- Paste
-- Review
-- Leerzeichen-getrennte Liste
return r
end -- unified()
local function main( args, frame )
-- Do the job
-- Precondition:
-- args -- table; assignments
-- frame -- object or nil
-- Postcondition:
-- Returns string with link, if fine
-- Throws error on failure
-- Uses:
-- unified()
-- sourcing()
local defaults = { Bugzilla = "",
Engage = true,
User = true }
local got = { }
local mode = 0
local params = { style = 0,
Anchor = 1,
Anchor = 1,
Bugzilla = 1,
Countdown = 1,
Differential = 1,
Engage = 1,
File = 1,
-- Gerrit = 1,
Join = 1,
Mock = 1,
Paste = 1,
Review = 1,
Show = 1,
Task = 1,
User = 1,
branch = 2,
commit = 2,
commitdiff = 2,
diff = 2,
dir = 2,
file = 2,
history = 2,
line = 2,
plain = 2,
project = 2,
title = 2,
callsigns = 3 }
local gr, s
for k, v in pairs( args ) do
mode = params[ k ]
if not mode then
mode = -1
end
if not got[ mode ] then
got[ mode ] = { }
end
got[ mode ][ k ] = v
end -- for k, v
r = got[ -1 ]
if r then
if #r == 1 then
s = ""
else
s = "s"
end
r = string.format( "Unknown parameter%s: '%s'",
s, concatKeys( r ) )
error( r, 0 )
elseif got[ 1 ] and got[ 2 ] then
r = string.format( "'%s' conflicting with '%s'",
concatKeys( got[ 1 ] ),
concatKeys( got[ 2 ] ) )
error( r, 0 )
else
local procs = { unified, sourcing, phabCallsigns }
if mode == 0 then
mode = 2
got[ 2 ] = { }
end
if got[ 0 ] then
for k, v in pairs( got[ 0 ] ) do
got[ mode ][ k ] = v
end -- for k, v
end
got = got[ mode ]
for k, v in pairs( got ) do
s = type( v )
if s == "number" then
v = tostring( v )
elseif s == "string" then
if #v == 0 then
v = defaults[ k ]
end
elseif v == true then
v = defaults[ k ]
else
v = nil
end
if v then
got[ k ] = v
else
got[ k ] = nil
end
end -- for k, v
r = procs[ mode ]( got, frame )
end
return r
end -- main()
-- Export
local p = {}
function p.test( a )
local lucky, r = pcall( main, a )
return r
end
function p.f( frame )
local lucky, r = pcall( main, frame:getParent().args, frame )
if not lucky then
r = string.format( "<span class=\"error\">%s</span>[[%s]]",
r, Sick )
end
return r
end
function p.failsafe()
return Serial
end
return p