Modul:URIutil: Unterschied zwischen den Versionen
te>PerfektesChaos (fix) |
Admin (Diskussion | Beiträge) K (41 Versionen importiert) |
||
(33 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
− | --[=[ | + | local URIutil = { suite = "URIutil", |
+ | serial = "2019-08-07", | ||
+ | item = 19644443 }; | ||
+ | --[=[ | ||
Utilities for URI etc. | Utilities for URI etc. | ||
* coreISSN() | * coreISSN() | ||
Zeile 9: | Zeile 12: | ||
* isEscValid() | * isEscValid() | ||
* isGTINvalid() | * isGTINvalid() | ||
+ | * isHandle() | ||
* isISBN() | * isISBN() | ||
* isISBNvalid() | * isISBNvalid() | ||
* isISSNvalid() | * isISSNvalid() | ||
* isLCCN() | * isLCCN() | ||
+ | * linkDNBopac() | ||
* linkDOI() | * linkDOI() | ||
+ | * linkHandle() | ||
* linkISBN() | * linkISBN() | ||
* linkISSN() | * linkISSN() | ||
* linkLCCN() | * linkLCCN() | ||
+ | * linkURN() | ||
* mayDOI() | * mayDOI() | ||
+ | * mayHandle() | ||
* mayISBN() | * mayISBN() | ||
* mayISSN() | * mayISSN() | ||
Zeile 24: | Zeile 32: | ||
* mayURN() | * mayURN() | ||
* plainISBN() | * plainISBN() | ||
+ | * targetISSN() | ||
* uriDOI() | * uriDOI() | ||
+ | * uriHandle() | ||
+ | * uriURN() | ||
+ | * failsafe() | ||
* URIutil() | * URIutil() | ||
− | loadData: URIutil/config URIutil/isbn | + | loadData: URIutil/config URIutil/isbn URIutil/urn |
]=] | ]=] | ||
− | + | local Failsafe = URIutil | |
− | + | local CurrentPageName | |
− | |||
− | |||
− | local | ||
Zeile 144: | Zeile 153: | ||
return ( 11 - r % 11 ); | return ( 11 - r % 11 ); | ||
end -- fair() | end -- fair() | ||
+ | |||
+ | |||
+ | |||
+ | local fault = function ( alert ) | ||
+ | -- Format error message by class=error | ||
+ | -- Parameter: | ||
+ | -- alert -- string, error message | ||
+ | -- Returns: | ||
+ | -- string, HTML span | ||
+ | return tostring( mw.html.create( "span" ) | ||
+ | :addClass( "error" ) | ||
+ | :wikitext( alert ) ); | ||
+ | end -- fault() | ||
+ | |||
+ | |||
+ | |||
+ | local fetch = function ( acquire ) | ||
+ | -- Load data submodule | ||
+ | -- Precondition: | ||
+ | -- acquire -- string, one of | ||
+ | -- "config" | ||
+ | -- "isbn" | ||
+ | -- "urn" | ||
+ | -- Postcondition: | ||
+ | -- Returns any table | ||
+ | local r; | ||
+ | if URIutil.data then | ||
+ | r = URIutil.data[ acquire ]; | ||
+ | else | ||
+ | URIutil.data = { }; | ||
+ | end | ||
+ | if not r then | ||
+ | local lucky; | ||
+ | lucky, r = pcall( mw.loadData, "Module:URIutil/" .. acquire ); | ||
+ | if type( r ) ~= "table" then | ||
+ | r = { }; | ||
+ | end | ||
+ | URIutil.data[ acquire ] = r; | ||
+ | end | ||
+ | return r; | ||
+ | end -- fetch() | ||
+ | |||
+ | |||
+ | |||
+ | local flop = function ( alert ) | ||
+ | -- Create link to (maintenance) category | ||
+ | -- Precondition: | ||
+ | -- alert -- trimmed string with title, not empty, or nil | ||
+ | -- Postcondition: | ||
+ | -- Returns link, or false | ||
+ | local r; | ||
+ | if type( alert ) == "string" and alert ~= "" then | ||
+ | r = string.format( "[[Category:%s]]", alert ); | ||
+ | end | ||
+ | return r; | ||
+ | end -- flop() | ||
Zeile 167: | Zeile 232: | ||
return r; | return r; | ||
end -- format() | end -- format() | ||
+ | |||
+ | |||
+ | |||
+ | local fullPageName = function () | ||
+ | -- Retrieve current page name | ||
+ | -- Postcondition: | ||
+ | -- Returns string: current page name | ||
+ | if not CurrentPageName then | ||
+ | CurrentPageName = mw.title.getCurrentTitle().fullText; | ||
+ | end | ||
+ | return CurrentPageName; | ||
+ | end -- fullPageName() | ||
Zeile 204: | Zeile 281: | ||
lead = false; | lead = false; | ||
else -- even | else -- even | ||
− | r | + | r = r + k + k; |
lead = true; | lead = true; | ||
end | end | ||
Zeile 243: | Zeile 320: | ||
local r; | local r; | ||
if type( attempt ) == "string" then | if type( attempt ) == "string" then | ||
+ | local s; | ||
r = factory( attempt, 10 ); | r = factory( attempt, 10 ); | ||
− | if type( r ) == "table" then | + | s = type( r ); |
+ | if s == "number" and r ~= 10 and r > 6 and r < 13 then | ||
+ | r = factory( attempt, r ); | ||
+ | s = type( r ); | ||
+ | end | ||
+ | if s == "table" then | ||
if r.type == 13 then | if r.type == 13 then | ||
if r[1] ~= 9 or | if r[1] ~= 9 or | ||
Zeile 323: | Zeile 406: | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns number of digits, at least 0 | -- Returns number of digits, at least 0 | ||
− | local r = 0; | + | local r = 0; |
− | local | + | local def = fetch( "isbn" ); |
− | + | local bookland = def[ apply ]; | |
− | + | if type( bookland ) == "table" then | |
− | + | local country = bookland[ allocate ]; | |
− | + | if type( country ) == "table" then | |
− | + | local e, i, j, k, m, v; | |
− | + | for i = 1, 4 do | |
− | + | v = country[ i ]; | |
− | + | if type( v ) == "table" then | |
− | + | m = tonumber( format( assigned, already, i ) ); | |
− | + | for k, e in pairs( v ) do | |
− | + | if m >= e[ 1 ] and m <= e[ 2 ] then | |
− | + | r = e[ 3 ]; | |
− | + | break; -- for k | |
− | + | end | |
− | + | end -- for k | |
− | + | end | |
− | + | if r > 0 then | |
− | + | break; -- for i | |
− | + | end | |
− | + | end -- for i | |
− | |||
− | |||
end | end | ||
end | end | ||
Zeile 378: | Zeile 459: | ||
else | else | ||
k = 2; | k = 2; | ||
− | if assigned[ j + 1 ] > 4 then | + | if assigned[ j ] == 9 and |
+ | assigned[ j + 1 ] > 4 then | ||
k = 3; | k = 3; | ||
if assigned[ j + 1 ] > 8 then | if assigned[ j + 1 ] > 8 then | ||
k = 4; | k = 4; | ||
if assigned[ j + 2 ] > 8 then | if assigned[ j + 2 ] > 8 then | ||
− | k = | + | k = 5; |
end | end | ||
end | end | ||
Zeile 390: | Zeile 472: | ||
if k then | if k then | ||
n = format( assigned, j, k ); | n = format( assigned, j, k ); | ||
− | r = | + | r = string.format( "%s%s-", r, n ); |
j = j + k; | j = j + k; | ||
n = ISBNfold( assigned, m, tonumber( n ), j ); | n = ISBNfold( assigned, m, tonumber( n ), j ); | ||
if n > 0 then | if n > 0 then | ||
− | r = r | + | r = string.format( "%s%s-", r, format( assigned, j, n ) ); |
j = j + n; | j = j + n; | ||
end | end | ||
Zeile 402: | Zeile 484: | ||
r = r .. "-X"; | r = r .. "-X"; | ||
else | else | ||
− | r = | + | r = string.format( "%s-%s", |
+ | r, | ||
+ | tostring( assigned[ assigned.type ] ) ); | ||
end | end | ||
if not r then | if not r then | ||
Zeile 458: | Zeile 542: | ||
local r; | local r; | ||
if assert.type == 8 then | if assert.type == 8 then | ||
− | + | local k = fair( assert ); | |
+ | if k == 11 then | ||
+ | r = ( assert[ 8 ] == 0 ); | ||
+ | else | ||
+ | r = ( assert[ 8 ] == k ); | ||
+ | end | ||
elseif assert.type == 13 then | elseif assert.type == 13 then | ||
r = GTINfaith( assert ); | r = GTINfaith( assert ); | ||
Zeile 480: | Zeile 569: | ||
local x; | local x; | ||
if assigned.type == 8 then | if assigned.type == 8 then | ||
− | r = format( assigned, 1, 4 ) | + | r = string.format( "%s-%s", |
− | + | format( assigned, 1, 4 ), | |
+ | format( assigned, 5, 3 ) ); | ||
x = assigned[ 8 ]; | x = assigned[ 8 ]; | ||
elseif assigned.type == 13 then | elseif assigned.type == 13 then | ||
− | r = format( assigned, 4, 4 ) | + | r = string.format( "%s-%s", |
− | + | format( assigned, 4, 4 ), | |
+ | format( assigned, 8, 3 ) ); | ||
x = fair( assigned ); | x = fair( assigned ); | ||
end | end | ||
Zeile 495: | Zeile 586: | ||
elseif achieve == 13 then | elseif achieve == 13 then | ||
if assigned.type == 8 then | if assigned.type == 8 then | ||
− | r = "977-" | + | r = string.format( "977-%s-00-%s", |
− | + | format( assigned, 1, 7 ), | |
+ | GTINfair( assigned ) ); | ||
elseif assigned.type == 13 then | elseif assigned.type == 13 then | ||
− | r = "977-" | + | r = string.format( "977-%s%s-%s", |
− | + | format( assigned, 4, 7 ), | |
− | + | format( assigned, 10, 2 ), | |
+ | tostring( assigned[ 13 ] ) ); | ||
end | end | ||
end | end | ||
Zeile 516: | Zeile 609: | ||
-- Returns table; success | -- Returns table; success | ||
-- false if not correct, bad data | -- false if not correct, bad data | ||
− | -- | + | -- 2014-12-28 |
local r = false; | local r = false; | ||
− | local pat = "^ | + | local pat = "^%s*(%a*)(/?)(%d%S+)%s*$"; |
local pre, sep, s = attempt:match( pat ); | local pre, sep, s = attempt:match( pat ); | ||
if pre and s then | if pre and s then | ||
Zeile 535: | Zeile 628: | ||
if allow ~= "/" or sep == "/" then | if allow ~= "/" or sep == "/" then | ||
if sep == "/" then | if sep == "/" then | ||
− | year, serial = s:match( "^( | + | year, serial = s:match( "^(%d+)/(%d.+)$" ); |
elseif s:find( "-", 2, true ) then | elseif s:find( "-", 2, true ) then | ||
− | year, serial = s:match( "^( | + | year, serial = s:match( "^(%d+)%-(%d.+)$" ); |
else | else | ||
year = s:match( "^([%d]+)" ); | year = s:match( "^([%d]+)" ); | ||
Zeile 576: | Zeile 669: | ||
if serial:find( "/", 2, true ) then | if serial:find( "/", 2, true ) then | ||
local q; | local q; | ||
− | serial, q = serial: | + | serial, q = serial:lower() |
− | :match( "^( | + | :match( "^(%d+)/([a-z]+)$" ); |
if q == "dc" or | if q == "dc" or | ||
q == "mads" or | q == "mads" or | ||
Zeile 586: | Zeile 679: | ||
end | end | ||
end | end | ||
− | serial = serial:match( "^0*([1-9] | + | if serial then |
+ | serial = serial:match( "^0*([1-9]%d*)$" ); | ||
+ | end | ||
if not serial then | if not serial then | ||
r = false; | r = false; | ||
elseif #serial < 6 then | elseif #serial < 6 then | ||
− | r.serial = | + | r.serial = string.format( "%06d", |
− | + | tonumber( serial ) ); | |
elseif #serial > 6 then | elseif #serial > 6 then | ||
r = false; | r = false; | ||
Zeile 630: | Zeile 725: | ||
end | end | ||
if assigned.qualifier then | if assigned.qualifier then | ||
− | r = | + | r = string.format( "%s/%s", r, assigned.qualifier ); |
end | end | ||
return r; | return r; | ||
Zeile 644: | Zeile 739: | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns link, or plain attempt if bad LCCN | -- Returns link, or plain attempt if bad LCCN | ||
− | -- | + | -- 2015-08-10 |
local lccn = LCCNfactory( attempt ); | local lccn = LCCNfactory( attempt ); | ||
local r; | local r; | ||
Zeile 650: | Zeile 745: | ||
r = LCCNformat( lccn, false ); | r = LCCNformat( lccn, false ); | ||
if r then | if r then | ||
+ | local s; | ||
if achieve then | if achieve then | ||
− | + | s = LCCNformat( lccn, achieve ); | |
else | else | ||
− | + | s = r; | |
end | end | ||
− | r = "[ | + | r = string.format( "[//lccn.loc.gov/%s %s]", r, s ); |
end | end | ||
else | else | ||
Zeile 671: | Zeile 767: | ||
-- acquire -- string with identification | -- acquire -- string with identification | ||
-- Postcondition: | -- Postcondition: | ||
− | -- Returns false if no problem | + | -- Returns false if no problem detected |
-- string with violation | -- string with violation | ||
− | local | + | local r; |
− | if | + | if area == "urn" then |
− | r = | + | r = "urn:"; |
− | + | else | |
− | + | local s = fetch( "urn" ).sns; | |
− | + | if type( s ) == "string" then | |
− | + | r = string.format( ":%s:", area ); | |
− | + | if s:match( r ) then | |
− | + | s = "[^%w%(%)%+,%-%.:=/@;%$_!%*'].*$"; | |
− | + | r = acquire:match( s ); | |
− | + | else | |
− | + | r = string.format( ":%s:", area ); | |
− | + | end | |
− | + | if not r then | |
− | + | r = false; | |
− | + | if area == "isbn" then | |
− | + | if not URIutil.isISBNvalid( acquire ) then | |
− | + | r = acquire; | |
− | + | end | |
− | + | elseif area == "issn" then | |
− | + | if not URIutil.isISSNvalid( acquire ) then | |
− | + | r = acquire; | |
− | |||
end | end | ||
end | end | ||
− | |||
− | |||
end | end | ||
− | |||
− | |||
end | end | ||
end | end | ||
return r; | return r; | ||
end -- URNnamespace() | end -- URNnamespace() | ||
+ | |||
+ | |||
+ | |||
+ | local URNresolve = function ( assigned, ask, alter ) | ||
+ | -- Resolve URN within space | ||
+ | -- Precondition: | ||
+ | -- assigned -- table with resolvers for this space | ||
+ | -- ask -- string with ID within this space | ||
+ | -- alter -- string with alternative resolver, or not | ||
+ | -- Postcondition: | ||
+ | -- Returns | ||
+ | -- 1. URL of resolver, or nil | ||
+ | -- 2. modified ask | ||
+ | local resolver = assigned; | ||
+ | local sign = ask; | ||
+ | local subset = assigned[ ":" ]; | ||
+ | local r; | ||
+ | if subset then | ||
+ | local s = sign:match( subset ); | ||
+ | if s then | ||
+ | s = s:lower(); | ||
+ | sign = s .. sign:sub( #s + 1 ) | ||
+ | if assigned[ s ] then | ||
+ | resolver = assigned[ s ]; | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | if alter then | ||
+ | r = resolver[ alter ]; | ||
+ | end | ||
+ | if not r then | ||
+ | r = resolver[ "*" ]; | ||
+ | end | ||
+ | return r, sign; | ||
+ | end -- URNresolve() | ||
Zeile 814: | Zeile 940: | ||
-- attempt -- string with any presumable DNB code | -- attempt -- string with any presumable DNB code | ||
-- also -- string or nil; optional requirement DMA GND SWD | -- also -- string or nil; optional requirement DMA GND SWD | ||
− | -- | + | -- "ZDB" -- permit hyphen, but use >2011 rule |
-- DMA starting with 3 and no hyphen | -- DMA starting with 3 and no hyphen | ||
-- GND not DNB2011 | -- GND not DNB2011 | ||
Zeile 821: | Zeile 947: | ||
-- Returns number of digits or 2011, if valid | -- Returns number of digits or 2011, if valid | ||
-- false if not correct, bad data or check digit wrong | -- false if not correct, bad data or check digit wrong | ||
− | |||
local s = mw.text.trim( attempt ); | local s = mw.text.trim( attempt ); | ||
local j = s:find( "/", 5, true ); | local j = s:find( "/", 5, true ); | ||
Zeile 833: | Zeile 958: | ||
if j > 3 and j <= 8 then | if j > 3 and j <= 8 then | ||
if s:match( "^[0-9]+-[0-9xX]$" ) then | if s:match( "^[0-9]+-[0-9xX]$" ) then | ||
− | dnb = factory( s, | + | dnb = factory( s, true ); |
end | end | ||
end | end | ||
− | elseif #s > | + | elseif #s > 6 then |
if s:match( "^[0-9]+[0-9xX]$" ) then | if s:match( "^[0-9]+[0-9xX]$" ) then | ||
dnb = factory( s, #s ); | dnb = factory( s, #s ); | ||
Zeile 845: | Zeile 970: | ||
if DNBfaith( dnb, true ) then | if DNBfaith( dnb, true ) then | ||
r = 2011; | r = 2011; | ||
+ | elseif type( also ) == "string" then | ||
+ | s = mw.text.trim( also ); | ||
+ | if s == "ZDB" then | ||
+ | if DNBfaith( dnb, false ) then | ||
+ | r = dnb.type; | ||
+ | end | ||
+ | end | ||
end | end | ||
else | else | ||
if DNBfaith( dnb, false ) then | if DNBfaith( dnb, false ) then | ||
r = dnb.type; | r = dnb.type; | ||
+ | elseif type( also ) == "string" then | ||
+ | s = mw.text.trim( also ); | ||
+ | if s == "ZDB" then | ||
+ | if DNBfaith( dnb, true ) then | ||
+ | r = dnb.type; | ||
+ | end | ||
+ | end | ||
end | end | ||
end | end | ||
Zeile 865: | Zeile 1.004: | ||
-- false if not correct, bad character or syntax | -- false if not correct, bad character or syntax | ||
local r = false; | local r = false; | ||
− | local k, s = attempt:match( "^ *10%.([1-9][0-9]+)/(.+) *$" ); | + | local k, s = attempt:match( "^%s*10%.([1-9][0-9]+)/(.+)%s*$" ); |
if k then | if k then | ||
k = tonumber( k ); | k = tonumber( k ); | ||
if k >= 1000 and k < 100000000 then | if k >= 1000 and k < 100000000 then | ||
− | local pc = "^[0-9A-Za-z]" | + | local pc = "^[0-9A-Za-z%(%[<%./]" |
− | .. "[%-0-9/A-Z%.a-z%(%)_%[%];:<>] | + | .. "[%-0-9/A-Z%.a-z%(%)_%[%];,:<>%+]*" |
− | .. "[0-9A-Za-z]$" | + | .. "[0-9A-Za-z%)%]>%+#]$" |
s = mw.uri.decode( mw.text.decode( s ), "PATH" ); | s = mw.uri.decode( mw.text.decode( s ), "PATH" ); | ||
if s:match( pc ) then | if s:match( pc ) then | ||
Zeile 937: | Zeile 1.076: | ||
return r; | return r; | ||
end -- URIutil.isGTINvalid() | end -- URIutil.isGTINvalid() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.isHandle( attempt ) | ||
+ | -- Is this a meaningful handle for handle.net? | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable handle code | ||
+ | -- Postcondition: | ||
+ | -- Returns number of primary authority, if valid | ||
+ | -- false if not correct, bad character or syntax | ||
+ | local r = attempt:match( "^%s*([^/%s]+)/%S+%s*$" ); | ||
+ | if r then | ||
+ | local k = r:find( ".", 1, true ); | ||
+ | if k then | ||
+ | if k == 1 or r:match( "%.$" ) then | ||
+ | r = false; | ||
+ | else | ||
+ | r = r:sub( 1, k - 1 ); | ||
+ | end | ||
+ | end | ||
+ | if r then | ||
+ | if r:match( "^[1-9][0-9]+$" ) then | ||
+ | r = tonumber( r ); | ||
+ | else | ||
+ | r = false; | ||
+ | end | ||
+ | end | ||
+ | else | ||
+ | r = false; | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.isHandle() | ||
Zeile 950: | Zeile 1.121: | ||
-- false if not an ISBN | -- false if not an ISBN | ||
-- 2 -- internal table, if (1) | -- 2 -- internal table, if (1) | ||
+ | -- number; no string or bad length or data | ||
+ | -- 0 -- no string | ||
+ | -- >0 -- unexpected char at position (trimmed) | ||
+ | -- -1 -- bad digit count | ||
+ | -- -2 -- bad bookland | ||
local r; | local r; | ||
local isbn = ISBNfactory( attempt ); | local isbn = ISBNfactory( attempt ); | ||
Zeile 972: | Zeile 1.148: | ||
-- false if not correct, bad data or check digit wrong | -- false if not correct, bad data or check digit wrong | ||
-- 2 -- internal table, if (1) | -- 2 -- internal table, if (1) | ||
+ | -- number; no string or bad length or data | ||
+ | -- 0 -- no string | ||
+ | -- >0 -- unexpected char at position (trimmed) | ||
+ | -- -1 -- bad digit count | ||
+ | -- -2 -- bad bookland | ||
local r = false; | local r = false; | ||
local isbn = ISBNfactory( attempt ); | local isbn = ISBNfactory( attempt ); | ||
Zeile 1.022: | Zeile 1.203: | ||
− | function URIutil. | + | function URIutil.linkDNBopac( attempt, about, allow, abbr, alert ) |
− | -- Retrieve bracketed titled external link | + | -- Retrieve bracketed titled external DNB opac link |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable DNB ID |
+ | -- about -- title, or false | ||
+ | -- allow -- true: permit invalid ID | ||
+ | -- abbr -- true: link DNB abbreviation | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns link, or plain string if bad DNB |
− | local r = URIutil. | + | local r = allow or URIutil.isDNBvalid( attempt ); |
+ | local s = "DNB"; | ||
+ | if abbr and not about then | ||
+ | local cnf = fetch( "config" ); | ||
+ | if cnf.supportDNB and cnf.supportDNB ~= fullPageName() then | ||
+ | s = string.format( "[[%s|DNB]]", cnf.supportDNB ); | ||
+ | end | ||
+ | end | ||
if r then | if r then | ||
− | r = mw. | + | if about then |
− | r = string.format( "[%s%s %s]", | + | r = about; |
− | " | + | else |
+ | r = attempt; | ||
+ | end | ||
+ | r = string.format( "%s [%s%s%s%s%s %s]", | ||
+ | s, | ||
+ | "https://portal.dnb.de/opac.htm", | ||
+ | "?referrer=Wikipedia", | ||
+ | "&method=simpleSearch&cqlMode=true", | ||
+ | "&query=idn%3D", | ||
+ | attempt, | ||
+ | r ); | ||
+ | else | ||
+ | r = string.format( "%s %s", s, attempt ); | ||
+ | if about then | ||
+ | r = string.format( "%s %s", r, about ); | ||
+ | end | ||
+ | if alert then | ||
+ | r = r .. flop( alert ); | ||
+ | end | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.linkDNBopac() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.linkDOI( attempt, any1, any2, any3, alert ) | ||
+ | -- Retrieve bracketed titled external link on DOI resolver | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable DOI | ||
+ | -- any1 -- intentionally dummy parameter | ||
+ | -- any2 -- intentionally dummy parameter | ||
+ | -- any3 -- intentionally dummy parameter | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
+ | -- Postcondition: | ||
+ | -- Returns external link, or false | ||
+ | local r = URIutil.isDOI( attempt ); | ||
+ | if r then | ||
+ | local e = mw.html.create( "span" ) | ||
+ | :addClass( "uri-handle" ); | ||
+ | local s; | ||
+ | s, r = attempt:match( "^%s*(10%.[1-9][0-9]+/)(.+)%s*$" ); | ||
+ | r = mw.text.decode( r, "PATH" ); | ||
+ | r = string.format( "[%s/%s%s %s%s]", | ||
+ | "//doi.org", | ||
+ | s, | ||
mw.uri.encode( r ), | mw.uri.encode( r ), | ||
+ | s, | ||
mw.text.encode( r, "<>&%]" ) ); | mw.text.encode( r, "<>&%]" ) ); | ||
+ | r = tostring( e:wikitext( r ) ); | ||
+ | else | ||
+ | r = flop( alert ); | ||
end | end | ||
return r; | return r; | ||
Zeile 1.041: | Zeile 1.281: | ||
− | function URIutil. | + | function URIutil.linkHandle( attempt, any1, any2, any3, alert ) |
− | -- Retrieve bracketed titled | + | -- Retrieve bracketed titled external link on handle resolver |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable ISBN | + | -- attempt -- string with presumable handle |
− | -- allow -- true: permit invalid check digit | + | -- any1 -- intentionally dummy parameter |
− | -- abbr -- true or string: link ISBN abbreviation | + | -- any2 -- intentionally dummy parameter |
− | -- adhere -- true: use else: use simple space | + | -- any3 -- intentionally dummy parameter |
+ | -- alert -- string with title of maintenance category, or nil | ||
+ | -- Postcondition: | ||
+ | -- Returns external link, or false | ||
+ | local r = URIutil.isHandle( attempt ); | ||
+ | if r then | ||
+ | local e = mw.html.create( "span" ) | ||
+ | :addClass( "uri-handle" ); | ||
+ | r = mw.text.decode( mw.text.trim( attempt ), "PATH" ); | ||
+ | r = string.format( "[%s%s %s]", | ||
+ | "//hdl.handle.net/", | ||
+ | mw.uri.encode( r ), | ||
+ | mw.text.encode( r, "<>&%]" ) ); | ||
+ | r = tostring( e:wikitext( r ) ); | ||
+ | else | ||
+ | r = flop( alert ); | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.linkHandle() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.linkISBN( attempt, allow, abbr, adhere, alert ) | ||
+ | -- Retrieve bracketed titled wikilink on booksources page with "ISBN" | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable ISBN | ||
+ | -- allow -- true: permit invalid check digit or digit count | ||
+ | -- abbr -- true or string: link ISBN abbreviation | ||
+ | -- adhere -- true: use else: use simple space | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns link | -- Returns link | ||
local lapsus; | local lapsus; | ||
local source = mw.text.trim( attempt ); | local source = mw.text.trim( attempt ); | ||
− | local r = "[[Special:Booksources/" | + | local r = string.format( "[[Special:Booksources/%s|", source ); |
local isbn = ISBNfactory( source ); | local isbn = ISBNfactory( source ); | ||
if type( isbn ) == "table" then | if type( isbn ) == "table" then | ||
Zeile 1.068: | Zeile 1.337: | ||
r = r .. ISBNformat( attempt, isbn ); | r = r .. ISBNformat( attempt, isbn ); | ||
else | else | ||
− | lapsus = | + | lapsus = not allow; |
r = r .. source; | r = r .. source; | ||
end | end | ||
r = r .. "]]"; | r = r .. "]]"; | ||
if lapsus then | if lapsus then | ||
− | + | local e = mw.html.create( "span" ) | |
− | + | :addClass( "invalid-ISBN" ) | |
− | + | :wikitext( r ); | |
+ | r = tostring( e ) .. fault( "(?!?!)" ); | ||
+ | if alert then | ||
+ | r = r .. flop( alert ); | ||
+ | end | ||
end | end | ||
if adhere then | if adhere then | ||
Zeile 1.083: | Zeile 1.356: | ||
end | end | ||
if abbr then | if abbr then | ||
− | local s; | + | local cnf = fetch( "config" ); |
− | if type( | + | local s = cnf.supportISBN; |
− | + | if s then | |
+ | if type( s ) ~= "string" | ||
+ | or s == "" then | ||
+ | s = false; | ||
+ | end | ||
else | else | ||
s = "International Standard Book Number"; | s = "International Standard Book Number"; | ||
end | end | ||
− | + | if s and s ~= fullPageName() then | |
+ | s = string.format( "[[%s|ISBN]]", s ); | ||
+ | else | ||
+ | s = "ISBN"; | ||
+ | end | ||
+ | r = string.format( "%s %s", s, r ); | ||
else | else | ||
r = "ISBN" .. r; | r = "ISBN" .. r; | ||
Zeile 1.098: | Zeile 1.380: | ||
− | function URIutil.linkISSN( attempt, allow, abbr, adhere ) | + | function URIutil.linkISSN( attempt, allow, abbr, adhere, alert ) |
-- Retrieve bracketed titled external link on ISSN DB with "ISSN" | -- Retrieve bracketed titled external link on ISSN DB with "ISSN" | ||
-- Precondition: | -- Precondition: | ||
-- attempt -- string with presumable ISSN | -- attempt -- string with presumable ISSN | ||
-- allow -- true: permit invalid check digit | -- allow -- true: permit invalid check digit | ||
− | -- abbr -- true | + | -- abbr -- true: link ISSN abbreviation |
-- adhere -- true: use else: use simple space; | -- adhere -- true: use else: use simple space; | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns link | -- Returns link | ||
− | local | + | local r = URIutil.targetISSN( attempt, allow, nil, nil, alert ); |
− | + | if adhere then | |
− | + | r = " " .. r; | |
− | if | + | else |
− | local | + | r = " " .. r; |
− | local | + | end |
− | if type( | + | if abbr then |
− | + | local cnf = fetch( "config" ); | |
+ | local s = cnf.supportISSN; | ||
+ | if s then | ||
+ | if type( s ) ~= "string" | ||
+ | or s == "" then | ||
+ | s = false; | ||
+ | end | ||
else | else | ||
− | + | s = "International Standard Serial Number"; | |
end | end | ||
− | if | + | if s and s ~= fullPageName() then |
− | + | s = string.format( "[[%s|ISSN]]", s ); | |
else | else | ||
− | + | s = "ISSN"; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
+ | r = string.format( "%s%s", s, r ); | ||
else | else | ||
− | + | r = "ISSN" .. r; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | r = "ISSN" .. r; | ||
end | end | ||
return r; | return r; | ||
Zeile 1.161: | Zeile 1.421: | ||
− | function URIutil.linkLCCN( attempt, achieve ) | + | function URIutil.linkLCCN( attempt, achieve, any1, any2, alert ) |
-- Retrieve bracketed titled external LCCN permalink | -- Retrieve bracketed titled external LCCN permalink | ||
-- Precondition: | -- Precondition: | ||
-- attempt -- string with presumable LCCN | -- attempt -- string with presumable LCCN | ||
-- achieve -- additional title formatting desires, like "-" | -- achieve -- additional title formatting desires, like "-" | ||
+ | -- any1 -- intentionally dummy parameter | ||
+ | -- any2 -- intentionally dummy parameter | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns link, or false if bad LCCN | -- Returns link, or false if bad LCCN | ||
− | + | local r = LCCNforward( attempt, achieve ); | |
+ | if not r then | ||
+ | r = flop( alert ); | ||
+ | end | ||
+ | return r; | ||
end -- URIutil.linkLCCN() | end -- URIutil.linkLCCN() | ||
− | function URIutil. | + | function URIutil.linkURN( attempt, alter, any1, any2, alert, at, alone ) |
− | -- | + | -- Retrieve bracketed titled external URN link |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string, with presumable URN, starting with "urn:" |
+ | -- alter -- alternative handler | ||
+ | -- any1 -- intentionally dummy parameter | ||
+ | -- any2 -- intentionally dummy parameter | ||
+ | -- alert -- string, with title of maintenance category, or nil | ||
+ | -- at -- fragment, or nil | ||
+ | -- alone -- true, if link text not preceded by "urn:" | ||
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns |
− | -- | + | -- 1. linked ID, or plain string if bad URN |
− | -- | + | -- 2. true, if to be preceded by "urn:" |
− | local r; | + | local r2 = true; |
− | if | + | local r; |
− | local | + | if URIutil.mayURN( attempt ) then |
− | if | + | local e = mw.html.create( "span" ) |
− | + | :addClass( "invalid-URN" ); | |
− | + | local serial = attempt; | |
− | + | local suffix = flop( alert ); | |
− | + | if serial:sub( 1, 4 ):lower() == "urn:" then | |
− | r = | + | serial = serial:sub( 5 ); |
+ | end | ||
+ | e:wikitext( serial ); | ||
+ | r = tostring( e ) .. fault( "(?!?!)" ); | ||
+ | if suffix then | ||
+ | r = r .. suffix; | ||
end | end | ||
else | else | ||
− | r = false; | + | local s = attempt:match( "^%s*[uU][rR][nN]:(%S+)%s*$" ); |
− | end | + | if s then |
− | return r; | + | local space, sign = s:match( "^(%w+):(.+)$" ); |
− | end -- URIutil. | + | if space then |
− | + | local defs = fetch( "urn" ); | |
− | + | if type( defs ) == "table" then | |
− | + | local resolver = defs.resolver; | |
− | function URIutil. | + | space = space:lower(); |
− | -- Is this a syntactically correct | + | resolver = resolver[ space ]; |
+ | r2 = ( resolver ~= true ); | ||
+ | if type( resolver ) == "table" then | ||
+ | r, sign = URNresolve( resolver, sign, alter ); | ||
+ | s = string.format( "%s:%s", space, sign ); | ||
+ | if r then | ||
+ | r = r:gsub( "%$1", "urn:" .. s ); | ||
+ | if at then | ||
+ | r = string.format( "%s#%s", r, at ); | ||
+ | end | ||
+ | if alone then | ||
+ | r2 = true; | ||
+ | else | ||
+ | s = "urn:" .. s; | ||
+ | end | ||
+ | r = string.format( "[%s %s]", r, s ); | ||
+ | end | ||
+ | elseif r2 then | ||
+ | if type( defs.sns ) == "string" then | ||
+ | s = string.format( ":%s:", space ); | ||
+ | if not defs.sns:find( s, 1, true ) then | ||
+ | s = false; | ||
+ | end | ||
+ | else | ||
+ | s = false; | ||
+ | end | ||
+ | if s then | ||
+ | r = string.format( "%s:%s", space, sign ); | ||
+ | else | ||
+ | r = string.format( "%s:%s", | ||
+ | space, sign ); | ||
+ | end | ||
+ | r2 = not alone; | ||
+ | else | ||
+ | s = "link" .. space:upper(); | ||
+ | r = URIutil[ s ]( sign, alter, nil, nil, alert ); | ||
+ | end | ||
+ | else | ||
+ | r = fault( "Bad structure in Module:URIutil/urn" ); | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | if not r then | ||
+ | if alert then | ||
+ | r = flop( alert ) or ""; | ||
+ | if attempt then | ||
+ | r = attempt .. r; | ||
+ | end | ||
+ | else | ||
+ | r = mw.text.trim( attempt ); | ||
+ | end | ||
+ | r2 = false; | ||
+ | end | ||
+ | return r, r2; | ||
+ | end -- URIutil.linkURN() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.mayDOI( attempt ) | ||
+ | -- Is this a syntactically correct DOI, or empty? | ||
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable DOI |
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns number of organization |
− | |||
-- 0 if empty | -- 0 if empty | ||
− | -- false if not empty and not | + | -- false if not empty and not a DOI |
local r; | local r; | ||
if type( attempt ) == "string" then | if type( attempt ) == "string" then | ||
local s = mw.text.trim( attempt ); | local s = mw.text.trim( attempt ); | ||
if #s >= 10 then | if #s >= 10 then | ||
− | r = URIutil. | + | r = URIutil.isDOI( attempt ); |
elseif #s == 0 then | elseif #s == 0 then | ||
r = 0; | r = 0; | ||
Zeile 1.222: | Zeile 1.559: | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil. | + | end -- URIutil.mayDOI() |
− | function URIutil. | + | function URIutil.mayHandle( attempt ) |
− | -- Is this a | + | -- Is this a meaningful handle, or empty? |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable handle |
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns number of organization |
− | |||
-- 0 if empty | -- 0 if empty | ||
− | -- false if not empty and not | + | -- false if not empty and not a DOI |
local r; | local r; | ||
if type( attempt ) == "string" then | if type( attempt ) == "string" then | ||
local s = mw.text.trim( attempt ); | local s = mw.text.trim( attempt ); | ||
− | if #s > | + | if #s > 5 then |
− | r = URIutil. | + | r = URIutil.isHandle( attempt ); |
elseif #s == 0 then | elseif #s == 0 then | ||
r = 0; | r = 0; | ||
Zeile 1.249: | Zeile 1.585: | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil. | + | end -- URIutil.mayHandle() |
− | function URIutil. | + | function URIutil.mayISBN( attempt ) |
− | -- Is this a syntactically correct | + | -- Is this a syntactically correct ISBN, or empty? |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable ISBN |
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns 10 if 10 digits and hyphens; also X at end of ISBN-10 |
+ | -- 13 if 13 digits and hyphens; beginning with bookland | ||
-- 0 if empty | -- 0 if empty | ||
− | -- false if not | + | -- false if not empty and not an ISBN |
+ | local r; | ||
if type( attempt ) == "string" then | if type( attempt ) == "string" then | ||
local s = mw.text.trim( attempt ); | local s = mw.text.trim( attempt ); | ||
− | if | + | if #s >= 10 then |
+ | r = URIutil.isISBN( attempt ); | ||
+ | elseif #s == 0 then | ||
r = 0; | r = 0; | ||
else | else | ||
− | r = | + | r = false; |
end | end | ||
else | else | ||
Zeile 1.272: | Zeile 1.612: | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil. | + | end -- URIutil.mayISBN() |
− | function URIutil. | + | function URIutil.mayISSN( attempt ) |
− | -- Is this a | + | -- Is this a correct ISSN, or empty? |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable ISSN |
− | |||
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns 8 if 8 digits and hyphens; also X at end |
− | -- | + | -- 13 if 13 digits and hyphens; beginning with issnland |
− | local r | + | -- 0 if empty |
− | if | + | -- false if not empty and not an ISSN |
+ | local r; | ||
+ | if type( attempt ) == "string" then | ||
local s = mw.text.trim( attempt ); | local s = mw.text.trim( attempt ); | ||
− | + | if #s >= 8 then | |
− | + | r = URIutil.isISSNvalid( attempt ); | |
− | r = | + | elseif #s == 0 then |
− | + | r = 0; | |
− | + | else | |
− | + | r = false; | |
− | |||
− | |||
− | |||
− | |||
end | end | ||
+ | else | ||
+ | r = false; | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil. | + | end -- URIutil.mayISSN() |
− | function URIutil. | + | function URIutil.mayLCCN( attempt ) |
− | -- Is this a syntactically correct | + | -- Is this a syntactically correct LCCN? |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable LCCN |
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns string with LCCN formatted aa9999-99999999 |
− | -- | + | -- 0 if empty |
− | + | -- false if not recognized | |
− | + | if type( attempt ) == "string" then | |
− | + | local s = mw.text.trim( attempt ); | |
− | + | if s == "" then | |
− | + | r = 0; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | r = | ||
else | else | ||
− | r = | + | r = URIutil.isLCCN( s ); |
end | end | ||
+ | else | ||
+ | r = false; | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil. | + | end -- URIutil.mayLCCN() |
− | function URIutil. | + | function URIutil.mayURI( attempt, ascii ) |
− | -- | + | -- Is this a syntactically correct URI, or empty? |
-- Precondition: | -- Precondition: | ||
− | -- attempt -- string with presumable | + | -- attempt -- string with presumable URI |
+ | -- ascii -- limit to ASCII (no IRI) | ||
-- Postcondition: | -- Postcondition: | ||
− | -- Returns | + | -- Returns false if no problem |
− | -- | + | -- string with violation |
− | local r; | + | local r = URIutil.isEscValid( attempt ); |
− | local | + | if not r then |
− | + | local s = mw.text.trim( attempt ); | |
− | + | r = s:match( "%s(.+)$" ); | |
− | + | if not r then | |
− | + | r = s:match( "#(.*)$" ); | |
+ | if r then | ||
+ | r = "#" .. r; | ||
+ | elseif ascii then | ||
+ | local p = string.format( "[%s].+$", | ||
+ | mw.ustring.char( 128,45,255 ) ); | ||
+ | r = mw.ustring.match( s, p ); | ||
+ | end | ||
+ | end | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil. | + | end -- URIutil.mayURI() |
− | function URIutil. | + | function URIutil.mayURN( attempt ) |
− | -- | + | -- Is this a syntactically correct URN, or empty? |
-- Precondition: | -- Precondition: | ||
− | -- attempt | + | -- attempt -- string with presumable URN, starting with "urn:" |
− | -- | + | -- Postcondition: |
− | -- | + | -- Returns false if no problem |
− | local r = URIutil. | + | -- string with violation |
− | if r then | + | local r = URIutil.mayURI( attempt, true ); |
− | if | + | if not r then |
− | local s; | + | local s = attempt:match( "^%s*[uU][rR][nN]:(.+)$" ); |
− | if | + | if s then |
− | + | local space, id = s:match( "^(%w+):(.+)$" ); | |
+ | if space then | ||
+ | r = URNnamespace( space:lower(), id ); | ||
else | else | ||
− | s | + | r = s; |
end | end | ||
− | |||
else | else | ||
− | r = " | + | s = mw.text.trim( attempt ); |
+ | if s == "" then | ||
+ | r = false; | ||
+ | elseif s:match( "^https?://" ) then | ||
+ | r = "http:"; | ||
+ | else | ||
+ | r = "urn:"; | ||
+ | end | ||
end | end | ||
end | end | ||
return r; | return r; | ||
− | end -- URIutil.uriDOI() | + | end -- URIutil.mayURN() |
+ | |||
+ | |||
+ | |||
+ | function URIutil.plainISBN( attempt ) | ||
+ | -- Format ISBN as digits (and 'X') only string | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable ISBN | ||
+ | -- Postcondition: | ||
+ | -- Returns string with 10 or 13 chars | ||
+ | -- false if not empty and not an ISBN | ||
+ | local r; | ||
+ | local isbn = ISBNfactory( attempt ); | ||
+ | if type( isbn ) == "table" then | ||
+ | r = ISBNflat( isbn ); | ||
+ | else | ||
+ | r = false; | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.plainISBN() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.targetISSN( attempt, allow, any1, any2, alert ) | ||
+ | -- Retrieve bracketed titled external link on ISSN DB without "ISSN" | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable ISSN | ||
+ | -- allow -- true: permit invalid check digit | ||
+ | -- any1 -- intentionally dummy parameter | ||
+ | -- any2 -- intentionally dummy parameter | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
+ | -- Postcondition: | ||
+ | -- Returns link | ||
+ | local cnf = fetch( "config" ); | ||
+ | local issn = ISSNfactory( attempt ); | ||
+ | local lapsus, r; | ||
+ | if type( issn ) == "table" then | ||
+ | local lenient; | ||
+ | if type( allow ) == "string" then | ||
+ | lenient = ( allow ~= "0" ); | ||
+ | else | ||
+ | lenient = allow; | ||
+ | end | ||
+ | if lenient then | ||
+ | lapsus = false; | ||
+ | else | ||
+ | lapsus = ( not ISSNfaith( issn ) ); | ||
+ | end | ||
+ | r = ISSNformat( issn, issn.type ); | ||
+ | if type( cnf.issn ) == "string" then | ||
+ | r = string.format( "[%s %s]", | ||
+ | cnf.issn:gsub( "%$1", r ), | ||
+ | r ); | ||
+ | end | ||
+ | else | ||
+ | lapsus = true; | ||
+ | r = attempt; | ||
+ | end | ||
+ | if lapsus then | ||
+ | local e = mw.html.create( "span" ) | ||
+ | :addClass( "invalid-ISSN" ) | ||
+ | :wikitext( r ); | ||
+ | r = tostring( e ) .. fault( "(?!?!)" ); | ||
+ | if alert then | ||
+ | r = r .. flop( alert ); | ||
+ | end | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.targetISSN() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.uriDOI( attempt, anything, abbr ) | ||
+ | -- Retrieve linked URI on DOI resolver | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable DOI | ||
+ | -- anything -- intentionally dummy parameter | ||
+ | -- abbr -- true or string: link doi: abbreviation | ||
+ | local r = URIutil.linkDOI( attempt ); | ||
+ | if r then | ||
+ | if abbr then | ||
+ | local s; | ||
+ | if type( abbr ) == "string" then | ||
+ | s = abbr; | ||
+ | else | ||
+ | s = "Digital Object Identifier"; | ||
+ | end | ||
+ | r = string.format( "[[%s|doi]]:%s", s, r ); | ||
+ | else | ||
+ | r = "doi:" .. r; | ||
+ | end | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.uriDOI() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.uriHandle( attempt, anything, abbr ) | ||
+ | -- Retrieve linked URI on handle resolver | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable handle | ||
+ | -- anything -- intentionally dummy parameter | ||
+ | -- abbr -- true or string: link hdl: abbreviation | ||
+ | local r = URIutil.linkHandle( attempt ); | ||
+ | if r then | ||
+ | local s; | ||
+ | if type( abbr ) == "string" then | ||
+ | s = abbr; | ||
+ | end | ||
+ | if s then | ||
+ | r = string.format( "[[%s|hdl]]:%s", s, r ); | ||
+ | else | ||
+ | r = "hdl:" .. r; | ||
+ | end | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.uriHandle() | ||
+ | |||
+ | |||
+ | |||
+ | function URIutil.uriURN( attempt, anything, alter, alert, at ) | ||
+ | -- Retrieve linked URI on URN resolver | ||
+ | -- Precondition: | ||
+ | -- attempt -- string with presumable URN, starting with "urn:" | ||
+ | -- anything -- intentionally dummy parameter | ||
+ | -- alter -- string with alternative handler, or nil | ||
+ | -- alert -- string with title of maintenance category, or nil | ||
+ | -- at -- fragment, or nil | ||
+ | -- Postcondition: | ||
+ | -- Returns link, or plain string if bad URN | ||
+ | local r, l = | ||
+ | URIutil.linkURN( attempt, alter, false, false, alert, at, true ); | ||
+ | if l then | ||
+ | local s = fetch( "config" ).supportURN; | ||
+ | if s then | ||
+ | if type( s ) ~= "string" | ||
+ | or s == "" then | ||
+ | s = false; | ||
+ | end | ||
+ | else | ||
+ | s = "Uniform Resource Name"; | ||
+ | end | ||
+ | if s then | ||
+ | r = string.format( "[[%s|urn]]:%s", s, r ); | ||
+ | else | ||
+ | r = "urn:" .. r; | ||
+ | end | ||
+ | end | ||
+ | return r; | ||
+ | end -- URIutil.uriURN() | ||
+ | |||
+ | |||
+ | |||
+ | 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 | ||
+ | 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 vsn = entity:formatPropertyValues( "P348" ) | ||
+ | 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() | ||
local Template = function ( frame, action ) | local Template = function ( frame, action ) | ||
− | -- Retrieve library result for template access | + | -- Retrieve library result for template access |
− | -- Precondition: | + | -- Precondition: |
− | -- frame -- object | + | -- frame -- object |
− | -- action -- string; function name | + | -- action -- string; function name |
− | -- Postcondition: | + | -- Postcondition: |
− | -- Returns appropriate string, or error message (development) | + | -- Returns appropriate string, or error message (development) |
− | local lucky, r = pcall( URIutil[ action ], | + | local lucky, r = pcall( URIutil[ action ], |
− | frame.args[ 1 ] or "", | + | frame.args[ 1 ] or "", |
− | frame.args[ 2 ], | + | frame.args[ 2 ], |
− | faculty( frame.args.link, true ), | + | faculty( frame.args.link, true ), |
− | faculty( frame.args.nbsp, true ) ); | + | faculty( frame.args.nbsp, true ), |
− | if lucky then | + | frame.args.cat, |
− | if r then | + | frame.args.fragment ); |
− | r = tostring( r ); | + | if lucky then |
− | else | + | if r then |
− | r = ""; | + | r = tostring( r ); |
− | end | + | else |
− | else | + | r = ""; |
− | r = | + | end |
− | end | + | else |
− | return r; | + | r = fault( r ); |
− | end -- Template() | + | end |
− | + | return r; | |
− | + | end -- Template() | |
− | + | ||
− | -- Provide template access and expose URIutil table to require() | + | |
− | + | ||
− | local p = {}; | + | -- Provide template access and expose URIutil table to require() |
− | + | ||
− | function p.coreISSN( frame ) | + | local p = {}; |
− | return Template( frame, "coreISSN" ); | + | |
+ | function p.coreISSN( frame ) | ||
+ | return Template( frame, "coreISSN" ); | ||
+ | end | ||
+ | function p.formatISBN( frame ) | ||
+ | return Template( frame, "formatISBN" ); | ||
+ | end | ||
+ | function p.formatISSN( frame ) | ||
+ | return Template( frame, "formatISSN" ); | ||
+ | end | ||
+ | function p.formatLCCN( frame ) | ||
+ | return Template( frame, "formatLCCN" ); | ||
+ | end | ||
+ | function p.isDNBvalid( frame ) | ||
+ | return Template( frame, "isDNBvalid" ); | ||
+ | end | ||
+ | function p.isDOI( frame ) | ||
+ | return Template( frame, "isDOI" ); | ||
+ | end | ||
+ | function p.isEscValid( frame ) | ||
+ | return Template( frame, "isEscValid" ); | ||
+ | end | ||
+ | function p.isGTINvalid( frame ) | ||
+ | return Template( frame, "isGTINvalid" ); | ||
+ | end | ||
+ | function p.isHandle( frame ) | ||
+ | return Template( frame, "isHandle" ); | ||
+ | end | ||
+ | function p.isISBN( frame ) | ||
+ | return Template( frame, "isISBN" ); | ||
+ | end | ||
+ | function p.isISBNvalid( frame ) | ||
+ | return Template( frame, "isISBNvalid" ); | ||
+ | end | ||
+ | function p.isISSNvalid( frame ) | ||
+ | return Template( frame, "isISSNvalid" ); | ||
end | end | ||
− | function p. | + | function p.isLCCN( frame ) |
− | return Template( frame, " | + | return Template( frame, "isLCCN" ); |
end | end | ||
− | function p. | + | function p.linkDNBopac( frame ) |
− | return Template( frame, " | + | return Template( frame, "linkDNBopac" ); |
end | end | ||
− | function p. | + | function p.linkDOI( frame ) |
− | return Template( frame, " | + | return Template( frame, "linkDOI" ); |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
function p.linkDOI( frame ) | function p.linkDOI( frame ) | ||
return Template( frame, "linkDOI" ); | return Template( frame, "linkDOI" ); | ||
+ | end | ||
+ | function p.linkHandle( frame ) | ||
+ | return Template( frame, "linkHandle" ); | ||
end | end | ||
function p.linkISBN( frame ) | function p.linkISBN( frame ) | ||
Zeile 1.453: | Zeile 2.010: | ||
function p.linkLCCN( frame ) | function p.linkLCCN( frame ) | ||
return Template( frame, "linkLCCN" ); | return Template( frame, "linkLCCN" ); | ||
+ | end | ||
+ | function p.linkURN( frame ) | ||
+ | return Template( frame, "linkURN" ); | ||
end | end | ||
function p.mayDOI( frame ) | function p.mayDOI( frame ) | ||
return Template( frame, "mayDOI" ); | return Template( frame, "mayDOI" ); | ||
+ | end | ||
+ | function p.mayHandle( frame ) | ||
+ | return Template( frame, "mayHandle" ); | ||
end | end | ||
function p.mayISBN( frame ) | function p.mayISBN( frame ) | ||
Zeile 1.474: | Zeile 2.037: | ||
function p.plainISBN( frame ) | function p.plainISBN( frame ) | ||
return Template( frame, "plainISBN" ); | return Template( frame, "plainISBN" ); | ||
+ | end | ||
+ | function p.targetISSN( frame ) | ||
+ | return Template( frame, "targetISSN" ); | ||
end | end | ||
function p.uriDOI( frame ) | function p.uriDOI( frame ) | ||
return Template( frame, "uriDOI" ); | return Template( frame, "uriDOI" ); | ||
end | end | ||
− | function p.URIutil() | + | function p.uriHandle( frame ) |
− | return | + | return Template( frame, "uriHandle" ); |
+ | end | ||
+ | function p.uriURN( frame ) | ||
+ | return Template( frame, "uriURN" ); | ||
+ | end | ||
+ | p.failsafe = function ( frame ) | ||
+ | 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() | ||
+ | function p.URIutil( arg ) | ||
+ | local r; | ||
+ | if arg then | ||
+ | r = ""; | ||
+ | else | ||
+ | r = URIutil; | ||
+ | end | ||
+ | return r; | ||
end | end | ||
return p; | return p; |
Aktuelle Version vom 6. September 2019, 12:27 Uhr
Die Dokumentation für dieses Modul kann unter Modul:URIutil/Doku erstellt werden
local URIutil = { suite = "URIutil",
serial = "2019-08-07",
item = 19644443 };
--[=[
Utilities for URI etc.
* coreISSN()
* formatISBN()
* formatISSN()
* formatLCCN()
* isDNBvalid()
* isDOI()
* isEscValid()
* isGTINvalid()
* isHandle()
* isISBN()
* isISBNvalid()
* isISSNvalid()
* isLCCN()
* linkDNBopac()
* linkDOI()
* linkHandle()
* linkISBN()
* linkISSN()
* linkLCCN()
* linkURN()
* mayDOI()
* mayHandle()
* mayISBN()
* mayISSN()
* mayLCCN()
* mayURI()
* mayURN()
* plainISBN()
* targetISSN()
* uriDOI()
* uriHandle()
* uriURN()
* failsafe()
* URIutil()
loadData: URIutil/config URIutil/isbn URIutil/urn
]=]
local Failsafe = URIutil
local CurrentPageName
local factory = function ( attempt, allowX )
-- Retrieve plain digits of attempt
-- Precondition:
-- attempt -- string; with digits (+xX) and hyphens, not trimmed
-- allowX -- number; of (last) position for permitted xX
-- boolean; xX at last position permitted
-- Postcondition:
-- Returns table; success
-- [1]...[8]/[10]...[13] -- digits 0...9
-- 10 at last position
-- .hyphens -- number of hyphens
-- .type -- number of digits
-- number; no string or bad length or data
-- 0 -- no string
-- >0 -- unexpected char at position (trimmed)
local r;
if type( attempt ) == "string" then
local c, i;
local j = 0;
local k = 1;
local s = mw.text.trim( attempt );
local n = mw.ustring.len( s );
r = { hyphens = 0 };
for i = 1, n do
c = mw.ustring.codepoint( s, i, i + 1 );
if c >= 48 and c <= 57 then
j = j + 1;
r[ j ] = c - 48;
k = false;
elseif c == 45 then -- hyphen
if i > 1 and i < n then
r.hyphens = r.hyphens + 1;
k = i;
else
r = j;
break;
end
elseif c == 88 or c == 120 then -- X x
j = j + 1;
if allowX and i == n then
if allowX == true or allowX == j then
r[ j ] = 10;
else
r = j;
end
else
r = j;
end
break;
else
r = j;
break;
end
end -- for i
if type( r ) == "table" then
r.type = j;
end
else
r = 0;
end
return r;
end -- factory()
local faculty = function ( ask, auto )
-- Evaluate possible string as boolean signal, if brief
-- Precondition:
-- ask -- trimmed string or nil or other
-- auto -- fallback value if nil
-- Postcondition:
-- Returns appropriate value, or ask
local r;
if type( ask ) == "string" then
if ask == "1" or ask == "" then
r = true;
elseif ask == "0" or ask == "-" then
r = false;
else
r = ask;
end
elseif ask == nil then
r = auto;
else
r = ask;
end
return r;
end -- faculty()
local fair = function ( assert )
-- Compute check digit (11 minus modulo 11) for descending factor
-- Precondition:
-- assert -- table; as of factory()
-- .type -- number of digits including check digit
-- Postcondition:
-- Returns checksum
local i;
local n = assert.type;
local k = n;
local r = 0;
for i = 1, n - 1 do
r = r + k * assert[ i ];
k = k - 1;
end -- for i
return ( 11 - r % 11 );
end -- fair()
local fault = function ( alert )
-- Format error message by class=error
-- Parameter:
-- alert -- string, error message
-- Returns:
-- string, HTML span
return tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( alert ) );
end -- fault()
local fetch = function ( acquire )
-- Load data submodule
-- Precondition:
-- acquire -- string, one of
-- "config"
-- "isbn"
-- "urn"
-- Postcondition:
-- Returns any table
local r;
if URIutil.data then
r = URIutil.data[ acquire ];
else
URIutil.data = { };
end
if not r then
local lucky;
lucky, r = pcall( mw.loadData, "Module:URIutil/" .. acquire );
if type( r ) ~= "table" then
r = { };
end
URIutil.data[ acquire ] = r;
end
return r;
end -- fetch()
local flop = function ( alert )
-- Create link to (maintenance) category
-- Precondition:
-- alert -- trimmed string with title, not empty, or nil
-- Postcondition:
-- Returns link, or false
local r;
if type( alert ) == "string" and alert ~= "" then
r = string.format( "[[Category:%s]]", alert );
end
return r;
end -- flop()
local format = function ( assigned, ahead, amount )
-- Convert part of digit sequence into string
-- Precondition:
-- assigned -- table; as of factory()
-- ahead -- index of first digit
-- amount -- number of digits to append
-- Postcondition:
-- Returns string with digits and hyphens
local i, k;
local r = "";
for i = ahead, ahead + amount - 1 do
k = assigned[ i ];
if k == 10 then
r = r .. "X";
else
r = r .. tostring( k );
end
end -- for i
return r;
end -- format()
local fullPageName = function ()
-- Retrieve current page name
-- Postcondition:
-- Returns string: current page name
if not CurrentPageName then
CurrentPageName = mw.title.getCurrentTitle().fullText;
end
return CurrentPageName;
end -- fullPageName()
local DNBfaith = function ( assert, ancestor )
-- Compute DNB (also GND, ZDB) check digit and verify
-- Precondition:
-- assert -- table; as of factory()
-- .type -- until 11 including check digit
-- ancestor -- true: 2011 mode
-- Postcondition:
-- Returns true: check digit matches
-- 2013-09-01
local k = fair( assert ) % 11;
if ancestor then
k = 11 - k;
end
return ( k == assert[ assert.type ] );
end -- DNBfaith()
local GTINfair = function ( assert )
-- Compute GTIN check digit
-- Precondition:
-- assert -- table; ~ 13 digits
-- .type -- 13 ...
-- Postcondition:
-- Returns number 0...9
local i, k;
local lead = true;
local r = 0;
for i = 1, assert.type - 1 do
k = assert[ i ];
r = r + k;
if lead then -- odd
lead = false;
else -- even
r = r + k + k;
lead = true;
end
end -- for i
r = (10 - r % 10) % 10;
return r;
end -- GTINfair()
local GTINfaith = function ( assert )
-- Compute GTIN check digit and verify
-- Precondition:
-- assert -- table; ~ 13 digits
-- .type -- 13 ...
-- Postcondition:
-- Returns true: check digit matches
return ( GTINfair( assert ) == assert[ assert.type ] );
end -- GTINfaith()
local ISBNfactory = function ( attempt )
-- Retrieve plain digits of ISBN attempt
-- Precondition:
-- attempt -- string with digits (+xX) and hyphens, not trimmed
-- Postcondition:
-- Returns table; success
-- [1]...[13] -- digits 0...9
-- 10 at ISBN-10 last position
-- .type -- 10 or 13
-- .hyphens -- 0... number of hyphens
-- number; no string or bad length or data
-- 0 -- no string
-- >0 -- unexpected char at position (trimmed)
-- -1 -- bad digit count
-- -2 -- bad bookland
local r;
if type( attempt ) == "string" then
local s;
r = factory( attempt, 10 );
s = type( r );
if s == "number" and r ~= 10 and r > 6 and r < 13 then
r = factory( attempt, r );
s = type( r );
end
if s == "table" then
if r.type == 13 then
if r[1] ~= 9 or
r[2] ~= 7 or
r[3] < 8 then
r = -2;
end
elseif r.type ~= 10 then
r = -1;
end
end
else
r = 0;
end
return r;
end -- ISBNfactory()
local ISBNfaith = function ( assert )
-- Compute ISBN check digit and verify
-- Precondition:
-- assert -- table; as of ISBNfactory()
-- .type -- 10 or 13
-- Postcondition:
-- Returns true: check digit matches
local r;
if assert.type == 10 then
local i;
local k = 0;
for i = 1, 9 do
k = k + i * assert[ i ];
end -- for i
k = k % 11;
r = ( k == assert[ 10 ] );
elseif assert.type == 13 then
r = GTINfaith( assert );
else
r = false;
end
return r;
end -- ISBNfaith()
local ISBNflat = function ( assigned )
-- Plain digits of attempt ISBN
-- Precondition:
-- assigned -- table; as of ISBNfactory()
-- Postcondition:
-- Returns string with digits; ISBN-10 with 'X' at last position
local i;
local r = "";
local n = assigned.type;
if n == 10 then
if assigned[ assigned.type ] == 10 then
n = 9;
end
end
for i = 1, n do
r = r .. tostring( assigned[ i ] );
end -- for i
if n == 9 then
r = r .. "X";
end
return r;
end -- ISBNflat()
local ISBNfold = function ( assigned, apply, allocate, already )
-- Retrieve number of digits for ISBN publisher/group
-- Precondition:
-- assigned -- table; as of ISBNfactory()
-- apply -- number; of bookland (978 or 979)
-- allocate -- number; of country
-- already -- number; position in assigned to inspect
-- Postcondition:
-- Returns number of digits, at least 0
local r = 0;
local def = fetch( "isbn" );
local bookland = def[ apply ];
if type( bookland ) == "table" then
local country = bookland[ allocate ];
if type( country ) == "table" then
local e, i, j, k, m, v;
for i = 1, 4 do
v = country[ i ];
if type( v ) == "table" then
m = tonumber( format( assigned, already, i ) );
for k, e in pairs( v ) do
if m >= e[ 1 ] and m <= e[ 2 ] then
r = e[ 3 ];
break; -- for k
end
end -- for k
end
if r > 0 then
break; -- for i
end
end -- for i
end
end
return r;
end -- ISBNfold()
local ISBNformat = function ( attempt, assigned )
-- Hyphen formatting; at least try minimum
-- Precondition:
-- attempt -- string with presumable ISBN
-- assigned -- table; as of ISBNfactory()
-- .type -- 10 or 13
-- .hyphens -- 0...4
-- Postcondition:
-- Returns string with digits and hyphens
local r = false;
local j, k, m, n;
if assigned.type == 10 then
m = 978;
r = "";
j = 1;
else
m = 970 + assigned[ 3 ];
r = tostring( m ) .. "-";
j = 4;
end
if assigned[ j ] < 8 then
k = 1;
else
k = 2;
if assigned[ j ] == 9 and
assigned[ j + 1 ] > 4 then
k = 3;
if assigned[ j + 1 ] > 8 then
k = 4;
if assigned[ j + 2 ] > 8 then
k = 5;
end
end
end
end
if k then
n = format( assigned, j, k );
r = string.format( "%s%s-", r, n );
j = j + k;
n = ISBNfold( assigned, m, tonumber( n ), j );
if n > 0 then
r = string.format( "%s%s-", r, format( assigned, j, n ) );
j = j + n;
end
end
r = r .. format( assigned, j, assigned.type - j );
if assigned[ assigned.type ] == 10 then
r = r .. "-X";
else
r = string.format( "%s-%s",
r,
tostring( assigned[ assigned.type ] ) );
end
if not r then
r = mw.ustring.upper( mw.text.trim( attempt ) );
end
return r;
end -- ISBNformat()
local ISSNfactory = function ( attempt )
-- Retrieve plain digits of ISSN attempt
-- Precondition:
-- attempt -- string with digits (+xX) and hyphens, not trimmed
-- Postcondition:
-- Returns table; success
-- [1]...[13] -- digits 0...9
-- 10 at ISSN-8 last position
-- .type -- 8 or 13
-- .hyphens -- 0... number of hyphens
-- number; no string or bad length or data
-- 0 -- no string
-- >0 -- unexpected char at position (trimmed)
-- -1 -- bad digit count
-- -2 -- bad issnland
local r;
if type( attempt ) == "string" then
r = factory( attempt, 8 );
if type( r ) == "table" then
if r.type == 13 then
if r[1] ~= 9 or
r[2] ~= 7 or
r[3] ~= 7 then
r = -2;
end
elseif r.type ~= 8 then
r = -1;
end
end
else
r = 0;
end
return r;
end -- ISSNfactory()
local ISSNfaith = function ( assert )
-- Compute ISSN check digit and verify
-- Precondition:
-- assert -- table; as of ISSNfactory()
-- .type -- 8 or 13
-- Postcondition:
-- Returns true: check digit matches
local r;
if assert.type == 8 then
local k = fair( assert );
if k == 11 then
r = ( assert[ 8 ] == 0 );
else
r = ( assert[ 8 ] == k );
end
elseif assert.type == 13 then
r = GTINfaith( assert );
else
r = false;
end
return r;
end -- ISSNfaith()
local ISSNformat = function ( assigned, achieve )
-- Hyphen formatting of ISSN
-- Precondition:
-- assigned -- table; as of ISSNfactory(), and valid
-- achieve -- 8 or 13
-- Postcondition:
-- Returns string with digits and hyphens
local r;
if achieve == 8 then
local x;
if assigned.type == 8 then
r = string.format( "%s-%s",
format( assigned, 1, 4 ),
format( assigned, 5, 3 ) );
x = assigned[ 8 ];
elseif assigned.type == 13 then
r = string.format( "%s-%s",
format( assigned, 4, 4 ),
format( assigned, 8, 3 ) );
x = fair( assigned );
end
if x == 10 then
r = r .. "X";
else
r = r .. tostring( x );
end
elseif achieve == 13 then
if assigned.type == 8 then
r = string.format( "977-%s-00-%s",
format( assigned, 1, 7 ),
GTINfair( assigned ) );
elseif assigned.type == 13 then
r = string.format( "977-%s%s-%s",
format( assigned, 4, 7 ),
format( assigned, 10, 2 ),
tostring( assigned[ 13 ] ) );
end
end
return r;
end -- ISSNformat()
local LCCNfactory = function ( attempt, allow )
-- Retrieve segments of LCCN attempt (format since 2001)
-- Precondition:
-- attempt -- string with presumable LCCN
-- allow -- false or string: "/"
-- Postcondition:
-- Returns table; success
-- false if not correct, bad data
-- 2014-12-28
local r = false;
local pat = "^%s*(%a*)(/?)(%d%S+)%s*$";
local pre, sep, s = attempt:match( pat );
if pre and s then
local year, serial;
if pre == "" then
pre = false;
if sep ~= "" then
s = false;
end
elseif #pre > 3 then
s = false;
else
pre = pre:lower();
end
if s then
if allow ~= "/" or sep == "/" then
if sep == "/" then
year, serial = s:match( "^(%d+)/(%d.+)$" );
elseif s:find( "-", 2, true ) then
year, serial = s:match( "^(%d+)%-(%d.+)$" );
else
year = s:match( "^([%d]+)" );
if year then
if #year <= 8 then
year = s:sub( 1, 2 );
serial = s:sub( 3 );
elseif #year <= 10 then
year = s:sub( 1, 4 );
serial = s:sub( 5 );
else
year = false;
serial = s;
end
elseif tonumber( s ) then
serial = s;
end
end
end
if year then
if #year == 4 then
local n = tonumber( year );
if n <= 2000 then
-- 2000 -> "00"
serial = false;
elseif n > tonumber( os.date( "%Y" ) ) then
serial = false;
end
elseif #year ~= 2 then
serial = false;
end
end
if serial then
r = { pre = pre, serial = serial };
if year then
r.year = year;
end
if serial:find( "/", 2, true ) then
local q;
serial, q = serial:lower()
:match( "^(%d+)/([a-z]+)$" );
if q == "dc" or
q == "mads" or
q == "marcxml" or
q == "mods" then
r.serial = serial;
r.qualifier = q;
end
end
if serial then
serial = serial:match( "^0*([1-9]%d*)$" );
end
if not serial then
r = false;
elseif #serial < 6 then
r.serial = string.format( "%06d",
tonumber( serial ) );
elseif #serial > 6 then
r = false;
end
end
end
end
return r;
end -- LCCNfactory()
local LCCNformat = function ( assigned, achieve )
-- Standard or hyphen or slash formatting of LCCN
-- Precondition:
-- assigned -- table; as of LCCNfactory(), and valid
-- achieve -- additional formatting desires, like "-" or "/"
-- Postcondition:
-- Returns string with letters, digits and hyphens
-- 2013-07-14
local r;
if assigned.pre then
r = assigned.pre;
else
r = "";
end
if assigned.year then
if achieve == "/" and r ~= "" then
r = r .. "/";
end
r = r .. assigned.year;
if achieve then
r = r .. achieve;
end
end
if assigned.serial then
r = r .. assigned.serial;
end
if assigned.qualifier then
r = string.format( "%s/%s", r, assigned.qualifier );
end
return r;
end -- LCCNformat()
local LCCNforward = function ( attempt, achieve )
-- Retrieve bracketed titled external LCCN permalink
-- Precondition:
-- attempt -- string with presumable LCCN
-- achieve -- additional title formatting desires, like "-"
-- Postcondition:
-- Returns link, or plain attempt if bad LCCN
-- 2015-08-10
local lccn = LCCNfactory( attempt );
local r;
if lccn then
r = LCCNformat( lccn, false );
if r then
local s;
if achieve then
s = LCCNformat( lccn, achieve );
else
s = r;
end
r = string.format( "[//lccn.loc.gov/%s %s]", r, s );
end
else
r = attempt;
end
return r;
end -- LCCNforward()
local URNnamespace = function ( area, acquire )
-- Are these parts of a correct URN?
-- Precondition:
-- area -- string with lowercase namespace
-- acquire -- string with identification
-- Postcondition:
-- Returns false if no problem detected
-- string with violation
local r;
if area == "urn" then
r = "urn:";
else
local s = fetch( "urn" ).sns;
if type( s ) == "string" then
r = string.format( ":%s:", area );
if s:match( r ) then
s = "[^%w%(%)%+,%-%.:=/@;%$_!%*'].*$";
r = acquire:match( s );
else
r = string.format( ":%s:", area );
end
if not r then
r = false;
if area == "isbn" then
if not URIutil.isISBNvalid( acquire ) then
r = acquire;
end
elseif area == "issn" then
if not URIutil.isISSNvalid( acquire ) then
r = acquire;
end
end
end
end
end
return r;
end -- URNnamespace()
local URNresolve = function ( assigned, ask, alter )
-- Resolve URN within space
-- Precondition:
-- assigned -- table with resolvers for this space
-- ask -- string with ID within this space
-- alter -- string with alternative resolver, or not
-- Postcondition:
-- Returns
-- 1. URL of resolver, or nil
-- 2. modified ask
local resolver = assigned;
local sign = ask;
local subset = assigned[ ":" ];
local r;
if subset then
local s = sign:match( subset );
if s then
s = s:lower();
sign = s .. sign:sub( #s + 1 )
if assigned[ s ] then
resolver = assigned[ s ];
end
end
end
if alter then
r = resolver[ alter ];
end
if not r then
r = resolver[ "*" ];
end
return r, sign;
end -- URNresolve()
function URIutil.coreISSN( attempt )
-- Fetch significant ISSN
-- Precondition:
-- attempt -- string with presumable ISSN
-- Postcondition:
-- Returns string with 7 digits, without check digit nor GTIN
-- unmodified input if wrong
local r;
local issn = ISSNfactory( attempt );
if type( issn ) == "table" then
if issn.type == 8 then
r = format( issn, 1, 7 );
elseif issn.type == 13 then
r = format( issn, 4, 7 );
end
else
r = mw.ustring.upper( mw.text.trim( attempt ) );
end
return r;
end -- URIutil.coreISSN()
function URIutil.formatISBN( attempt, assigned )
-- Format ISBN, if no hyphens present
-- Precondition:
-- attempt -- string with presumable ISBN
-- assigned -- table or false; as of ISBNfactory()
-- Postcondition:
-- Returns string with some hyphens, if not yet
-- unmodified input if already hyphens or wrong
local r;
local isbn;
if type( assigned ) == "table" then
isbn = assigned;
else
isbn = ISBNfactory( attempt );
end
if type( isbn ) == "table" then
r = ISBNformat( attempt, isbn );
else
r = mw.ustring.upper( mw.text.trim( attempt ) );
end
return r;
end -- URIutil.formatISBN()
function URIutil.formatISSN( attempt, achieve )
-- Format ISSN
-- Precondition:
-- attempt -- string with presumable ISSN
-- achieve -- false or 8 or 13; requested presentation
-- Postcondition:
-- Returns string with some hyphens, if not yet
-- unmodified input if already hyphens or wrong
local r = false;
local issn = ISSNfactory( attempt );
if type( issn ) == "table" then
if ISSNfaith( issn ) then
local k, m;
if type( achieve ) == "string" then
m = tonumber( achieve );
else
m = achieve;
end
if m == 8 or m == 13 then
k = m;
else
k = issn.type;
end
r = ISSNformat( issn, k );
end
end
if not r then
r = mw.ustring.upper( mw.text.trim( attempt ) );
end
return r;
end -- URIutil.formatISSN()
function URIutil.formatLCCN( attempt, achieve )
-- Standard or hyphen formatting of LCCN
-- Precondition:
-- attempt -- string with presumable LCCN
-- achieve -- additional formatting desires, like "-"
-- Postcondition:
-- Returns string with letters, digits and hyphens
-- unmodified input if wrong
local r = LCCNfactory( attempt );
if r then
r = LCCNformat( r, achieve );
end
return r;
end -- URIutil.formatLCCN()
function URIutil.isDNBvalid( attempt, also )
-- Is this DNB (also GND, ZDB) formally correct (check digit)?
-- Precondition:
-- attempt -- string with any presumable DNB code
-- also -- string or nil; optional requirement DMA GND SWD
-- "ZDB" -- permit hyphen, but use >2011 rule
-- DMA starting with 3 and no hyphen
-- GND not DNB2011
-- SWD DNB2011 starting with 4 or 7 and no X check
-- Postcondition:
-- Returns number of digits or 2011, if valid
-- false if not correct, bad data or check digit wrong
local s = mw.text.trim( attempt );
local j = s:find( "/", 5, true );
local r = false;
local dnb;
if j then
s = attempt:sub( 1, j - 1 );
end
j = s:find( "-", 2, true );
if j then
if j > 3 and j <= 8 then
if s:match( "^[0-9]+-[0-9xX]$" ) then
dnb = factory( s, true );
end
end
elseif #s > 6 then
if s:match( "^[0-9]+[0-9xX]$" ) then
dnb = factory( s, #s );
end
end
if type( dnb ) == "table" then
if j then
if DNBfaith( dnb, true ) then
r = 2011;
elseif type( also ) == "string" then
s = mw.text.trim( also );
if s == "ZDB" then
if DNBfaith( dnb, false ) then
r = dnb.type;
end
end
end
else
if DNBfaith( dnb, false ) then
r = dnb.type;
elseif type( also ) == "string" then
s = mw.text.trim( also );
if s == "ZDB" then
if DNBfaith( dnb, true ) then
r = dnb.type;
end
end
end
end
end
return r;
end -- URIutil.isDNBvalid()
function URIutil.isDOI( attempt )
-- Is this a syntactically correct DOI?
-- Precondition:
-- attempt -- string with presumable DOI code
-- Postcondition:
-- Returns number of organization, if valid
-- false if not correct, bad character or syntax
local r = false;
local k, s = attempt:match( "^%s*10%.([1-9][0-9]+)/(.+)%s*$" );
if k then
k = tonumber( k );
if k >= 1000 and k < 100000000 then
local pc = "^[0-9A-Za-z%(%[<%./]"
.. "[%-0-9/A-Z%.a-z%(%)_%[%];,:<>%+]*"
.. "[0-9A-Za-z%)%]>%+#]$"
s = mw.uri.decode( mw.text.decode( s ), "PATH" );
if s:match( pc ) then
r = k;
end
end
end
return r;
end -- URIutil.isDOI()
function URIutil.isEscValid( attempt )
-- Are bad percent escapings in attempt?
-- Precondition:
-- attempt -- string with possible percent escapings
-- Postcondition:
-- Returns string with violating sequence
-- false if correct
local i = 0;
local r = false;
local h, s;
while i do
i = attempt:find( "%", i, true );
if i then
s = attempt:sub( i + 1, i + 2 );
h = s:match( "%x%x" );
if h then
if h == "00" then
r = "%00";
break; -- while i
end
i = i + 2;
else
r = "%" .. s;
break; -- while i
end
end
end -- while i
return r;
end -- URIutil.isEscValid()
function URIutil.isGTINvalid( attempt )
-- Is this GTIN (EAN) formally correct (check digit)?
-- Precondition:
-- attempt -- string with presumable GTIN
-- Postcondition:
-- Returns GTIN length
-- false if not correct, bad data or check digit wrong
local r;
local gtin = factory( attempt, false );
if type( gtin ) == "table" then
if gtin.type == 13 then
if GTINfaith( gtin ) then
r = gtin.type;
end
else
r = false;
end
else
r = false;
end
return r;
end -- URIutil.isGTINvalid()
function URIutil.isHandle( attempt )
-- Is this a meaningful handle for handle.net?
-- Precondition:
-- attempt -- string with presumable handle code
-- Postcondition:
-- Returns number of primary authority, if valid
-- false if not correct, bad character or syntax
local r = attempt:match( "^%s*([^/%s]+)/%S+%s*$" );
if r then
local k = r:find( ".", 1, true );
if k then
if k == 1 or r:match( "%.$" ) then
r = false;
else
r = r:sub( 1, k - 1 );
end
end
if r then
if r:match( "^[1-9][0-9]+$" ) then
r = tonumber( r );
else
r = false;
end
end
else
r = false;
end
return r;
end -- URIutil.isHandle()
function URIutil.isISBN( attempt )
-- Is this a syntactically correct ISBN?
-- Precondition:
-- attempt -- string with presumable ISBN
-- Postcondition:
-- Returns
-- 1 -- 10 if 10 digits and hyphens; also X at end of ISBN-10
-- 13 if 13 digits and hyphens; beginning with bookland
-- false if not an ISBN
-- 2 -- internal table, if (1)
-- number; no string or bad length or data
-- 0 -- no string
-- >0 -- unexpected char at position (trimmed)
-- -1 -- bad digit count
-- -2 -- bad bookland
local r;
local isbn = ISBNfactory( attempt );
if type( isbn ) == "table" then
r = isbn.type;
else
r = false;
end
return r, isbn;
end -- URIutil.isISBN()
function URIutil.isISBNvalid( attempt )
-- Is this ISBN formally correct (check digit)?
-- Precondition:
-- attempt -- string with presumable ISBN
-- Postcondition:
-- Returns
-- 1 -- 10 if 10 digits and hyphens; also X at end of ISBN-10
-- 13 if 13 digits and hyphens; beginning with bookland
-- false if not correct, bad data or check digit wrong
-- 2 -- internal table, if (1)
-- number; no string or bad length or data
-- 0 -- no string
-- >0 -- unexpected char at position (trimmed)
-- -1 -- bad digit count
-- -2 -- bad bookland
local r = false;
local isbn = ISBNfactory( attempt );
if type( isbn ) == "table" then
if ISBNfaith( isbn ) then
r = isbn.type;
end
end
return r, isbn;
end -- URIutil.isISBNvalid()
function URIutil.isISSNvalid( attempt )
-- Is this ISSN formally correct (check digit)?
-- Precondition:
-- attempt -- string with presumable ISSN
-- Postcondition:
-- Returns 8 if 8 digits and up to 1 hyphen; also X at end
-- 13 if 13 digits and hyphens; beginning with 977
-- false if not correct, bad data or check digit wrong
local r = false;
local issn = ISSNfactory( attempt );
if type( issn ) == "table" then
if ISSNfaith( issn ) then
r = issn.type;
end
end
return r;
end -- URIutil.isISSNvalid()
function URIutil.isLCCN( attempt, allow )
-- Is this a syntactically correct LCCN?
-- Precondition:
-- attempt -- string with presumable LCCN
-- allow -- false or string: "/"
-- Postcondition:
-- Returns string with LCCN formatted aa9999-99999999
-- false if not correct, bad data
local r = false;
local lccn = LCCNfactory( attempt, allow );
if lccn then
r = LCCNformat( lccn, "-" );
end
return r;
end -- URIutil.isLCCN()
function URIutil.linkDNBopac( attempt, about, allow, abbr, alert )
-- Retrieve bracketed titled external DNB opac link
-- Precondition:
-- attempt -- string with presumable DNB ID
-- about -- title, or false
-- allow -- true: permit invalid ID
-- abbr -- true: link DNB abbreviation
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns link, or plain string if bad DNB
local r = allow or URIutil.isDNBvalid( attempt );
local s = "DNB";
if abbr and not about then
local cnf = fetch( "config" );
if cnf.supportDNB and cnf.supportDNB ~= fullPageName() then
s = string.format( "[[%s|DNB]]", cnf.supportDNB );
end
end
if r then
if about then
r = about;
else
r = attempt;
end
r = string.format( "%s [%s%s%s%s%s %s]",
s,
"https://portal.dnb.de/opac.htm",
"?referrer=Wikipedia",
"&method=simpleSearch&cqlMode=true",
"&query=idn%3D",
attempt,
r );
else
r = string.format( "%s %s", s, attempt );
if about then
r = string.format( "%s %s", r, about );
end
if alert then
r = r .. flop( alert );
end
end
return r;
end -- URIutil.linkDNBopac()
function URIutil.linkDOI( attempt, any1, any2, any3, alert )
-- Retrieve bracketed titled external link on DOI resolver
-- Precondition:
-- attempt -- string with presumable DOI
-- any1 -- intentionally dummy parameter
-- any2 -- intentionally dummy parameter
-- any3 -- intentionally dummy parameter
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns external link, or false
local r = URIutil.isDOI( attempt );
if r then
local e = mw.html.create( "span" )
:addClass( "uri-handle" );
local s;
s, r = attempt:match( "^%s*(10%.[1-9][0-9]+/)(.+)%s*$" );
r = mw.text.decode( r, "PATH" );
r = string.format( "[%s/%s%s %s%s]",
"//doi.org",
s,
mw.uri.encode( r ),
s,
mw.text.encode( r, "<>&%]" ) );
r = tostring( e:wikitext( r ) );
else
r = flop( alert );
end
return r;
end -- URIutil.linkDOI()
function URIutil.linkHandle( attempt, any1, any2, any3, alert )
-- Retrieve bracketed titled external link on handle resolver
-- Precondition:
-- attempt -- string with presumable handle
-- any1 -- intentionally dummy parameter
-- any2 -- intentionally dummy parameter
-- any3 -- intentionally dummy parameter
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns external link, or false
local r = URIutil.isHandle( attempt );
if r then
local e = mw.html.create( "span" )
:addClass( "uri-handle" );
r = mw.text.decode( mw.text.trim( attempt ), "PATH" );
r = string.format( "[%s%s %s]",
"//hdl.handle.net/",
mw.uri.encode( r ),
mw.text.encode( r, "<>&%]" ) );
r = tostring( e:wikitext( r ) );
else
r = flop( alert );
end
return r;
end -- URIutil.linkHandle()
function URIutil.linkISBN( attempt, allow, abbr, adhere, alert )
-- Retrieve bracketed titled wikilink on booksources page with "ISBN"
-- Precondition:
-- attempt -- string with presumable ISBN
-- allow -- true: permit invalid check digit or digit count
-- abbr -- true or string: link ISBN abbreviation
-- adhere -- true: use else: use simple space
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns link
local lapsus;
local source = mw.text.trim( attempt );
local r = string.format( "[[Special:Booksources/%s|", source );
local isbn = ISBNfactory( source );
if type( isbn ) == "table" then
local lenient;
if type( allow ) == "string" then
lenient = ( allow ~= "0" );
else
lenient = allow;
end
if lenient then
lapsus = false;
else
lapsus = ( not ISBNfaith( isbn ) );
end
r = r .. ISBNformat( attempt, isbn );
else
lapsus = not allow;
r = r .. source;
end
r = r .. "]]";
if lapsus then
local e = mw.html.create( "span" )
:addClass( "invalid-ISBN" )
:wikitext( r );
r = tostring( e ) .. fault( "(?!?!)" );
if alert then
r = r .. flop( alert );
end
end
if adhere then
r = " " .. r;
else
r = " " .. r;
end
if abbr then
local cnf = fetch( "config" );
local s = cnf.supportISBN;
if s then
if type( s ) ~= "string"
or s == "" then
s = false;
end
else
s = "International Standard Book Number";
end
if s and s ~= fullPageName() then
s = string.format( "[[%s|ISBN]]", s );
else
s = "ISBN";
end
r = string.format( "%s %s", s, r );
else
r = "ISBN" .. r;
end
return r;
end -- URIutil.linkISBN()
function URIutil.linkISSN( attempt, allow, abbr, adhere, alert )
-- Retrieve bracketed titled external link on ISSN DB with "ISSN"
-- Precondition:
-- attempt -- string with presumable ISSN
-- allow -- true: permit invalid check digit
-- abbr -- true: link ISSN abbreviation
-- adhere -- true: use else: use simple space;
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns link
local r = URIutil.targetISSN( attempt, allow, nil, nil, alert );
if adhere then
r = " " .. r;
else
r = " " .. r;
end
if abbr then
local cnf = fetch( "config" );
local s = cnf.supportISSN;
if s then
if type( s ) ~= "string"
or s == "" then
s = false;
end
else
s = "International Standard Serial Number";
end
if s and s ~= fullPageName() then
s = string.format( "[[%s|ISSN]]", s );
else
s = "ISSN";
end
r = string.format( "%s%s", s, r );
else
r = "ISSN" .. r;
end
return r;
end -- URIutil.linkISSN()
function URIutil.linkLCCN( attempt, achieve, any1, any2, alert )
-- Retrieve bracketed titled external LCCN permalink
-- Precondition:
-- attempt -- string with presumable LCCN
-- achieve -- additional title formatting desires, like "-"
-- any1 -- intentionally dummy parameter
-- any2 -- intentionally dummy parameter
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns link, or false if bad LCCN
local r = LCCNforward( attempt, achieve );
if not r then
r = flop( alert );
end
return r;
end -- URIutil.linkLCCN()
function URIutil.linkURN( attempt, alter, any1, any2, alert, at, alone )
-- Retrieve bracketed titled external URN link
-- Precondition:
-- attempt -- string, with presumable URN, starting with "urn:"
-- alter -- alternative handler
-- any1 -- intentionally dummy parameter
-- any2 -- intentionally dummy parameter
-- alert -- string, with title of maintenance category, or nil
-- at -- fragment, or nil
-- alone -- true, if link text not preceded by "urn:"
-- Postcondition:
-- Returns
-- 1. linked ID, or plain string if bad URN
-- 2. true, if to be preceded by "urn:"
local r2 = true;
local r;
if URIutil.mayURN( attempt ) then
local e = mw.html.create( "span" )
:addClass( "invalid-URN" );
local serial = attempt;
local suffix = flop( alert );
if serial:sub( 1, 4 ):lower() == "urn:" then
serial = serial:sub( 5 );
end
e:wikitext( serial );
r = tostring( e ) .. fault( "(?!?!)" );
if suffix then
r = r .. suffix;
end
else
local s = attempt:match( "^%s*[uU][rR][nN]:(%S+)%s*$" );
if s then
local space, sign = s:match( "^(%w+):(.+)$" );
if space then
local defs = fetch( "urn" );
if type( defs ) == "table" then
local resolver = defs.resolver;
space = space:lower();
resolver = resolver[ space ];
r2 = ( resolver ~= true );
if type( resolver ) == "table" then
r, sign = URNresolve( resolver, sign, alter );
s = string.format( "%s:%s", space, sign );
if r then
r = r:gsub( "%$1", "urn:" .. s );
if at then
r = string.format( "%s#%s", r, at );
end
if alone then
r2 = true;
else
s = "urn:" .. s;
end
r = string.format( "[%s %s]", r, s );
end
elseif r2 then
if type( defs.sns ) == "string" then
s = string.format( ":%s:", space );
if not defs.sns:find( s, 1, true ) then
s = false;
end
else
s = false;
end
if s then
r = string.format( "%s:%s", space, sign );
else
r = string.format( "%s:%s",
space, sign );
end
r2 = not alone;
else
s = "link" .. space:upper();
r = URIutil[ s ]( sign, alter, nil, nil, alert );
end
else
r = fault( "Bad structure in Module:URIutil/urn" );
end
end
end
end
if not r then
if alert then
r = flop( alert ) or "";
if attempt then
r = attempt .. r;
end
else
r = mw.text.trim( attempt );
end
r2 = false;
end
return r, r2;
end -- URIutil.linkURN()
function URIutil.mayDOI( attempt )
-- Is this a syntactically correct DOI, or empty?
-- Precondition:
-- attempt -- string with presumable DOI
-- Postcondition:
-- Returns number of organization
-- 0 if empty
-- false if not empty and not a DOI
local r;
if type( attempt ) == "string" then
local s = mw.text.trim( attempt );
if #s >= 10 then
r = URIutil.isDOI( attempt );
elseif #s == 0 then
r = 0;
else
r = false;
end
else
r = false;
end
return r;
end -- URIutil.mayDOI()
function URIutil.mayHandle( attempt )
-- Is this a meaningful handle, or empty?
-- Precondition:
-- attempt -- string with presumable handle
-- Postcondition:
-- Returns number of organization
-- 0 if empty
-- false if not empty and not a DOI
local r;
if type( attempt ) == "string" then
local s = mw.text.trim( attempt );
if #s > 5 then
r = URIutil.isHandle( attempt );
elseif #s == 0 then
r = 0;
else
r = false;
end
else
r = false;
end
return r;
end -- URIutil.mayHandle()
function URIutil.mayISBN( attempt )
-- Is this a syntactically correct ISBN, or empty?
-- Precondition:
-- attempt -- string with presumable ISBN
-- Postcondition:
-- Returns 10 if 10 digits and hyphens; also X at end of ISBN-10
-- 13 if 13 digits and hyphens; beginning with bookland
-- 0 if empty
-- false if not empty and not an ISBN
local r;
if type( attempt ) == "string" then
local s = mw.text.trim( attempt );
if #s >= 10 then
r = URIutil.isISBN( attempt );
elseif #s == 0 then
r = 0;
else
r = false;
end
else
r = false;
end
return r;
end -- URIutil.mayISBN()
function URIutil.mayISSN( attempt )
-- Is this a correct ISSN, or empty?
-- Precondition:
-- attempt -- string with presumable ISSN
-- Postcondition:
-- Returns 8 if 8 digits and hyphens; also X at end
-- 13 if 13 digits and hyphens; beginning with issnland
-- 0 if empty
-- false if not empty and not an ISSN
local r;
if type( attempt ) == "string" then
local s = mw.text.trim( attempt );
if #s >= 8 then
r = URIutil.isISSNvalid( attempt );
elseif #s == 0 then
r = 0;
else
r = false;
end
else
r = false;
end
return r;
end -- URIutil.mayISSN()
function URIutil.mayLCCN( attempt )
-- Is this a syntactically correct LCCN?
-- Precondition:
-- attempt -- string with presumable LCCN
-- Postcondition:
-- Returns string with LCCN formatted aa9999-99999999
-- 0 if empty
-- false if not recognized
if type( attempt ) == "string" then
local s = mw.text.trim( attempt );
if s == "" then
r = 0;
else
r = URIutil.isLCCN( s );
end
else
r = false;
end
return r;
end -- URIutil.mayLCCN()
function URIutil.mayURI( attempt, ascii )
-- Is this a syntactically correct URI, or empty?
-- Precondition:
-- attempt -- string with presumable URI
-- ascii -- limit to ASCII (no IRI)
-- Postcondition:
-- Returns false if no problem
-- string with violation
local r = URIutil.isEscValid( attempt );
if not r then
local s = mw.text.trim( attempt );
r = s:match( "%s(.+)$" );
if not r then
r = s:match( "#(.*)$" );
if r then
r = "#" .. r;
elseif ascii then
local p = string.format( "[%s].+$",
mw.ustring.char( 128,45,255 ) );
r = mw.ustring.match( s, p );
end
end
end
return r;
end -- URIutil.mayURI()
function URIutil.mayURN( attempt )
-- Is this a syntactically correct URN, or empty?
-- Precondition:
-- attempt -- string with presumable URN, starting with "urn:"
-- Postcondition:
-- Returns false if no problem
-- string with violation
local r = URIutil.mayURI( attempt, true );
if not r then
local s = attempt:match( "^%s*[uU][rR][nN]:(.+)$" );
if s then
local space, id = s:match( "^(%w+):(.+)$" );
if space then
r = URNnamespace( space:lower(), id );
else
r = s;
end
else
s = mw.text.trim( attempt );
if s == "" then
r = false;
elseif s:match( "^https?://" ) then
r = "http:";
else
r = "urn:";
end
end
end
return r;
end -- URIutil.mayURN()
function URIutil.plainISBN( attempt )
-- Format ISBN as digits (and 'X') only string
-- Precondition:
-- attempt -- string with presumable ISBN
-- Postcondition:
-- Returns string with 10 or 13 chars
-- false if not empty and not an ISBN
local r;
local isbn = ISBNfactory( attempt );
if type( isbn ) == "table" then
r = ISBNflat( isbn );
else
r = false;
end
return r;
end -- URIutil.plainISBN()
function URIutil.targetISSN( attempt, allow, any1, any2, alert )
-- Retrieve bracketed titled external link on ISSN DB without "ISSN"
-- Precondition:
-- attempt -- string with presumable ISSN
-- allow -- true: permit invalid check digit
-- any1 -- intentionally dummy parameter
-- any2 -- intentionally dummy parameter
-- alert -- string with title of maintenance category, or nil
-- Postcondition:
-- Returns link
local cnf = fetch( "config" );
local issn = ISSNfactory( attempt );
local lapsus, r;
if type( issn ) == "table" then
local lenient;
if type( allow ) == "string" then
lenient = ( allow ~= "0" );
else
lenient = allow;
end
if lenient then
lapsus = false;
else
lapsus = ( not ISSNfaith( issn ) );
end
r = ISSNformat( issn, issn.type );
if type( cnf.issn ) == "string" then
r = string.format( "[%s %s]",
cnf.issn:gsub( "%$1", r ),
r );
end
else
lapsus = true;
r = attempt;
end
if lapsus then
local e = mw.html.create( "span" )
:addClass( "invalid-ISSN" )
:wikitext( r );
r = tostring( e ) .. fault( "(?!?!)" );
if alert then
r = r .. flop( alert );
end
end
return r;
end -- URIutil.targetISSN()
function URIutil.uriDOI( attempt, anything, abbr )
-- Retrieve linked URI on DOI resolver
-- Precondition:
-- attempt -- string with presumable DOI
-- anything -- intentionally dummy parameter
-- abbr -- true or string: link doi: abbreviation
local r = URIutil.linkDOI( attempt );
if r then
if abbr then
local s;
if type( abbr ) == "string" then
s = abbr;
else
s = "Digital Object Identifier";
end
r = string.format( "[[%s|doi]]:%s", s, r );
else
r = "doi:" .. r;
end
end
return r;
end -- URIutil.uriDOI()
function URIutil.uriHandle( attempt, anything, abbr )
-- Retrieve linked URI on handle resolver
-- Precondition:
-- attempt -- string with presumable handle
-- anything -- intentionally dummy parameter
-- abbr -- true or string: link hdl: abbreviation
local r = URIutil.linkHandle( attempt );
if r then
local s;
if type( abbr ) == "string" then
s = abbr;
end
if s then
r = string.format( "[[%s|hdl]]:%s", s, r );
else
r = "hdl:" .. r;
end
end
return r;
end -- URIutil.uriHandle()
function URIutil.uriURN( attempt, anything, alter, alert, at )
-- Retrieve linked URI on URN resolver
-- Precondition:
-- attempt -- string with presumable URN, starting with "urn:"
-- anything -- intentionally dummy parameter
-- alter -- string with alternative handler, or nil
-- alert -- string with title of maintenance category, or nil
-- at -- fragment, or nil
-- Postcondition:
-- Returns link, or plain string if bad URN
local r, l =
URIutil.linkURN( attempt, alter, false, false, alert, at, true );
if l then
local s = fetch( "config" ).supportURN;
if s then
if type( s ) ~= "string"
or s == "" then
s = false;
end
else
s = "Uniform Resource Name";
end
if s then
r = string.format( "[[%s|urn]]:%s", s, r );
else
r = "urn:" .. r;
end
end
return r;
end -- URIutil.uriURN()
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
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 vsn = entity:formatPropertyValues( "P348" )
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()
local Template = function ( frame, action )
-- Retrieve library result for template access
-- Precondition:
-- frame -- object
-- action -- string; function name
-- Postcondition:
-- Returns appropriate string, or error message (development)
local lucky, r = pcall( URIutil[ action ],
frame.args[ 1 ] or "",
frame.args[ 2 ],
faculty( frame.args.link, true ),
faculty( frame.args.nbsp, true ),
frame.args.cat,
frame.args.fragment );
if lucky then
if r then
r = tostring( r );
else
r = "";
end
else
r = fault( r );
end
return r;
end -- Template()
-- Provide template access and expose URIutil table to require()
local p = {};
function p.coreISSN( frame )
return Template( frame, "coreISSN" );
end
function p.formatISBN( frame )
return Template( frame, "formatISBN" );
end
function p.formatISSN( frame )
return Template( frame, "formatISSN" );
end
function p.formatLCCN( frame )
return Template( frame, "formatLCCN" );
end
function p.isDNBvalid( frame )
return Template( frame, "isDNBvalid" );
end
function p.isDOI( frame )
return Template( frame, "isDOI" );
end
function p.isEscValid( frame )
return Template( frame, "isEscValid" );
end
function p.isGTINvalid( frame )
return Template( frame, "isGTINvalid" );
end
function p.isHandle( frame )
return Template( frame, "isHandle" );
end
function p.isISBN( frame )
return Template( frame, "isISBN" );
end
function p.isISBNvalid( frame )
return Template( frame, "isISBNvalid" );
end
function p.isISSNvalid( frame )
return Template( frame, "isISSNvalid" );
end
function p.isLCCN( frame )
return Template( frame, "isLCCN" );
end
function p.linkDNBopac( frame )
return Template( frame, "linkDNBopac" );
end
function p.linkDOI( frame )
return Template( frame, "linkDOI" );
end
function p.linkDOI( frame )
return Template( frame, "linkDOI" );
end
function p.linkHandle( frame )
return Template( frame, "linkHandle" );
end
function p.linkISBN( frame )
return Template( frame, "linkISBN" );
end
function p.linkISSN( frame )
return Template( frame, "linkISSN" );
end
function p.linkLCCN( frame )
return Template( frame, "linkLCCN" );
end
function p.linkURN( frame )
return Template( frame, "linkURN" );
end
function p.mayDOI( frame )
return Template( frame, "mayDOI" );
end
function p.mayHandle( frame )
return Template( frame, "mayHandle" );
end
function p.mayISBN( frame )
return Template( frame, "mayISBN" );
end
function p.mayISSN( frame )
return Template( frame, "mayISSN" );
end
function p.mayLCCN( frame )
return Template( frame, "mayLCCN" );
end
function p.mayURI( frame )
return Template( frame, "mayURI" );
end
function p.mayURN( frame )
return Template( frame, "mayURN" );
end
function p.plainISBN( frame )
return Template( frame, "plainISBN" );
end
function p.targetISSN( frame )
return Template( frame, "targetISSN" );
end
function p.uriDOI( frame )
return Template( frame, "uriDOI" );
end
function p.uriHandle( frame )
return Template( frame, "uriHandle" );
end
function p.uriURN( frame )
return Template( frame, "uriURN" );
end
p.failsafe = function ( frame )
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()
function p.URIutil( arg )
local r;
if arg then
r = "";
else
r = URIutil;
end
return r;
end
return p;