Modul:WikidataScheme
| Vorlagenprogrammierung | Diskussionen | Lua | Unterseiten | |||
| Modul | Deutsch | English
|
Modul: | Dokumentation | ||
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
Dies ist die (produktive) Mutterversion eines global benutzten Lua-Moduls.
Wenn die serial-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Wenn die serial-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Versionsbezeichnung auf WikiData:
2019-12-16local WikidataScheme = { suite = "WikidataScheme",
serial = "2019-12-16",
item = 74420405,
globals = { Multilingual = 47541920 } }
--[=[
Pattern for new entities on Wikidata as internationalized guide
]=]
local Failsafe = WikidataScheme
local GlobalMod = WikidataScheme
local Config = { }
local JSONexport = { }
local Resolver = { }
local Table = { }
local Text = { }
Config.coded = { dir = "ltr",
lang = "en" }
Config.colors = { tableheadbg = "B3B7FF",
required = "EAF3FF",
suggested = "FFFFFF",
optional = "EAECF0",
deprecated = "FFCBCB" }
Config.spaces = { L = "Lexeme:",
P = "Property:",
Q = false }
Config.types = { "P", "Q", "L" }
Config.errors = { bag = false }
Config.i18n = { onLabel = "Q461984", -- naming convention
onDesc = "Q1200750", -- description
-- wikibase-newentity-description
onAlias = "wikibase-entitytermsforlanguagelistview-aliases" }
-- Q18616576 Wikidata property
-- Q19798642 Wikidata value
Config.defaults = { err_BadExample = "Invalid property example",
-- ToDo: I18n
err_BadQualifier = "Invalid qualifier definition",
err_InvalidClaim = "Invalid claim",
err_InvalidNameType = "Invalid entity name type",
err_NameBad = "is no assigned entity name",
err_NameEmpty = "entity name empty",
err_NameMissed = "unresolved",
err_NoEntity = "is not an entity",
err_NoNameResolver = "needs",
err_NoProperty = "is not a Property",
err_q_qlist = "Both q and qlist specified",
err_Unguided = "Missing guidance"
}
local foreignModule = function ( access, advanced, append, alt, alert )
-- Fetch global module
-- Precondition:
-- access -- string, with name of base module
-- advanced -- true, for require(); else mw.loadData()
-- append -- string, with subpage part, if any; or false
-- alt -- number, of wikidata item of root; or false
-- alert -- true, for throwing error on data problem
-- Postcondition:
-- Returns whatever, probably table
-- 2019-10-29
local storage = access
local finer = function ()
if append then
storage = string.format( "%s/%s",
storage,
append )
end
end
local fun, lucky, r, suited
if advanced then
fun = require
else
fun = mw.loadData
end
GlobalMod.globalModules = GlobalMod.globalModules or { }
suited = GlobalMod.globalModules[ access ]
if not suited then
finer()
lucky, r = pcall( fun, "Module:" .. storage )
end
if not lucky then
if not suited and
type( alt ) == "number" and
alt > 0 then
suited = string.format( "Q%d", alt )
suited = mw.wikibase.getSitelink( suited )
GlobalMod.globalModules[ access ] = suited or true
end
if type( suited ) == "string" then
storage = suited
finer()
lucky, r = pcall( fun, storage )
end
if not lucky and alert then
error( "Missing or invalid page: " .. storage, 0 )
end
end
return r
end -- foreignModule()
local failures = function ()
-- Summarize all faults
-- Postcondition:
-- Returns string, hopefully empty
local r
if Config.errors.bag then
local max = 1000000000
local id = math.floor( os.clock() * max )
local show = string.format( "%s * Errors",
WikidataScheme.suite )
local sign = string.format( "error_%d", id )
local errors = mw.html.create( "ul" )
:addClass( "error" )
local e = mw.html.create( "h2" )
:addClass( "error" )
:attr( "id", sign )
:wikitext( show )
for i = 1, #Config.errors.bag do
errors:newline()
:node( mw.html.create( "li" )
:addClass( "error" )
:wikitext( Config.errors.bag[ i ] ) )
end -- for i
r = string.format( "%s\n%s\n",
tostring( e ), tostring( errors ) )
show = string.format( "[[#%s|%s]]", sign, WikidataScheme.suite )
mw.addWarning( show )
end
Config.errors.bag = false
return r or ""
end -- failures()
local fault = function ( alert )
-- Format one error message in HTML
-- Precondition:
-- alert -- string, plain error message
-- Postcondition:
-- Returns string, HTML error message
local e = mw.html.create( "span" )
:addClass( "error" )
:wikitext( alert )
Config.errors.bag = Config.errors.bag or { }
table.insert( Config.errors.bag, alert or "??fault??" )
return tostring( e )
end -- fault()
local fix = function ( adjust )
-- Escape and trim string
-- Precondition:
-- adjust -- string, with some text
-- Postcondition:
-- Returns string, with some text
return mw.text.trim( adjust ):gsub( "\\", "\\\\" )
:gsub( "\"", "\\\"" )
end -- fix()
Config.feature = function ( area, about, allow )
local r
if Config.options then
end
return r
end -- Config.feature()
Config.field = function ( ask )
-- Retrieve general I18n text
-- Precondition:
-- ask -- string, with text ID, entity ID or system message
-- Postcondition:
-- Returns string, with message
local r
Config.texts = Config.texts or { }
r = Config.texts[ ask ]
if not r then
r = Config.i18n[ ask ]
if type( r ) == "string" then
if r:match( "^Q%d+$" ) then
r = Text.wikibase( r )
else
r = mw.message.new( r ):plain()
end
Config.texts[ ask ] = r
end
end
return r or "??????????"
end -- Config.field()
Config.first = function ()
-- Initialize or reset Config
if not Config.statelist then
Config.css = { }
Config.statelist = { }
for k, v in pairs( Config.colors ) do
if k == "tableheadbg" then
k = "tablehead"
else
Config.statelist[ k ] = true
end
Config.css[ k ] = { ["background-color"] = "#" .. v }
end -- for k, v
end
Config.options = false
-- aus /config neu, mit .Request überschreiben
end -- Config.first()
JSONexport.family = function ( assign, access, align, adjust )
-- Create list of claims or qualifiers
-- Precondition:
-- assign -- table, with definition of element
-- access -- string, with key in assign
-- align -- number, level of alignment
-- adjust -- true, for resolving symbolic IDs
-- Postcondition:
-- Returns string with extended JSON code, or not
local collect = assign[ access ]
local r
if type( collect ) == "table" then
local indent = align + 1
local n = #collect
local shift = string.rep( " ", align )
local list
if align > 1 and type( assign.list ) == "boolean" then
list = assign.list
r = string.format( "%s\"%s\": %s",
shift, tostring( list ) )
else
r = ""
end
if n > 0 then
local sep = ""
if list then
r = string.format( "%s\n%s", r, shift )
end
r = string.format( "%s%s\"%s\": [",
r, shift, access )
for i = 1, n do
r, sep = JSONexport.fiat( collect[ i ],
indent,
r,
sep,
adjust )
end -- for i
r = string.format( "%s\n%s%s ]",
r, shift, string.rep( " ", #access ) )
end
end
return r
end -- JSONexport.family()
JSONexport.favour = function ( all )
-- Create resolve component
-- Precondition:
-- all -- table, with entire request
local r
if type( all.resolve ) == "table" then
local n = 0
local order = { }
local j, coll, s
for k, v in pairs( all.resolve ) do
if type( k ) == "string" and
type( v ) == "table" then
k = mw.text.trim( k )
if k ~= "" then
for i = 1, #Config.types do
s = Config.types[ i ]
j = v[ s ]
if type( j ) == "number" and
j >= 0 and
j == math.floor( j ) then
coll = coll or { }
k = fix( k )
coll[ k ] = string.format( "{ \"%s\": %d }",
s, j )
table.insert( order, k )
j = mw.ustring.len( k )
if j > n then
n = j
end
break -- for i
end
end -- for i
end
end
end -- for k, v
if #order > 0 then
local sep = ""
local k, v
table.sort( order )
r = " \"resolve\": { "
n = n + 1
for i = 1, #order do
k = order[ i ]
v = coll[ k ]
j = mw.ustring.len( k )
s = string.rep( " ", n - mw.ustring.len( k ) )
r = string.format( "%s%s\"%s\": %s%s",
r, sep, k, s, v )
sep = ",\n "
end -- for k, v
r = r .. "\n }"
end
end
return r
end -- JSONexport.favour()
JSONexport.features = function ( assign, align, adjust )
-- Create value element
-- Precondition:
-- assign -- table, with definition of value
-- align -- number, level of alignment
-- adjust -- true, for resolving symbolic IDs
-- Postcondition:
-- Returns string, if not empty
local r
if type( assign ) == "table" then
local indent = align + 1
local shift = string.rep( " ", align )
local f = function ( a )
if a and a ~= "" then
if r then
r = string.format( "%s,\n%s", r, a )
else
r = "\n" .. a
end
end
end -- f()
f( JSONexport.flat( assign, "intro", indent ) )
f( JSONexport.filled( assign, indent, adjust ) )
f( JSONexport.fixed( assign, "q", indent, adjust ) )
f( JSONexport.fixed( assign, "qdefault", indent, adjust ) )
f( JSONexport.fixed( assign, "qqexample", indent, adjust ) )
f( JSONexport.flat( assign, "example", indent ) )
f( JSONexport.family( assign, "qualifiers", indent, adjust ) )
f( JSONexport.flat( assign, "terminate", indent ) )
if r then
r = string.format( "%s {%s\n%s }",
shift, r, shift )
end
end
return r
end -- JSONexport.features()
JSONexport.fetch = function ( access, adjust, alike )
-- Resolve symbolic entity name, if necessary
-- Precondition:
-- access -- string, with entity name or ID
-- adjust -- true, for resolving symbolic IDs
-- alike -- string, if Property or Item required
-- Postcondition:
-- Returns: string, if valid, with quoted thing
local r
if type( access ) == "string" then
local s = mw.text.trim( access )
if s ~= "" then
if adjust then
r = Resolver.fetch( s, alike )
else
r = s
end
if r then
r = string.format( "\"%s\"",
r:gsub( "\"", "" )
:gsub( "\\", "" ) )
end
end
end
return r
end -- JSONexport.fetch()
JSONexport.fiat = function ( assign, align, apply, after, adjust )
-- Create independent entry (in claims or qualifiers) as JSON
-- Precondition:
-- assign -- table, with definition of element
-- align -- number, level of alignment
-- apply -- string, with JSON code to be extended
-- after -- string, with preceding separator
-- adjust -- true, for resolving symbolic IDs
-- Postcondition:
-- Extend apply if element present
-- Returns:
-- 1. string with extended JSON code
-- 2. separator, for next element
local r = apply
local r2 = after
if type( assign ) == "table" then
local s = JSONexport.fetch( assign.subject, adjust, true )
if s then
local shift = string.rep( " ", align )
local indent = align + 1
local f = function ( a )
if a and a ~= "" then
if r then
r = string.format( "%s,\n%s", r, a )
else
r = "\n" .. a
end
end
end -- f()
local state
r = string.format( "%s%s\n%s{ \"subject\": %s",
r, r2, shift, s )
f( JSONexport.flat( assign, "intro", indent ) )
if Config.statelist[ assign.state ] then
state = assign.state
else
state = "optional"
end
r = string.format( "%s,\n%s \"state\": \"%s\"",
r, shift, state )
f( JSONexport.filled( assign, indent, adjust ) )
f( JSONexport.fixed( assign, "q", indent, adjust ) )
f( JSONexport.fixed( assign, "qdefault", indent, adjust ) )
f( JSONexport.fixed( assign, "qqexample", indent, adjust ) )
if type( assign.values ) == "table" then
local vals = { }
local v
for i = 1, #assign.values do
v = JSONexport.features( assign.values[ i ],
indent,
adjust )
if v then
table.insert( vals, v )
end
end -- for i
if #vals then
local sep = ""
r = string.format( "%s,\n%s \"values\": [",
r, shift )
for i = 1, #vals do
r = string.format( "%s%s\n%s %s",
r, sep, shift, vals[ i ] )
sep = ","
end -- for i
r = string.format( "%s\n%s ]", r, shift )
end
end
f( JSONexport.flat( assign, "example", indent ) )
f( JSONexport.flat( assign, "terminate", indent ) )
f( JSONexport.further( assign, "class", indent ) )
f( JSONexport.further( assign, "style", indent ) )
r = string.format( "%s\n%s}", r, shift )
r2 = ","
end
end
return r, r2
end -- JSONexport.fiat()
JSONexport.filled = function ( assign, align, adjust )
-- Create independent JSON list of suggested items (Q), if present
-- Precondition:
-- assign -- table, with definition of element
-- align -- number, level of alignment
-- adjust -- true, for resolving symbolic IDs
-- Postcondition:
-- Returns string with JSON code, or not
local r
if type( assign ) == "table" and
type( assign.qlist ) == "table" then
local n = #assign.qlist
if n > 0 then
local indent = align + 1
local sep = ""
local shift = string.rep( " ", align )
local q, s
r = shift .. "\"qlist\": [ "
for i = 1, n do
q = assign.qlist[ i ]
if type( q ) == "number" then
s = tostring( q )
if s:find( "^[1-9]%d*$" ) then
q = "Q" .. s
end
end
if type( q ) == "string" then
s = JSONexport.fetch( q, adjust, false )
elseif i == n and q == true then
s = "true"
end
if s then
r = string.format( "%s%s%s",
r, sep, s )
sep = ",\n " .. shift
end
end -- for i
r = r .. " ]"
end
end
return r
end -- JSONexport.filled()
JSONexport.fixed = function ( assign, at, align, adjust )
-- Create mandatory/default item (Q), if present
-- Precondition:
-- assign -- table, with definition of element
-- at -- string, with ID within assign
-- "q", "qdefault", "qqexample"
-- align -- number, level of alignment
-- adjust -- true, for resolving symbolic IDs
-- Postcondition:
-- Returns string with JSON code, or not
local r
if type( assign ) == "table" then
local v = assign[ at ]
local s = type( v )
if s == "string" then
s = v
elseif s == "number" then
if v > 0 and
v == math.floor( v ) then
s = string.format( "Q%d", v )
else
s = false
end
elseif s == "table" then
local n = #v
if n == 1 then
s = v[ 1 ]
elseif n > 1 then
local collect = { }
local k
for i = 1, n do
s = JSONexport.fetch( v[ i ], adjust, false )
if s then
table.insert( collect, s )
k = i
end
end -- for i
n = #collect
if at == "qqexample" and n ~= 2 then
n = 0
end
if n == 1 then
s = v[ k ]
else
if n > 1 then
local shift = string.rep( " ", align )
local sep = "\n"
r = string.format( "%s\"%s\": [", shift, at )
for i = 1, n do
r = string.format( "%s%s%s %s",
r,
sep,
shift,
collect[ i ] )
sep = ",\n"
end -- for i
s = string.rep( " ", 2*align + #at + 4 )
r = string.format( "%s\n%s]", r, s )
end
s = false
end
else
s = false
end
else
s = false
end
if s and not r and at ~= "qqexample" then
s = JSONexport.fetch( s, adjust, false )
if s then
local shift = string.rep( " ", align )
r = string.format( "%s\"%s\": %s", shift, at, s )
end
end
end
return r
end -- JSONexport.fixed()
JSONexport.flat = function ( all, at, align )
-- Create JSON for textual element
-- Precondition:
-- all -- table, with request branch
-- at -- string, with ID within { all }
-- align -- number, level of alignment
-- Postcondition:
-- Returns string with extended JSON code
local e = all[ at ]
local o = { }
local s = type( e )
local r, shift, t
if s == "table" then
local parts
for k, v in pairs( e ) do
if type( k ) == "string" and
k:find( "^%l%l" ) then
if type( v ) == "string" then
if k ~= "class" and k ~= "style" then
parts = mw.text.split( k, "-" )
if parts[ 1 ]:find( "^%l%l%l?$" ) then
if #parts >= 2 and
not parts[ 2 ]:find( "^%u%l%l%l$" ) and
not parts[ 2 ]:find( "^%l%l%l" ) and
not parts[ 2 ]:find( "^%u%u$" ) then
k = false
end
else
k = false
end
end
elseif type( v ) ~= "table" or
( k ~= "class" and k ~= "style" ) then
k = false
end
if k then
t = t or { }
t[ k ] = v
if k ~= "class" and k ~= "style" then
table.insert( o, k )
end
end
end
end -- for k, v
if t then
table.sort( o )
if t.class then
table.insert( o, "class" )
end
if t.style then
table.insert( o, "style" )
end
end
elseif s == "string" then
if e:match( "^[PQL]%d+$" ) then
r = string.format( "\"%s\"", e )
else
t = { }
t.und = e
table.insert( o, "und" )
end
end
if r or t then
shift = string.rep( " ", align )
end
if t then
local sep = ""
local data, slang
r = "{\n"
for i = 1, #o do
slang = o[ i ]
data = t[ slang ]
if type( data ) == "string" then
s = fix( data )
else
local sept = ""
s = "{\n"
for k, v in pairs( data ) do
s = string.format( "%s%s%s \"%s\": \"%s\"",
s, sept, shift, k, v )
sept = ",\n"
end -- for k, v
s = string.format( "%s\n%s %s}",
s,
shift,
string.rep( " ", #slang + 4 ) )
end
r = string.format( "%s%s%s \"%s\": \"%s\"",
r, sep, shift, slang, s )
sep = ",\n"
end -- for i
r = string.format( "%s\n%s%s}",
r,
shift,
string.rep( " ", #at + 4 ) )
end
if r then
r = string.format( "%s\"%s\": %s", shift, at, r )
end
return r
end -- JSONexport.flat()
JSONexport.full = function ( all, adjust )
-- Create independent JSON for registration elements
-- Precondition:
-- all -- table, with entire request
-- adjust -- true, for resolving symbolic IDs
-- Postcondition:
-- Returns string with JSON code, or error message
local r = string.format( "{ \"@generated\": \"%s\"",
Config.frame:callParserFunction( "#timel",
"c" ) )
local f = function ( a )
if a and a ~= "" then
r = string.format( "%s,\n%s", r, a )
end
end -- f()
r = string.format( "%s,\n \"@format\": \"%s %s\"",
r, WikidataScheme.suite, WikidataScheme.serial )
f( JSONexport.flat( all, "caption", 1 ) )
f( JSONexport.flat( all, "onLabel", 1 ) )
f( JSONexport.flat( all, "onDesc", 1 ) )
f( JSONexport.flat( all, "onAlias", 1 ) )
f( JSONexport.family( all, "claims", 1, adjust ) )
f( JSONexport.flat( all, "footer", 1 ) )
if not adjust then
f( JSONexport.favour( all ) )
end
f( JSONexport.further( all, "id", 1 ) )
f( JSONexport.further( all, "class", 1 ) )
f( JSONexport.further( all, "style", 1 ) )
f( JSONexport.further( all, "options", 1 ) )
r = r .. "\n}"
return r
end -- JSONexport.full()
JSONexport.further = function ( all, at, align )
-- Create entry for auxilary elements
-- Precondition:
-- all -- table, with entire request
-- at -- string, with ID within { all }
-- align -- number, level of alignment
-- Postcondition:
-- Returns string with JSON code, or not
local permit = { id_string = true,
class_string = true,
class_table = true,
style_string = true,
style_table = true,
options_table = true }
local e = all[ at ]
local s = type( e )
local r
if permit[ string.format( "%s_%s", at, s ) ] then
if s == "string" then
e = mw.text.trim( e )
if e == "" then
e = false
elseif at == "class" then
e = mw.text.split( e, "%s+" )
s = "table"
end
elseif not pairs( e ) then
e = false
end
if e then
local shift = string.rep( " ", align )
if s == "string" then
r = string.format( "%s%s%s \"%s\": \"%s\"",
shift, at, fix( e ) )
else
local sep = ""
r = "{\n"
for k, v in pairs( e ) do
r = string.format( "%s%s%s \"%s\": \"%s\"",
r, sep, shift, k, fix( e ) )
sep = ",\n"
end -- for k, v
r = string.format( "%s\n%s%s}",
r,
shift,
string.rep( " ", #at + 4 ) )
end
end
end
return r
end -- JSONexport.further()
Resolver.fetch = function ( access, alike )
-- Resolve entity name
-- Precondition:
-- access -- string, with entity name or ID
-- alike -- string, if Property or Item required, "P" or "Q"
-- Postcondition:
-- Returns
-- 1. string or not, with entity ID
-- 2. string, with error message
local r1, r2
if type( access ) == "string" then
r2 = mw.text.trim( access )
if r2 == "" then
r2 = Text.flip( "err_NameEmpty" )
else
if r2:find( "^[PQL]%d+$" ) then
r1 = r2
elseif type( WikidataScheme.Request.resolve ) == "table" then
local entry = WikidataScheme.Request.resolve[ r2 ]
if type( entry ) == "table" then
for k, v in pairs( Config.spaces ) do
if type( entry[ k ] ) == "number" then
r1 = string.format( "%s%d", k, entry[ k ] )
break -- for k, v
end
end -- for k, v
if not r1 then
r2 = string.format( "<%s> %s",
r2,
Text.flip( "err_NameBad" )
)
end
else
r2 = string.format( "<%s> %s",
r2,
Text.flip( "err_NameMissed" ) )
end
else
r2 = string.format( "<%s> %s .resolve",
r2,
Text.flip( "err_NoNameResolver" ) )
end
if r1 then
if alike and r1:sub( 1, 1 ) ~= alike then
r2 = string.format( "%s %s",
r1,
Text.flip( "err_InvalidNameType"
) )
elseif not mw.wikibase.isValidEntityId( r1 ) then
r2 = string.format( "%s %s",
r1,
Text.flip( "err_NoEntity" ) )
r1 = false
else
r2 = false
end
end
end
else
r2 = string.format( "%s %s",
Text.flip( "err_InvalidNameType" ),
type( access ) )
end
return r1, r2
end -- Resolver.fetch()
Resolver.fire = function ( all )
-- Create <table> for resolve assignment
-- Precondition:
-- all -- table, with entire request
-- Postcondition:
-- Returns string with entire HTML table, or not
local r
if type( all.resolve ) == "table" then
local order = { }
local j, coll, s
for k, v in pairs( all.resolve ) do
if type( k ) == "string" and
type( v ) == "table" then
k = mw.text.trim( k )
if k ~= "" then
for i = 1, #Config.types do
s = Config.types[ i ]
j = v[ s ]
if type( j ) == "number" and
j >= 0 and
j == math.floor( j ) then
coll = coll or { }
k = fix( k )
coll[ k ] = string.format( "%s%d", s, j )
table.insert( order, k )
break -- for i
end
end -- for i
end
end
end -- for k, v
if #order > 0 then
local tbl = mw.html.create( "table" )
:addClass( "wikitable sortable" )
:addClass( WikidataScheme.suite .. "-resolve" )
local tr = mw.html.create( "tr" )
local e, e2, k, s, td
tr:newline()
:node( mw.html.create( "th" )
:attr( "title", "symbol" )
:css( Config.css.tablehead )
:wikitext( "symbol" ) )
:newline()
:node( mw.html.create( "th" )
:attr( "title", "entity" )
:css( Config.css.tablehead )
:wikitext( "entity" ) )
:newline()
:node( mw.html.create( "th" )
:attr( "title", "label" )
:css( Config.css.tablehead )
:wikitext( "label" ) )
tbl:newline()
table.sort( order )
for i = 1, #order do
k = order[ i ]
tr = mw.html.create( "tr" )
e = mw.html.create( "code" )
:attr( Config.coded )
:wikitext( k )
td = mw.html.create( "td" )
:node( e )
tr:newline()
:node( td )
e, e2 = Table.fetch( coll[ k ], false, true )
td = mw.html.create( "td" )
:node( e )
tr:newline()
:node( td )
td = mw.html.create( "td" )
:node( e2 )
tr:newline()
:node( td )
tbl:newline()
:node( tr )
end -- for k, v
r = tostring( tbl:newline() )
end
end
return r
end -- Resolver.fire()
Text.fashion = function ( at, apply )
-- Assign class and style
-- Precondition:
-- at -- mw.html element
-- apply -- table, or not, may contain components class or style
-- Postcondition:
-- element modified
if type( apply ) == "table" then
local class = apply.class
local css = apply.style
if class then
if type( class ) == "string" then
at:addClass( class )
elseif type( class ) == "table" then
for i = 1, #class do
at:addClass( class[ i ] )
end -- for i
end
end
if css then
if type( css ) == "string" then
at:cssText( css )
elseif type( css ) == "table" then
at:css( css )
end
end
end
end -- Text.fashion()
Text.find = function ( available )
-- Find best match of I18N options
-- Precondition:
-- available -- table, I18N
-- Postcondition:
-- Returns
-- 1. string, with selected message, or not
-- 2. string, with language code, or not
local r, r2
local f = function ()
if type( r ) == "string" then
r = mw.text.trim( r )
if r == "" then
r = false
end
end
end -- f()
if type( available ) == "table" then
if Text.Multilingual then
r, r2 = Text.Multilingual.i18n( available,
false,
Config.frame )
else
Text.foreign()
r = available[ Text.slang ]
f()
if r then
r2 = Text.slang
else
r = available.en
r2 = "en"
end
end
elseif type( available ) == "string" then
r = available
end
f()
if not r then
for k, v in pairs( available ) do
r = v
f()
if r then
r2 = k
break -- for k, v
end
end -- for k, v
end
f()
if not r then
r2 = false
end
return r, r2
end -- Text.find()
Text.flip = function ( about, apply )
-- Retrieve specific module I18n text
-- Precondition:
-- about -- string, with text ID
-- apply -- sequence table, with parameters
-- Postcondition:
-- Returns
-- 1. string, with selected message
-- 2. string, with language code
local r, r2
if type( Config.globals ) == "nil" then
Text.flipper( WikidataScheme.suite )
end
if Config.globals then
r = Config.globals[ about ]
end
if r then
r, r2 = Text.find( r )
end
if not r then
r = Config.defaults[ about ]
if r then
r2 = "en"
else
if type( about ) == "string" then
r = string.format( "???I18N(%s)I18N???", about )
else
r = fault( "Invalid message ID type" )
end
end
end
if apply and
r:find( "$", 1, true ) and
type( apply ) == "table" then
r = mw.message.newRawMessage( r, apply ):plain()
end
return r, r2
end -- Text.flip()
Text.flipper = function ( apply )
-- Retrieve global specific I18N translations
-- Precondition:
-- apply -- string, with package ID
-- Postcondition:
local storage = string.format( "I18n/Module:%s.tab", apply )
local lucky, t = pcall( mw.ext.data.get, storage, "_" )
Config.globals = false
if type( t ) == "table" then
t = t.data
if type( t ) == "table" then
local e
for i = 1, #t do
e = t[ i ]
if type( e ) == "table" and
type( e[ 1 ] ) == "string" and
type( e[ 2 ] ) == "table" then
Config.globals = Config.globals or { }
Config.globals[ e[ 1 ] ] = e[ 2 ]
else
error( storage .. " has unexpected scheme", 0 )
end
end -- for i
else
error( storage .. " corrupted", 0 )
end
end
end -- Text.flipper()
Text.flow = function ( at, alien, applied )
-- Assign differing language and script direction
-- Precondition:
-- at -- mw.html element
-- alien -- string, with language (or script) code, or not
-- applied -- string, with plain text, or not
-- Postcondition:
-- element modified if not matching
-- Returns true if script direction changed
local dir = function ( a )
local r
if a then
r = "ltr"
else
r = "rtl"
end
return r
end -- dir()
local isRTL = function ( a )
local r
if Text.Multilingual then
r = Text.Multilingual.isRTL( a )
else
r = mw.language.new( a ):isRTL()
end
return r
end -- isRTL()
local shift, slang
if not Text.shift then
Text.foreign( true )
if Text.slang then
Text.ltr = not isRTL( Text.slang )
end
if type( Text.ltr ) ~= "boolean" then
Text.ltr = not mw.language.getContentLanguage():isRTL()
end
Text.shift = dir( Text.ltr )
end
if alien then
Text.dirs = Text.dirs or { }
shift = Text.dirs[ alien ]
if not shift then
shift = dir( not isRTL( alien ) )
Text.dirs[ alien ] = shift
end
if applied and shift == "rtl" then
if not Text.Latn then
Text.Latn = string.format( "^[ -%s]*$",
mw.ustring.char( 0x052F ) )
end
if mw.ustring.find( applied, Text.Latn ) then
shift = "ltr"
end
end
if shift == Text.shift then
shift = false
end
if alien ~= Text.slang then
slang = alien
end
else
shift = Text.shift
slang = Text.slang
end
if shift then
at:attr( "dir", shift )
end
if slang then
at:attr( "lang", slang )
end
return true and shift
end -- Text.flow()
Text.foreign = function ( again )
-- Guess human language
-- Precondition:
-- again -- true, for re-evaluation
-- Postcondition:
-- Returns language code, or not
if again or type( Text.slang ) == "nil" then
if Text.Multilingual then
Text.slang = Text.Multilingual.userLangCode()
elseif not Text.slang then
Text.slang = mw.language.getContentLanguage():getCode()
:lower()
end
end
if Text.slang and
mw.ustring.codepoint( Text.slang, 1, 1 ) > 122 then
Text.slang = false
end
return Text.slang
end -- Text.foreign()
Text.html = function ( available, as, alt, alien, across )
-- Create HTML text element
-- Precondition:
-- available -- table, I18N, string: plain text or ID, or not
-- as -- string, HTML tag name
-- alt -- string, with fallback text
-- alien -- string, with language (or script) code, or not
-- across -- number, of columns, for TD
-- Postcondition:
-- Returns mw.html element
local r = type( available )
local show, slang
if r == "table" then
show, slang = Text.find( available )
elseif r == "string" then
if available:find( "^[QPL]%d+$" ) then
local sign = available
if mw.wikibase.isValidEntityId( sign ) then
local s = Config.spaces[ sign:sub( 1, 1 ) ]
if s then
sign = s .. sign
else
sign = sign
end
show, slang = Text.wikibase( sign )
else
show = string.format( "%s %s",
sign,
Text.flip( "err_NoEntity" ) )
end
end
if not show then
show = available
end
slang = slang or alien
else
show = alt
end
if show then
r = mw.html.create( as )
if slang then
local bidi
if as == "code" then
r:attr( Config.coded )
bidi = not Text.ltr
else
bidi = Text.flow( r, slang, show )
end
if bidi and as == "span" then
r = mw.html.create( "bdo" )
:node( r )
Text.flow( r, slang )
end
end
r:wikitext( show )
Text.fashion( r, available )
else
r = mw.html.create( "code" )
:attr( Config.coded )
:wikitext( as )
end
if across and across > 1 then
r:attr( "colspan", tostring( across ) )
end
return r
end -- Text.html()
Text.templatedata = function ( area, about )
-- Retrieve TemplateData system message
-- Precondition:
-- area -- One of: "type", "desc", "status",
-- "example", "default"
-- about -- nil or in case of area=status: "required",
-- "suggested",
-- "optional",
-- "deprecated"
-- Postcondition:
-- Returns string, in general,
-- mw.html span for area=example|default
local s = "templatedata-doc-param-" .. area
local r
if about and area == "status" then
s = string.format( "%s-%s", s, about )
end
Text.templatedataCache = Text.templatedataCache or { }
r = Text.templatedataCache[ s ]
if not r then
local o = mw.message.new( s )
if o:exists() then
if Text.foreign( true ) then
o:inLanguage( Text.slang )
end
r = o:plain()
else
r = string.format( "???(%s)???", s )
end
if area == "example" or area == "default" then
r = mw.html.create( "span" )
:addClass( string.format( "%s-label-%s",
WikidataScheme.suite,
area ) )
:wikitext( r )
end
Text.templatedataCache[ s ] = r
end
return r
end -- Text.templatedata()
Text.wikibase = function ( all, about, attempt )
-- Translation of wikibase component
-- Precondition:
-- all -- string or table, object ID or entity
-- about -- boolean, true "descriptions" or false "labels"
-- attempt -- string or not, code of preferred language
-- Postcondition:
-- Returns
-- 1. string, with selected message, or not
-- 2. string, with language code, or not
local r, r2
if Text.Multilingual then
r, r2 = Text.Multilingual.wikibase( all,
about,
attempt,
Config.frame )
else
local s = type( all )
local object
if s == "table" then
object = all
elseif s == "string" then
object = mw.wikibase.getEntity( all )
r = all
end
if type( object ) == "table" then
if about then
s = "descriptions"
else
s = "labels"
end
object = object[ s ]
if type( object ) == "table" then
if object[ attempt ] then
r = object[ attempt ].value
r2 = attempt
elseif object.en then
r = object.en.value
r2 = "en"
else
local poly
for k, v in pairs( object ) do
r = v.value
r2 = k
break -- for k, v
end -- for k, v
end
end
end
end
return r or "????????", r2
end -- Text.wikibase()
Table.features = function ( assigned, across, already, asked, above )
-- Describe entry features
-- Precondition:
-- assigned -- table, with definition of one entry
-- across -- number, of columns, or nil on second level
-- already -- true, if first element to be created as TR
-- asked -- true, if first element to be created as TR
-- above -- string, with context property ID
-- Postcondition:
-- Returns sequence table with mw.html objects
-- 1. table, with TD
-- 2. table, with TR, or not
local r1, r2, td
local f = function ( add, also, a )
if add then
if across and across > 1 and not a then
add:attr( "colspan", tostring( across ) )
end
if already or r1 then
local tr
if add or not r2 then
tr = mw.html.create( "tr" )
:node( add )
Table.flag( tr, asked )
if also then
tr:newline()
:node( also )
end
r2 = r2 or { }
table.insert( r2, tr )
else
tr = r2[ #r2 ]
end
else
r1 = { }
table.insert( r1, add )
if also then
table.insert( r1, also )
end
end
end
end -- f()
local f1 = function ( already, add, about )
local ttd = Text.templatedata( about )
local sel = string.format( "%s-%s",
WikidataScheme.suite,
about )
local r = already
local lift
if r then
r:newline()
else
r = mw.html.create( "td" )
lift = true
end
r:node( mw.html.create( "div" )
:node( ttd ) )
:newline()
:node( add:addClass( sel ) )
if lift then
f( r )
end
return r
end -- f1()
local f2 = function ( add, about )
local ttd = Text.templatedata( about )
local sel = string.format( "%s-%s",
WikidataScheme.suite,
about )
local r = already
f( mw.html.create( "td" )
:node( ttd ),
add:addClass( sel ),
true )
end -- f2()
if type( assigned ) == "table" then
f( Table.field( assigned, "intro", 2 ) )
if type( assigned.qlist ) == "table" then
td = mw.html.create( "td" )
if type( assigned.q ) == "nil" then
local ul = Table.filled( assigned.qlist )
if ul then
f( td:node( ul ) )
end
else
f(td:wikitext( fault( Text.flip( "err_q_qlist" ) ) ) )
end
elseif type( assigned.q ) ~= "nil" then
td = mw.html.create( "td" )
f( td:node( Table.fixed( assigned, "q" ) ) )
end
if type( assigned.qdefault ) ~= "nil" then
local q = Table.fixed( assigned, "qdefault" )
if across == 2 then
q = mw.html.create( "td" )
:node( q )
f2( q, "default" )
else
td = f1( td, q, "default" )
end
end
if type( assigned.example ) ~= "nil" then
if across == 2 then
local q = Table.field( assigned, "example" )
f2( q, "example" )
else
local q = Text.html( assigned.example, "div" )
td = f1( td, q, "example" )
end
elseif type( assigned.qqexample ) == "table" then
local qpq = Table.fruit( above, assigned.qqexample )
if across == 2 then
f2( mw.html.create( "td" )
:node( qpq ),
"example" )
else
td = f1( td, qpq, "example" )
end
end
if type( assigned.qualifiers ) == "table" then
if across == 2 then
local hd, q, rows
for i = 1, #assigned.qualifiers do
q = assigned.qualifiers[ i ]
if type( q ) == "table" then
hd, rows = Table.further( q, hd )
if hd then
f( hd[ 1 ], hd[ 2 ], true )
end
if rows then
r2 = r2 or { }
for k = 1, #rows do
table.insert( r2, rows[ k ] )
end -- for k
end
else
q = Text.flip( "err_BadQualifier" )
f( mw.html.create( "td" )
:wikitext( fault( q ) ) )
end
end -- for i
else
td = mw.html.create( "td" )
:wikitext( fault( Text.flip( "err_Nesting" ) ) )
f( td )
end
end
f( Table.field( assigned, "terminate", 2 ) )
end
if not ( r1 ) then
f( mw.html.create( "td" ) )
end
return r1, r2
end -- Table.features()
Table.fetch = function ( access, alike, atom, alone )
-- Describe registration entity
-- Precondition:
-- access -- string, with entity name
-- alike -- string, if Property or Item required, "P" or "Q"
-- atom -- true, if two elements required
-- alone -- true, if combined linked element required
-- Postcondition:
-- Returns
-- 1. string, with entity ID and label, or error message,
-- or mw.html code element for atom
-- 2. mw.html span element for atom
local sign, r1 = Resolver.fetch( access, alike )
local r2
if sign then
local s = Config.spaces[ sign:sub( 1, 1 ) ]
local say, slang
if s then
s = s .. sign
else
s = sign
end
say, slang = Text.wikibase( sign, alike )
r2 = Text.html( say, "span", false, slang )
if alone then
r1 = string.format( "[[d:%s|%s]]", s, tostring( r2 ) )
else
s = string.format( "[[d:%s|%s]]", s, sign )
r1 = Text.html( s, "code", false, "en" )
if not atom then
r1 = string.format( "%s %s",
tostring( r1 ),
tostring( r2 ) )
end
end
elseif r1 then
r1 = fault( r1 )
else
r1 = fault( "Table.fetch()" )
end
return r1, r2
end -- Table.fetch()
Table.fiat = function ( assign )
-- Describe registration claim as major table row
-- Precondition:
-- assign -- table, with definition of one entry
-- Postcondition:
-- Returns sequence table, with mw.html.TR objects
local tr = mw.html.create( "tr" )
local td = mw.html.create( "td" )
local r = { }
if type( assign ) == "table" then
local state = Table.flag( tr, assign.state )
local how, n, rows, v
Text.fashion( tr, assign )
tr:addClass( string.format( "%s-%s",
WikidataScheme.suite, state ) )
v = Table.fetch( assign.subject )
td:wikitext( v )
if type( assign.values ) == "table" then
for i = 1, #assign.values do
how, v = Table.features( assign.values[ i ],
2,
how,
state,
assign.subject )
if v then
rows = rows or { }
for i = 1, #v do
table.insert( rows, v[ i ] )
end -- for i
end
end -- for i
else
how, rows = Table.features( false,
2,
false,
state,
assign.subject )
--[==[ if not ( how or rows ) then
td = mw.html.create( "td" )
:wikitext( fault( Text.flip( "err_Unguided" ) ) )
f( td )
end ]==]
end
if rows then
n = #rows + 1
else
n = 0
end
if n > 1 then
td:attr( "rowspan", tostring( n ) )
end
tr:newline()
:node( td )
if how then
for i = 1, #how do
tr:newline()
:node( how[ i ] )
end -- for i
end
td = mw.html.create( "td" )
:wikitext( Text.templatedata( "status", state ) )
if n > 1 then
td:attr( "rowspan", tostring( n ) )
end
tr:newline()
:node( td )
table.insert( r, tr )
for i = 1, n do
table.insert( r, rows[ i ] )
end -- for i
else
td:attr( "colspan", "3" )
:css( { ["background-color"] = "#FFFF00" } )
:wikitext( fault( Text.flip( "err_InvalidClaim" ) ) )
tr:node( td )
table.insert( r, tr )
end
return r
end -- Table.fiat()
Table.field = function ( all, ask, across )
-- Insert plain text table cell
-- Precondition:
-- all -- table, with request
-- ask -- string, with key in all
-- across -- number, of columns, or not
-- Postcondition:
-- Returns mw.html.TD object, or nothing
local q = all[ ask ]
local r
if q then
local n = across or 1
r = Text.html( q, "td", false, false, n )
end
return r
end -- Table.field()
Table.filled = function ( all )
-- Create unordered list of items
-- Precondition:
-- all -- sequence table, with entity names, and true as last
-- Postcondition:
-- Returns mw.html.UL, or nothing
local q, r, s
for i = 1, #all do
r = r or mw.html.create( "ul" )
q = all[ i ]
if type( q ) == "number" then
s = tostring( q )
if s:find( "^[1-9]%d*$" ) then
q = "Q" .. s
end
end
if type( q ) == "string" then
s = Table.fetch( q )
elseif i == #all and q == true then
s = "…"
else
q = mw.html.create( "code" )
:wikitext( tostring( q ) )
s = Text.flip( "err_InvalidNameType" )
s = string.format( "%s %s", tostring( q ), fault( s ) )
end
r:newline()
:node( mw.html.create( "li" )
:wikitext( s ) )
end -- for i
r:newline()
return r
end -- Table.filled()
Table.fixed = function ( assigned, at )
-- Create mandatory/default item (Q)
-- Precondition:
-- assigned -- string or number or sequence table of strings,
-- with item identifier
-- at -- string, with ID within assign, "q" or "qdefault"
-- -> string or number or sequence table of strings,
-- with item identifier
-- Postcondition:
-- Returns mw.html.span
local v = assigned[ at ]
local s = type( v )
local r
if s == "string" then
s = v
elseif s == "number" then
if v > 0 and
v == math.floor( v ) then
s = string.format( "Q%d", v )
else
s = false
end
elseif s == "table" then
local n = #v
if n == 1 then
r = Table.fixed( v[ 1 ], at )
elseif n > 1 then
r = mw.html.create( "span" )
for i = 1, #n do
if i > 1 then
r:node( mw.html.create( "br" ) )
:newline()
end
r:node( Table.fixed( v[ i ], at ) )
end -- for i
else
s = false
end
else
s = false
end
if not r then
if s then
s = Table.fetch( s )
else
s = fault( Text.flip( "err_NoEntity" ) )
end
r = mw.html.create( "span" )
:wikitext( s )
end
return r
end -- Table.fixed()
Table.flag = function ( adjust, assign )
-- Equip element with state style
-- Precondition:
-- adjust -- mw.html object, to be flagged
-- assign -- state name
-- Postcondition:
-- element modified
-- Returns defined state name
local r = assign
local css
if Config.css[ r ] then
css = Config.css[ r ]
else
r = "optional"
css = { ["background-color"] = "#FFFF00" }
end
adjust:css( css )
css = Config.feature( "css", r, "table string" )
if type( css ) == "string" then
adjust:cssText( css )
elseif type( css ) == "table" then
adjust:css( css )
end
return r
end -- Table.flag()
Table.flat = function ( all, ask, across, append )
-- Insert plain text table row
-- Precondition:
-- all -- table, with request
-- ask -- string, with key in all
-- across -- number, of columns, or not
-- append -- mw.html object, to be added to, or nothing
-- Postcondition:
-- Returns mw.html.TR object, or nothing
local q = all[ ask ]
local r
if q then
local n = across or 1
local s = Config.field( ask )
local td
r = mw.html.create( "tr" )
if s then
td = mw.html.create( "td" )
:wikitext( s )
r:newline()
:node( td )
n = 2
end
td = Text.html( q, "td", false, false, n )
r:newline()
:node( td )
if append then
append:newline()
:node( r )
end
end
return r
end -- Table.flat()
Table.form = function ( all )
-- Create <table> for registration elements
-- Precondition:
-- all -- table, with entire request
-- Postcondition:
-- Returns string with entire HTML table
local tbl = mw.html.create( "table" )
:addClass( "wikitable" )
:addClass( WikidataScheme.suite .. "-table" )
local tr, rows
if type( all.claims ) == "table" then
local got
for i = 1, #all.claims do
got = Table.fiat( all.claims[ i ] )
for k = 1, #got do
rows = rows or { }
table.insert( rows, got[ k ] )
end -- for k
end -- for i
end
if not rows then
rows = { Table.fiat( false ) }
end
if all.caption then
local o = type( all.caption )
if o == "string" or o == "table" then
o = Text.html( all.caption, "caption" )
Text.fashion( caption, all.caption )
tbl:newline()
:node( o )
end
end
Table.flat( all, "onLabel", 2, tbl )
Table.flat( all, "onDesc", 2, tbl )
Table.flat( all, "onAlias", 2, tbl )
Text.shift = false
Text.flow( tbl )
Text.fashion( tbl, all )
if type( all.id ) == "string" then
tbl:attr( "id", all.id )
end
tr = mw.html.create( "tr" )
tr:newline()
:node( mw.html.create( "th" )
:attr( "title", "type" )
:css( Config.css.tablehead )
:wikitext( Text.templatedata( "type" ) ) )
:newline()
:node( mw.html.create( "th" )
:attr( "colspan", "2" )
:css( Config.css.tablehead )
:wikitext( Text.templatedata( "desc" ) ) )
:newline()
:node( mw.html.create( "th" )
:attr( "title", "status" )
:css( Config.css.tablehead )
:wikitext( Text.templatedata( "status" ) ) )
tbl:newline()
-- :node( mw.html.create( "thead" )
:node( tr )
-- )
for i = 1, #rows do
tbl:newline()
:node( rows[ i ] )
end -- for i
if all.footer then
local o = type( all.footer )
if o == "string" or o == "table" then
o = Table.flat( all, "footer", 3 )
Text.fashion( footer, all.footer )
tbl:newline()
:node( o )
end
end
return tostring( tbl:newline() )
end -- Table.form()
Table.fruit = function ( assigned, adjoin )
-- Return content of a qqexample chain
-- Precondition:
-- assigned -- string, with name of P
-- adjoin -- table, with 2 elements as Q names: Item, P-value
-- Postcondition:
local e, r, s
if type( adjoin ) == "table" and #adjoin == 2 then
local p
p, e = Resolver.fetch( assigned, "P" )
if p then
local q1
q1, e = Resolver.fetch( adjoin[ 1 ], "Q" )
if q1 then
local q2
q2, e = Resolver.fetch( adjoin[ 2 ], "Q" )
if q2 then
local x
r = mw.html.create( "span" )
x, p = Table.fetch( p, false, true )
q1 = Table.fetch( q1, false, false, true )
q2 = Table.fetch( q2, false, false, true )
r:wikitext( q1 )
:wikitext( " <" )
:node( p )
:wikitext( "> " )
:wikitext( q2 )
end
end
end
end
if not r then
e = Text.flip( "err_BadExample" )
end
if e then
r = fault( e )
end
return r
end -- Table.fruit()
Table.further = function ( assign, already )
-- Describe one qualifier as middle column table row
-- Precondition:
-- assign -- table, with definition of one qualifier
-- already -- true, if first element to be created as TR
-- Postcondition:
-- Returns sequence tables with mw.html objects, or not
-- 1. TD, if not already
-- 2. TR, if any
local state, r1, r2, tr
local f = function ( add, also )
if add then
if state then
Table.flag( add, state )
if also then
Table.flag( also, state )
end
end
if already or r1 then
tr = mw.html.create( "tr" )
:newline()
:node( add )
if also then
tr:newline()
:node( also )
end
r2 = r2 or { }
table.insert( r2, tr )
else
r1 = { }
table.insert( r1, add )
if also then
table.insert( r1, also )
end
end
end
end -- f()
local td
local how, rows
if Config.statelist[ assign.state ] then
state = assign.state
else
state = "optional"
end
f( Table.flat( assign, "intro", 2 ) )
how, rows = Table.features( assign, 1, r1, state, assign.subject )
r1 = r1 or how
if rows then
r2 = r2 or { }
for i = 1, #rows do
table.insert( r2, rows[ i ] )
end -- for i
end
f( Table.flat( assign, "terminate" ) )
td = mw.html.create( "td" )
:node( Table.fetch( assign.subject, "P" ) )
if r1 then
table.insert( r1, 1, td )
elseif r2 then
r2[ 1 ]:newline()
:node( td )
else
f( td )
end
return r1, r2
end -- Table.further()
WikidataScheme.fetch = function ( about )
-- Retrieve Lua table
-- Precondition:
-- about -- table or JSON string or mw.loadData page name
-- Postcondition:
-- Returns string with error message, or not
-- Makes Lua table available as .Request
local s = type( about )
local r
if s == "string" then
local lucky, d
s = mw.text.trim( about )
if s:sub( 1, 1 ) == "{" and
s:sub( -1 ) == "}" then
lucky, d = pcall( mw.text.jsonDecode, about )
elseif not s:find( "\n", 2, true ) then
lucky, d = pcall( mw.loadData, about )
end
s = type( d )
if s == "table" then
WikidataScheme.Request = d
elseif s == "string" then
r = d
else
r = "Invalid data for WikidataScheme"
end
elseif s == "table" then
WikidataScheme.Request = about
else
r = "Invalid request for WikidataScheme"
end
return r
end -- WikidataScheme.fetch()
WikidataScheme.flat = function ( about, adjust, frame )
-- Export registration description as JSON
-- Precondition:
-- about -- table or JSON string or mw.loadData page name
-- adjust -- true, for resolving symbolic IDs
-- frame -- frame, if available
-- Postcondition:
-- Returns string with JSON or error message
local r = WikidataScheme.fetch( about )
if not r then
Config.frame = Config.frame or frame or mw.getCurrentFrame()
Config.first()
r = JSONexport.full( WikidataScheme.Request, adjust )
r = failures() .. r
end
return r
end -- WikidataScheme.flat()
WikidataScheme.form = function ( about, assigned, frame )
-- Describe registration elements
-- Precondition:
-- about -- table or JSON string or mw.loadData page name
-- assigned -- true, for resolve table only
-- frame -- frame, if available
-- Postcondition:
-- Returns string with entire HTML table
local r
Config.frame = Config.frame or frame or mw.getCurrentFrame()
if not Text.Multilingual and Text.Multilingual ~= false then
local bib = foreignModule( "Multilingual",
true,
false,
WikidataScheme.globals.Multilingual,
true )
if type( bib ) == "table" and
type( bib.Multilingual ) == "function" then
Text.Multilingual = bib.Multilingual()
else
Text.Multilingual = false
end
end
r = WikidataScheme.fetch( about )
if not r then
Config.first()
if assigned then
r = Resolver.fire( WikidataScheme.Request )
else
r = Table.form( WikidataScheme.Request )
end
end
r = failures() .. r
return r
end -- WikidataScheme.form()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version or "wikidata" or "~"
-- or false
-- Postcondition:
-- Returns string -- with queried version, also if problem
-- false -- if appropriate
-- 2019-10-15
local last = ( atleast == "~" )
local since = atleast
local r
if last or since == "wikidata" then
local item = Failsafe.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 seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues( seek )
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
else
r = vsn.value
end
end
end
end
end
if type( r ) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
-- Export
local p = { }
p.form = function ( frame )
local s = mw.text.trim( frame.args[ 1 ] or "" )
local r
if s ~= "" then
r = WikidataScheme.form( s, false, frame )
end
return r or ""
end -- p.form
p.format = function ( frame )
local s = mw.text.trim( frame.args[ 1 ] or "" )
local r
if s ~= "" then
r = WikidataScheme.flat( s, false, frame )
end
return r or ""
end -- p.form
p.furnished = function ( frame )
local s = mw.text.trim( frame.args[ 1 ] or "" )
local r
if s ~= "" then
r = WikidataScheme.form( s, true, frame )
end
return r or ""
end -- p.furnished
p.JSON = function ( frame )
local s = mw.text.trim( frame.args[ 1 ] or "" )
local r
if s ~= "" then
r = WikidataScheme.flat( s, true, frame )
end
return r or ""
end -- p.JSON
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe()
p.WikidataScheme = function ()
WikidataScheme.Text = Text
return WikidataScheme
end -- p.WikidataScheme
return p
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.