„Modul:Sort/cellDate“ – Versionsunterschied
Erscheinungsbild
[gesichtete Version] | [gesichtete Version] |
Inhalt gelöscht Inhalt hinzugefügt
2020-03-01 |
2024-06-01 |
||
(17 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
local Sort = { suite = "Sort", |
local Sort = { suite = "Sort", |
||
sub = "cellDate", |
sub = "cellDate", |
||
serial = " |
serial = "2024-06-01", |
||
item = |
item = 90149250, |
||
globals = { |
globals = { Cell = 90144855, |
||
DateTime = 20652535 } } |
|||
--[=[ |
--[=[ |
||
Sort/cellDate -- support table cells with sortable date and time |
Sort/cellDate -- support table cells with sortable date and time |
||
Zeile 9: | Zeile 10: | ||
local Failsafe = Sort |
local Failsafe = Sort |
||
local GlobalMod = Sort |
local GlobalMod = Sort |
||
Sort.localized = false |
|||
Sort.mpz = 0.7 |
|||
Sort.maxYear = 2099 |
|||
Sort.minYear = 100 |
|||
Sort.similar = mw.ustring.char( 8776 ) -- ~~ |
|||
Sort.simple = "j M Y" |
|||
Sort.supreme = mw.ustring.char( 8734 ) -- infinit |
|||
Sort.types = { "date", |
|||
"time", |
|||
"isoDate", |
|||
"usLongDate" } |
|||
Sort.weights = { } |
|||
Sort.weights.en = { |
|||
[true] = Sort.similar .. "abeus", |
|||
["before"] = 3, |
|||
["begin"] = 4, |
|||
["begin of"] = 4, |
|||
["beginning"] = 4, |
|||
["beginning of"] = 4, |
|||
["since"] = 6, |
|||
["until"] = 7, |
|||
["end of"] = 8, |
|||
["after"] = 9, |
|||
["about"] = true, |
|||
[Sort.similar] = true |
|||
} |
|||
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 |
|||
-- 2020-01-01 |
|||
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 ) |
|||
end |
|||
end |
|||
return r |
|||
end -- foreignModule() |
|||
local fetch = function ( access, append ) |
|||
-- Fetch global library |
|||
-- Precondition: |
|||
-- access -- string|false, with name of base module |
|||
-- append -- string, with subpage part, if any; or false |
|||
local store, sub, suite |
|||
if access then |
|||
suite = access |
|||
store = access |
|||
else |
|||
suite = Sort.suite |
|||
if append then |
|||
sub = append:lower() |
|||
store = append |
|||
else |
|||
store = "Sorter" |
|||
end |
|||
end |
|||
if type( Sort[ store ] ) == "nil" then |
|||
local bib = foreignModule( suite, |
|||
true, |
|||
sub, |
|||
Sort.globals[ store ], |
|||
true ) |
|||
if type( bib ) == "table" and |
|||
type( bib[ suite ] ) == "function" then |
|||
Sort[ store ] = bib[ suite ]() -- MIGRATE = bib() |
|||
else |
|||
error( tostring( bib ) ) |
|||
end |
|||
end |
|||
end -- fetch() |
|||
local focus = function () |
|||
-- Provide simple date pattern |
|||
-- Postcondition: |
|||
-- Returns simple date pattern |
|||
local r = Sort.simple |
|||
if not Sort.localized then |
|||
Sort.localized = true |
|||
local data = foreignModule( Sort.suite, false, "local" ) |
|||
if data and |
|||
type( data.simpleDatePattern ) == "string" then |
|||
Sort.simple = data.simpleDatePattern |
|||
r = Sort.simple |
|||
end |
|||
end |
|||
return r |
|||
end -- focus() |
|||
local fold = function ( access, alien, assign ) |
|||
-- Retrieve config table |
|||
-- Precondition: |
|||
-- access -- string, external table |
|||
-- alien -- string, language code |
|||
-- assign -- string, local table |
|||
-- Postcondition: |
|||
-- Returns table, or not |
|||
local r |
|||
Sort[ assign ] = Sort[ assign ] or { } |
|||
if type( Sort[ assign ][ alien ] ) == "nil" then |
|||
local data = foreignModule( "DateTime", false, "local" ) |
|||
if data and |
|||
type( data[ access ] ) == "table" then |
|||
Sort[ assign ][ alien ] = data[ access ][ alien ] |
|||
else |
|||
Sort[ assign ][ alien ] = false |
|||
end |
|||
end |
|||
if type( Sort[ assign ][ alien ] ) == "table" then |
|||
r = Sort[ assign ][ alien ] |
|||
end |
|||
return r |
|||
end -- fold() |
|||
local fore = function ( args ) |
|||
-- Create and merge sort attribute |
|||
-- Precondition: |
|||
-- args -- table, parameters |
|||
-- .d -- table, with date |
|||
-- .infinit -- number|nil, out of ages, +/-1 |
|||
-- .pre -- string|false, for prefix |
|||
-- .type -- string|false, for sorting |
|||
-- Postcondition: |
|||
-- attributes extended |
|||
local d = { lang = args.d.lang } |
|||
local latest, least, s, stamp |
|||
if args.pre then |
|||
local weights = fold( "sortWeights", d.lang, "weights" ) |
|||
local i |
|||
if weights then |
|||
i = weights[ args.pre ] |
|||
if type( i ) == "number" then |
|||
if i < 7 then |
|||
least = true |
|||
else |
|||
latest = true |
|||
end |
|||
end |
|||
end |
|||
end |
|||
if args.infinit then |
|||
d.hour = 0 |
|||
if args.infinit > 0 then |
|||
d.year = Sort.maxYear |
|||
d.month = 12 |
|||
d.dom = 31 |
|||
d.min = 59 |
|||
d.sec = 59 |
|||
else |
|||
d.month = 1 |
|||
d.dom = 1 |
|||
d.min = 0 |
|||
d.sec = 0 |
|||
if args.type == "isoDate" then |
|||
d.year = Sort.minYear |
|||
elseif Sort.minYear < 0 then |
|||
d.year = -1 * Sort.minYear |
|||
d.bc = true |
|||
else |
|||
d.year = Sort.minYear |
|||
end |
|||
end |
|||
stamp = string.format( "%04d-%02d-%02d", |
|||
d.year, d.month, d.dom ) |
|||
if args.type == "isoDate" then |
|||
stamp = string.format( "%sT%02d:%02d:%02d", |
|||
stamp, d.hour, d.min, d.sec ) |
|||
end |
|||
elseif args.type == "time" then |
|||
if args.d.hour then |
|||
d.hour = args.d.hour |
|||
elseif least then |
|||
d.hour = 0 |
|||
elseif latest then |
|||
d.hour = 24 |
|||
else |
|||
d.hour = 12 |
|||
end |
|||
if args.d.min then |
|||
d.min = args.d.min |
|||
elseif least then |
|||
d.min = 0 |
|||
elseif latest then |
|||
d.min = 59 |
|||
else |
|||
d.min = 30 |
|||
end |
|||
if args.d.sec then |
|||
d.sec = args.d.sec |
|||
elseif least then |
|||
d.sec = 0 |
|||
elseif latest then |
|||
d.sec = 59 |
|||
else |
|||
d.sec = 30 |
|||
end |
|||
stamp = string.format( "%02d:%02d:%02d", |
|||
d.hour, d.min, d.sec ) |
|||
else |
|||
args.d = Sort.DateTime( args.d ) |
|||
d.year = ( args.d.year or 0 ) |
|||
if args.d.bc and args.type == "isoDate" then |
|||
d.bc = true |
|||
else |
|||
d.year = args.d.year or 0 |
|||
end |
|||
if args.d.month then |
|||
d.month = args.d.month |
|||
elseif least then |
|||
d.month = 1 |
|||
elseif latest then |
|||
d.month = 12 |
|||
else |
|||
d.month = 6 |
|||
end |
|||
if args.d.dom then |
|||
d.dom = args.d.dom |
|||
elseif least then |
|||
d.dom = 1 |
|||
else |
|||
d.dom = tonumber( Sort.DateTime( d ):format( "t" ) ) |
|||
if not latest then |
|||
d.dom = math.floor( 0.5 * d.dom ) |
|||
end |
|||
end |
|||
stamp = string.format( "%04d-%02d-%02d", |
|||
d.year, d.month, d.dom ) |
|||
if args.type == "isoDate" and args.d.hour then |
|||
stamp = string.format( "%sT%02d", |
|||
stamp, args.d.hour ) |
|||
if args.d.min then |
|||
stamp = string.format( "%s:%02d", |
|||
stamp, args.d.min ) |
|||
if args.d.sec then |
|||
stamp = string.format( "%s:%02d", |
|||
stamp, args.d.sec ) |
|||
end |
|||
end |
|||
end |
|||
end |
|||
if args.type == "isoDate" then |
|||
s = "c" |
|||
elseif args.type == "time" then |
|||
s = "H:i:s" |
|||
elseif args.type == "usLongDate" then |
|||
d.lang = "en" |
|||
s = "F j, Y H:i:s" |
|||
else |
|||
s = focus() |
|||
end |
|||
s = Sort.Cell.formatDate( s, stamp, true ) |
|||
if args.infinit then |
|||
if args.infinit > 0 then |
|||
s = s:gsub( tostring( Sort.maxYear ), "9999" ) |
|||
elseif args.type == "isoDate" then |
|||
s = s:gsub( string.format( "^%04d", Sort.minYear ), |
|||
"-999999" ) |
|||
end |
|||
elseif args.type == "isoDate" and d.bc then |
|||
s = "-" .. s |
|||
end |
|||
Sort.Cell.faced( args, s ) |
|||
end -- fore() |
|||
local format = function ( args ) |
|||
-- Format visible date |
|||
-- Precondition: |
|||
-- args -- table, parameters |
|||
-- .d -- table, with date |
|||
-- .pattern -- string, with format |
|||
-- .target -- string|nil, for formatting |
|||
-- .url -- string|nil, for formatting |
|||
-- .pad -- boolean, for padding |
|||
-- .pre -- string, for prefix |
|||
-- .post -- string, for postfix |
|||
-- .type -- string, for sorting |
|||
-- Postcondition: |
|||
-- Returns string |
|||
local r, templates |
|||
if not args.d.lang then |
|||
args.d.lang = Sort.Cell.facility() |
|||
end |
|||
if args.pad and not args.pre then |
|||
local scheme = args.pattern |
|||
if scheme then |
|||
local templates = fold( "templates", |
|||
Sort.Cell.facility(), |
|||
"templates" ) |
|||
if templates and |
|||
type( templates[ scheme ] ) == "table" and |
|||
type( templates[ scheme ].spec ) == "string" then |
|||
scheme = templates[ scheme ].spec |
|||
end |
|||
end |
|||
if scheme then |
|||
local lift |
|||
if args.type == "time" then |
|||
lift = ( scheme:sub( 1, 1 ) == "G" and |
|||
args.d.hour and |
|||
args.d.hour < 10 ) |
|||
else |
|||
lift = ( scheme:sub( 1, 1 ) == "j" and |
|||
args.d.dom and |
|||
args.d.dom < 10 ) |
|||
end |
|||
if lift then |
|||
if not Sort.shift then |
|||
if Sort.Cell.following() then |
|||
Sort.shift = "left" |
|||
else |
|||
Sort.shift = "right" |
|||
end |
|||
Sort.shift = "padding-" .. Sort.shift |
|||
end |
|||
Sort.Cell.feature( args, |
|||
Sort.shift, |
|||
string.format( "%.2fem !important", |
|||
Sort.mpz ) ) |
|||
end |
|||
end |
|||
end |
|||
r = args.d:format( args.pattern or "*" ) |
|||
if type( args.target ) == "string" then |
|||
if r == args.target then |
|||
r = string.format( "[[%s]]", r ) |
|||
else |
|||
r = string.format( "[[%s|%s]]", args.target, r ) |
|||
end |
|||
elseif type( args.url ) == "string" then |
|||
r = string.format( "[%s %s]", args.url, r ) |
|||
end |
|||
if args.pre or args.post then |
|||
local e |
|||
if args.pre then |
|||
r = string.format( "%s %s", args.pre, r ) |
|||
end |
|||
if args.post then |
|||
r = string.format( "%s %s", r, args.post ) |
|||
end |
|||
e = mw.html.create( "span" ) |
|||
:css( "white-space", "nowrap" ) |
|||
:wikitext( r ) |
|||
r = tostring( e ) |
|||
end |
|||
return r |
|||
end -- format() |
|||
local furnish = function ( args ) |
|||
-- Execute task |
|||
-- Parameter: |
|||
-- args -- table, parameters |
|||
-- Postcondition: |
|||
-- Returns string, or expands .cell |
|||
-- Throws error on failure |
|||
local r |
|||
fetch( false, "Cell" ) |
|||
fetch( "DateTime" ) |
|||
if type( args ) == "table" then |
|||
local present = Sort.Cell.first( args, true ) |
|||
local s |
|||
Sort.Cell.fair( args, "d", present ) |
|||
if not present.lang then |
|||
present.lang = Sort.Cell.facility() |
|||
end |
|||
if type( present.d ) == "string" and |
|||
mw.ustring.find( present.d, Sort.supreme, 1, true ) then |
|||
s = mw.text.trim( present.d ) |
|||
if s == Sort.supreme then |
|||
present.infinit = 1 |
|||
elseif mw.ustring.len( s ) == 2 and |
|||
mw.ustring.codepoint( s, 2, 2 ) == 8734 then |
|||
local m = mw.ustring.codepoint( s, 1, 1 ) |
|||
if m == 45 or m == 8722 then |
|||
present.infinit = -1 |
|||
elseif m == 43 then |
|||
present.infinit = 1 |
|||
end |
|||
end |
|||
end |
|||
if present.infinit then |
|||
present.d = { lang = Sort.Cell.facility() } |
|||
else |
|||
Sort.Cell.fair( args, "pre", present ) |
|||
s = type( present.d ) |
|||
if s == "string" and not present.pre then |
|||
local weights = fold( "sortWeights", |
|||
present.lang, |
|||
"weights" ) |
|||
if weights and weights[ true ] then |
|||
local sw = weights[ true ] |
|||
if type( sw ) == "string" then |
|||
local slim |
|||
slim = mw.ustring.sub( present.d, 1, 1 ) |
|||
slim = mw.ustring.lower( slim ) |
|||
if mw.ustring.find( sw, slim, 1, true ) then |
|||
local n |
|||
for k, v in pairs( weights ) do |
|||
if type( k ) == "string" then |
|||
n = mw.ustring.len( k ) |
|||
slim = mw.ustring.sub( present.d, |
|||
1, |
|||
n ) |
|||
if slim == k then |
|||
present.pre = k |
|||
present.d = mw.text.trim( |
|||
mw.ustring.sub( present.d, |
|||
n + 1 ) ) |
|||
break -- for k, v |
|||
end |
|||
end |
|||
end -- for k, v |
|||
end |
|||
end |
|||
end |
|||
end |
|||
if s == "string" then |
|||
if present.d == "" then |
|||
s = "now" |
|||
else |
|||
s = present.d |
|||
end |
|||
present.d = Sort.DateTime( s, args.lang ) |
|||
elseif s ~= "table" then |
|||
present.d = Sort.DateTime( "now", args.lang ) |
|||
end |
|||
end |
|||
if type( present.d ) == "table" then |
|||
if present.d.hour then |
|||
local memory = present.d.sec |
|||
present.d:fix() |
|||
if not memory then |
|||
present.d.sec = nil |
|||
end |
|||
end |
|||
Sort.Cell.fair( args, "type", present ) |
|||
if type( present.type ) == "string" then |
|||
local n |
|||
s = present.type |
|||
n = #s |
|||
if n > 0 then |
|||
local sort |
|||
s = s:lower() |
|||
for i = 1, #Sort.types do |
|||
sort = Sort.types[ i ]:sub( 1, n ):lower() |
|||
if s == sort then |
|||
present.type = Sort.types[ i ] |
|||
break -- for i |
|||
end |
|||
end -- i = 1, #Sort.types |
|||
end |
|||
end |
|||
if not present.infinit then |
|||
Sort.Cell.fair( args, "pattern", present ) |
|||
if present.pattern ~= "-" then |
|||
if present.pattern then |
|||
present.pattern = |
|||
present.pattern:gsub( "\\ ", " " ) |
|||
:gsub( " ", " " ) |
|||
end |
|||
Sort.Cell.fair( args, "target", present ) |
|||
Sort.Cell.fair( args, "url", present ) |
|||
s = type( args.pad ) |
|||
if s == "string" then |
|||
present.pad = ( args.pad == "1" ) |
|||
elseif s == "boolean" then |
|||
present.pad = args.pad |
|||
end |
|||
Sort.Cell.fair( args, "post", present ) |
|||
r = format( present ) |
|||
end |
|||
end |
|||
fore( present ) |
|||
r = Sort.Cell.finalize( present, r ) |
|||
else |
|||
r = Sort.Cell.fault( "?!?!?!", args ) |
|||
end |
|||
else |
|||
error( "'args' is not a table" ) |
|||
end |
|||
return r |
|||
end -- furnish() |
|||
Sort.f = function ( args ) |
|||
-- Create table cell start |
|||
-- Parameter: |
|||
-- args -- table, parameters |
|||
-- .d -- string|table, with date |
|||
-- .pattern -- string, with format |
|||
-- .lang -- string, for formatting |
|||
-- .target -- string|nil, for formatting |
|||
-- .url -- strin|nil, for formatting |
|||
-- .pad -- boolean, for padding |
|||
-- .pre -- string, for prefix |
|||
-- .post -- string, for postfix |
|||
-- .cell -- table|nil, sort environment |
|||
-- .type -- string, for sorting mode |
|||
-- .rowspan -- number|string, for cell attribute |
|||
-- .colspan -- number|string, for cell attribute |
|||
-- .class -- string, for cell attribute |
|||
-- .style -- string|table, for cell attribute |
|||
-- .id -- string, for cell attribute |
|||
-- .dir -- string, for cell attribute |
|||
-- .cat -- string|nil, for error category |
|||
-- Postcondition: |
|||
-- Returns string, or expands .cell |
|||
local lucky, r = pcall( furnish, args ) |
|||
if not lucky then |
|||
local e = mw.html.create( "span" ) |
|||
:addClass( "error" ) |
|||
:wikitext( "Module:Sort/cell * " .. r ) |
|||
if type( args.cell ) == "table" and |
|||
type( args.cell.wikitext ) == "function" then |
|||
args.cell:node( e ) |
|||
else |
|||
r = tostring( e ) |
|||
end |
|||
end |
|||
return r |
|||
end -- Sort.f() |
|||
Sort.furnish = function () |
|||
-- Retrieve list of project prefixes |
|||
-- Postcondition: |
|||
-- Returns string -- with wikitext list |
|||
-- false -- if none |
|||
local r, weights |
|||
fetch( false, "Cell" ) |
|||
weights = fold( "sortWeights", Sort.Cell.facility(), "weights" ) |
|||
if weights and weights[ true ] then |
|||
local order = { } |
|||
for k, v in pairs( weights ) do |
|||
if type( k ) == "string" then |
|||
table.insert( order, k ) |
|||
end |
|||
end -- for k, v |
|||
table.sort( order ) |
|||
for i = 1, #order do |
|||
if r then |
|||
r = r .. "\n" |
|||
else |
|||
r = "" |
|||
end |
|||
r = string.format( "%s* %s", r, order[ i ] ) |
|||
end -- i = 1, #order |
|||
end |
|||
return r |
|||
end -- Sort.furnish() |
|||
Zeile 15: | Zeile 623: | ||
-- Retrieve versioning and check for compliance |
-- Retrieve versioning and check for compliance |
||
-- Precondition: |
-- Precondition: |
||
-- atleast -- string, with required version |
-- atleast -- string, with required version |
||
-- or false |
-- or wikidata|item|~|@ or false |
||
-- Postcondition: |
-- Postcondition: |
||
-- Returns string -- with queried version, also if problem |
-- Returns string -- with queried version/item, also if problem |
||
-- false -- if appropriate |
-- false -- if appropriate |
||
-- |
-- 2024-03-01 |
||
local |
local since = atleast |
||
local since = |
local last = ( since == "~" ) |
||
local linked = ( since == "@" ) |
|||
local link = ( since == "item" ) |
|||
local r |
local r |
||
if last or since == "wikidata" then |
if last or link or linked or since == "wikidata" then |
||
local item = Failsafe.item |
local item = Failsafe.item |
||
since = false |
since = false |
||
if type( item ) == "number" and item > 0 then |
if type( item ) == "number" and item > 0 then |
||
local |
local suited = string.format( "Q%d", item ) |
||
if link then |
|||
item ) ) |
|||
r = suited |
|||
else |
|||
local seek = Failsafe.serialProperty or "P348" |
|||
local |
local entity = mw.wikibase.getEntity( suited ) |
||
if type( |
if type( entity ) == "table" then |
||
local seek = Failsafe.serialProperty or "P348" |
|||
vsn |
local vsn = entity:formatPropertyValues( seek ) |
||
if |
if type( vsn ) == "table" and |
||
type( vsn.value ) == "string" and |
|||
vsn.value ~= "" then |
|||
if last and vsn.value == Failsafe.serial then |
|||
r = false |
|||
elseif linked then |
|||
if mw.title.getCurrentTitle().prefixedText |
|||
== mw.wikibase.getSitelink( suited ) then |
|||
r = false |
|||
else |
|||
r = suited |
|||
end |
|||
else |
|||
r = vsn.value |
|||
end |
|||
end |
end |
||
end |
end |
||
end |
end |
||
elseif link then |
|||
r = false |
|||
end |
end |
||
end |
end |
||
Zeile 59: | Zeile 682: | ||
-- Export |
-- Export |
||
local p = { } |
local p = { } |
||
p.f = function ( frame ) |
|||
-- Template call |
|||
Sort.frame = frame |
|||
return Sort.f( frame.args ) or "" |
|||
end -- p.f |
|||
p.failsafe = function ( frame ) |
p.failsafe = function ( frame ) |
||
Zeile 77: | Zeile 706: | ||
return Failsafe.failsafe( since ) or "" |
return Failsafe.failsafe( since ) or "" |
||
end -- p.failsafe |
end -- p.failsafe |
||
p.furnish = function () |
|||
return Sort.furnish() or "" |
|||
end -- p.f |
|||
p.Sort = function () |
p.Sort = function () |
||
Zeile 82: | Zeile 715: | ||
return Sort |
return Sort |
||
end |
end |
||
setmetatable( p, { __call = function ( func, ... ) |
|||
setmetatable( p, nil ) |
|||
return Failsafe |
|||
end } ) |
|||
return p |
return p |
Aktuelle Version vom 27. Juni 2024, 13:04 Uhr
Vorlagenprogrammierung | Diskussionen | Lua | Test | 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:
2024-06-01
local Sort = { suite = "Sort",
sub = "cellDate",
serial = "2024-06-01",
item = 90149250,
globals = { Cell = 90144855,
DateTime = 20652535 } }
--[=[
Sort/cellDate -- support table cells with sortable date and time
]=]
local Failsafe = Sort
local GlobalMod = Sort
Sort.localized = false
Sort.mpz = 0.7
Sort.maxYear = 2099
Sort.minYear = 100
Sort.similar = mw.ustring.char( 8776 ) -- ~~
Sort.simple = "j M Y"
Sort.supreme = mw.ustring.char( 8734 ) -- infinit
Sort.types = { "date",
"time",
"isoDate",
"usLongDate" }
Sort.weights = { }
Sort.weights.en = {
[true] = Sort.similar .. "abeus",
["before"] = 3,
["begin"] = 4,
["begin of"] = 4,
["beginning"] = 4,
["beginning of"] = 4,
["since"] = 6,
["until"] = 7,
["end of"] = 8,
["after"] = 9,
["about"] = true,
[Sort.similar] = true
}
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
-- 2020-01-01
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 )
end
end
return r
end -- foreignModule()
local fetch = function ( access, append )
-- Fetch global library
-- Precondition:
-- access -- string|false, with name of base module
-- append -- string, with subpage part, if any; or false
local store, sub, suite
if access then
suite = access
store = access
else
suite = Sort.suite
if append then
sub = append:lower()
store = append
else
store = "Sorter"
end
end
if type( Sort[ store ] ) == "nil" then
local bib = foreignModule( suite,
true,
sub,
Sort.globals[ store ],
true )
if type( bib ) == "table" and
type( bib[ suite ] ) == "function" then
Sort[ store ] = bib[ suite ]() -- MIGRATE = bib()
else
error( tostring( bib ) )
end
end
end -- fetch()
local focus = function ()
-- Provide simple date pattern
-- Postcondition:
-- Returns simple date pattern
local r = Sort.simple
if not Sort.localized then
Sort.localized = true
local data = foreignModule( Sort.suite, false, "local" )
if data and
type( data.simpleDatePattern ) == "string" then
Sort.simple = data.simpleDatePattern
r = Sort.simple
end
end
return r
end -- focus()
local fold = function ( access, alien, assign )
-- Retrieve config table
-- Precondition:
-- access -- string, external table
-- alien -- string, language code
-- assign -- string, local table
-- Postcondition:
-- Returns table, or not
local r
Sort[ assign ] = Sort[ assign ] or { }
if type( Sort[ assign ][ alien ] ) == "nil" then
local data = foreignModule( "DateTime", false, "local" )
if data and
type( data[ access ] ) == "table" then
Sort[ assign ][ alien ] = data[ access ][ alien ]
else
Sort[ assign ][ alien ] = false
end
end
if type( Sort[ assign ][ alien ] ) == "table" then
r = Sort[ assign ][ alien ]
end
return r
end -- fold()
local fore = function ( args )
-- Create and merge sort attribute
-- Precondition:
-- args -- table, parameters
-- .d -- table, with date
-- .infinit -- number|nil, out of ages, +/-1
-- .pre -- string|false, for prefix
-- .type -- string|false, for sorting
-- Postcondition:
-- attributes extended
local d = { lang = args.d.lang }
local latest, least, s, stamp
if args.pre then
local weights = fold( "sortWeights", d.lang, "weights" )
local i
if weights then
i = weights[ args.pre ]
if type( i ) == "number" then
if i < 7 then
least = true
else
latest = true
end
end
end
end
if args.infinit then
d.hour = 0
if args.infinit > 0 then
d.year = Sort.maxYear
d.month = 12
d.dom = 31
d.min = 59
d.sec = 59
else
d.month = 1
d.dom = 1
d.min = 0
d.sec = 0
if args.type == "isoDate" then
d.year = Sort.minYear
elseif Sort.minYear < 0 then
d.year = -1 * Sort.minYear
d.bc = true
else
d.year = Sort.minYear
end
end
stamp = string.format( "%04d-%02d-%02d",
d.year, d.month, d.dom )
if args.type == "isoDate" then
stamp = string.format( "%sT%02d:%02d:%02d",
stamp, d.hour, d.min, d.sec )
end
elseif args.type == "time" then
if args.d.hour then
d.hour = args.d.hour
elseif least then
d.hour = 0
elseif latest then
d.hour = 24
else
d.hour = 12
end
if args.d.min then
d.min = args.d.min
elseif least then
d.min = 0
elseif latest then
d.min = 59
else
d.min = 30
end
if args.d.sec then
d.sec = args.d.sec
elseif least then
d.sec = 0
elseif latest then
d.sec = 59
else
d.sec = 30
end
stamp = string.format( "%02d:%02d:%02d",
d.hour, d.min, d.sec )
else
args.d = Sort.DateTime( args.d )
d.year = ( args.d.year or 0 )
if args.d.bc and args.type == "isoDate" then
d.bc = true
else
d.year = args.d.year or 0
end
if args.d.month then
d.month = args.d.month
elseif least then
d.month = 1
elseif latest then
d.month = 12
else
d.month = 6
end
if args.d.dom then
d.dom = args.d.dom
elseif least then
d.dom = 1
else
d.dom = tonumber( Sort.DateTime( d ):format( "t" ) )
if not latest then
d.dom = math.floor( 0.5 * d.dom )
end
end
stamp = string.format( "%04d-%02d-%02d",
d.year, d.month, d.dom )
if args.type == "isoDate" and args.d.hour then
stamp = string.format( "%sT%02d",
stamp, args.d.hour )
if args.d.min then
stamp = string.format( "%s:%02d",
stamp, args.d.min )
if args.d.sec then
stamp = string.format( "%s:%02d",
stamp, args.d.sec )
end
end
end
end
if args.type == "isoDate" then
s = "c"
elseif args.type == "time" then
s = "H:i:s"
elseif args.type == "usLongDate" then
d.lang = "en"
s = "F j, Y H:i:s"
else
s = focus()
end
s = Sort.Cell.formatDate( s, stamp, true )
if args.infinit then
if args.infinit > 0 then
s = s:gsub( tostring( Sort.maxYear ), "9999" )
elseif args.type == "isoDate" then
s = s:gsub( string.format( "^%04d", Sort.minYear ),
"-999999" )
end
elseif args.type == "isoDate" and d.bc then
s = "-" .. s
end
Sort.Cell.faced( args, s )
end -- fore()
local format = function ( args )
-- Format visible date
-- Precondition:
-- args -- table, parameters
-- .d -- table, with date
-- .pattern -- string, with format
-- .target -- string|nil, for formatting
-- .url -- string|nil, for formatting
-- .pad -- boolean, for padding
-- .pre -- string, for prefix
-- .post -- string, for postfix
-- .type -- string, for sorting
-- Postcondition:
-- Returns string
local r, templates
if not args.d.lang then
args.d.lang = Sort.Cell.facility()
end
if args.pad and not args.pre then
local scheme = args.pattern
if scheme then
local templates = fold( "templates",
Sort.Cell.facility(),
"templates" )
if templates and
type( templates[ scheme ] ) == "table" and
type( templates[ scheme ].spec ) == "string" then
scheme = templates[ scheme ].spec
end
end
if scheme then
local lift
if args.type == "time" then
lift = ( scheme:sub( 1, 1 ) == "G" and
args.d.hour and
args.d.hour < 10 )
else
lift = ( scheme:sub( 1, 1 ) == "j" and
args.d.dom and
args.d.dom < 10 )
end
if lift then
if not Sort.shift then
if Sort.Cell.following() then
Sort.shift = "left"
else
Sort.shift = "right"
end
Sort.shift = "padding-" .. Sort.shift
end
Sort.Cell.feature( args,
Sort.shift,
string.format( "%.2fem !important",
Sort.mpz ) )
end
end
end
r = args.d:format( args.pattern or "*" )
if type( args.target ) == "string" then
if r == args.target then
r = string.format( "[[%s]]", r )
else
r = string.format( "[[%s|%s]]", args.target, r )
end
elseif type( args.url ) == "string" then
r = string.format( "[%s %s]", args.url, r )
end
if args.pre or args.post then
local e
if args.pre then
r = string.format( "%s %s", args.pre, r )
end
if args.post then
r = string.format( "%s %s", r, args.post )
end
e = mw.html.create( "span" )
:css( "white-space", "nowrap" )
:wikitext( r )
r = tostring( e )
end
return r
end -- format()
local furnish = function ( args )
-- Execute task
-- Parameter:
-- args -- table, parameters
-- Postcondition:
-- Returns string, or expands .cell
-- Throws error on failure
local r
fetch( false, "Cell" )
fetch( "DateTime" )
if type( args ) == "table" then
local present = Sort.Cell.first( args, true )
local s
Sort.Cell.fair( args, "d", present )
if not present.lang then
present.lang = Sort.Cell.facility()
end
if type( present.d ) == "string" and
mw.ustring.find( present.d, Sort.supreme, 1, true ) then
s = mw.text.trim( present.d )
if s == Sort.supreme then
present.infinit = 1
elseif mw.ustring.len( s ) == 2 and
mw.ustring.codepoint( s, 2, 2 ) == 8734 then
local m = mw.ustring.codepoint( s, 1, 1 )
if m == 45 or m == 8722 then
present.infinit = -1
elseif m == 43 then
present.infinit = 1
end
end
end
if present.infinit then
present.d = { lang = Sort.Cell.facility() }
else
Sort.Cell.fair( args, "pre", present )
s = type( present.d )
if s == "string" and not present.pre then
local weights = fold( "sortWeights",
present.lang,
"weights" )
if weights and weights[ true ] then
local sw = weights[ true ]
if type( sw ) == "string" then
local slim
slim = mw.ustring.sub( present.d, 1, 1 )
slim = mw.ustring.lower( slim )
if mw.ustring.find( sw, slim, 1, true ) then
local n
for k, v in pairs( weights ) do
if type( k ) == "string" then
n = mw.ustring.len( k )
slim = mw.ustring.sub( present.d,
1,
n )
if slim == k then
present.pre = k
present.d = mw.text.trim(
mw.ustring.sub( present.d,
n + 1 ) )
break -- for k, v
end
end
end -- for k, v
end
end
end
end
if s == "string" then
if present.d == "" then
s = "now"
else
s = present.d
end
present.d = Sort.DateTime( s, args.lang )
elseif s ~= "table" then
present.d = Sort.DateTime( "now", args.lang )
end
end
if type( present.d ) == "table" then
if present.d.hour then
local memory = present.d.sec
present.d:fix()
if not memory then
present.d.sec = nil
end
end
Sort.Cell.fair( args, "type", present )
if type( present.type ) == "string" then
local n
s = present.type
n = #s
if n > 0 then
local sort
s = s:lower()
for i = 1, #Sort.types do
sort = Sort.types[ i ]:sub( 1, n ):lower()
if s == sort then
present.type = Sort.types[ i ]
break -- for i
end
end -- i = 1, #Sort.types
end
end
if not present.infinit then
Sort.Cell.fair( args, "pattern", present )
if present.pattern ~= "-" then
if present.pattern then
present.pattern =
present.pattern:gsub( "\\ ", " " )
:gsub( " ", " " )
end
Sort.Cell.fair( args, "target", present )
Sort.Cell.fair( args, "url", present )
s = type( args.pad )
if s == "string" then
present.pad = ( args.pad == "1" )
elseif s == "boolean" then
present.pad = args.pad
end
Sort.Cell.fair( args, "post", present )
r = format( present )
end
end
fore( present )
r = Sort.Cell.finalize( present, r )
else
r = Sort.Cell.fault( "?!?!?!", args )
end
else
error( "'args' is not a table" )
end
return r
end -- furnish()
Sort.f = function ( args )
-- Create table cell start
-- Parameter:
-- args -- table, parameters
-- .d -- string|table, with date
-- .pattern -- string, with format
-- .lang -- string, for formatting
-- .target -- string|nil, for formatting
-- .url -- strin|nil, for formatting
-- .pad -- boolean, for padding
-- .pre -- string, for prefix
-- .post -- string, for postfix
-- .cell -- table|nil, sort environment
-- .type -- string, for sorting mode
-- .rowspan -- number|string, for cell attribute
-- .colspan -- number|string, for cell attribute
-- .class -- string, for cell attribute
-- .style -- string|table, for cell attribute
-- .id -- string, for cell attribute
-- .dir -- string, for cell attribute
-- .cat -- string|nil, for error category
-- Postcondition:
-- Returns string, or expands .cell
local lucky, r = pcall( furnish, args )
if not lucky then
local e = mw.html.create( "span" )
:addClass( "error" )
:wikitext( "Module:Sort/cell * " .. r )
if type( args.cell ) == "table" and
type( args.cell.wikitext ) == "function" then
args.cell:node( e )
else
r = tostring( e )
end
end
return r
end -- Sort.f()
Sort.furnish = function ()
-- Retrieve list of project prefixes
-- Postcondition:
-- Returns string -- with wikitext list
-- false -- if none
local r, weights
fetch( false, "Cell" )
weights = fold( "sortWeights", Sort.Cell.facility(), "weights" )
if weights and weights[ true ] then
local order = { }
for k, v in pairs( weights ) do
if type( k ) == "string" then
table.insert( order, k )
end
end -- for k, v
table.sort( order )
for i = 1, #order do
if r then
r = r .. "\n"
else
r = ""
end
r = string.format( "%s* %s", r, order[ i ] )
end -- i = 1, #order
end
return r
end -- Sort.furnish()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2024-03-01
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )
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
elseif linked then
if mw.title.getCurrentTitle().prefixedText
== mw.wikibase.getSitelink( suited ) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
elseif link then
r = false
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.f = function ( frame )
-- Template call
Sort.frame = frame
return Sort.f( frame.args ) or ""
end -- p.f
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.furnish = function ()
return Sort.furnish() or ""
end -- p.f
p.Sort = function ()
-- Module interface
return Sort
end
setmetatable( p, { __call = function ( func, ... )
setmetatable( p, nil )
return Failsafe
end } )
return p