Modul:URIutil: Unterschied zwischen den Versionen
te>PerfektesChaos (updates) |
te>PerfektesChaos (update) |
||
Zeile 1: | Zeile 1: | ||
− | --[=[ URIutil 2013- | + | --[=[ URIutil 2013-11-03 |
Utilities for URI etc. | Utilities for URI etc. | ||
* coreISSN() | * coreISSN() | ||
Zeile 744: | Zeile 744: | ||
local isbn; | local isbn; | ||
if type( assigned ) == "table" then | if type( assigned ) == "table" then | ||
− | isbn = | + | isbn = assigned; |
else | else | ||
isbn = ISBNfactory( attempt ); | isbn = ISBNfactory( attempt ); | ||
Zeile 1.026: | Zeile 1.026: | ||
-- Precondition: | -- Precondition: | ||
-- attempt -- string with presumable DOI | -- attempt -- string with presumable DOI | ||
+ | -- Postcondition: | ||
+ | -- Returns external link, or false | ||
local r = URIutil.isDOI( attempt ); | local r = URIutil.isDOI( attempt ); | ||
if r then | if r then | ||
r = mw.text.decode( mw.text.trim( attempt ), "PATH" ); | r = mw.text.decode( mw.text.trim( attempt ), "PATH" ); | ||
− | r = string.format( "[%s %s]", | + | r = string.format( "[%s%s %s]", |
− | "http://dx.doi.org/" | + | "http://dx.doi.org/", |
+ | mw.uri.encode( r ), | ||
mw.text.encode( r, "<>&%]" ) ); | mw.text.encode( r, "<>&%]" ) ); | ||
end | end |
Version vom 3. November 2013, 22:34 Uhr
Die Dokumentation für dieses Modul kann unter Modul:URIutil/Doku erstellt werden
--[=[ URIutil 2013-11-03
Utilities for URI etc.
* coreISSN()
* formatISBN()
* formatISSN()
* formatLCCN()
* isDNBvalid()
* isDOI()
* isEscValid()
* isGTINvalid()
* isISBN()
* isISBNvalid()
* isISSNvalid()
* isLCCN()
* linkDOI()
* linkISBN()
* linkISSN()
* linkLCCN()
* mayDOI()
* mayISBN()
* mayISSN()
* mayLCCN()
* mayURI()
* mayURN()
* plainISBN()
* uriDOI()
* URIutil()
loadData: URIutil/config URIutil/isbn
]=]
-- table for export
local URIutil = {};
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 == n 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 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 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
r = factory( attempt, 10 );
if type( r ) == "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 lucky, def = pcall( mw.loadData, "Module:URIutil/isbn" );
if type( def ) == "table" then
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
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 + 1 ] > 4 then
k = 3;
if assigned[ j + 1 ] > 8 then
k = 4;
if assigned[ j + 2 ] > 8 then
k = false; -- invalid
end
end
end
end
if k then
n = format( assigned, j, k );
r = r .. n .. "-";
j = j + k;
n = ISBNfold( assigned, m, tonumber( n ), j );
if n > 0 then
r = 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 = 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
r = ( fair( assert ) == assert[ 8 ] );
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 = format( assigned, 1, 4 ) .. "-" ..
format( assigned, 5, 3 );
x = assigned[ 8 ];
elseif assigned.type == 13 then
r = 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 = "977-" .. format( assigned, 1, 7 ) .. "-00-"
.. GTINfair( assigned );
elseif assigned.type == 13 then
r = "977-" .. 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
-- 2013-08-25
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:tolower()
: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
serial = serial:match( "^0*([1-9][%d]*)$" );
if not serial then
r = false;
elseif #serial < 6 then
r.serial = mw.ustring.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 = 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
-- 2013-07-14
local lccn = LCCNfactory( attempt );
local r;
if lccn then
r = LCCNformat( lccn, false );
if r then
if achieve then
r = r .. " " .. LCCNformat( lccn, achieve );
else
r = r .. " " .. r;
end
r = "[http://lccn.loc.gov/" .. r .. "]";
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
-- string with violation
local lucky, r = pcall( mw.loadData, "Module:URIutil/config" );
if type( r ) == "table" then
r = r.urn;
if type( r ) == "table" then
local s = r.sns;
if type( s ) == "string" then
r = ":" .. area .. ":";
if s:match( r ) then
s = "[^%w%(%)%+,%-%.:=@;%$_!%*'].*$";
r = acquire:match( s );
else
r = ":" .. 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
else
r = "Module:URIutil/config.urn.sns";
end
else
r = "Module:URIutil/config.urn";
end
end
return r;
end -- URNnamespace()
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
-- currently not implemented
-- 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
-- 2013-09-01
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, #s );
end
end
elseif #s > 7 then
if s:match( "^[0-9]+$" ) then
dnb = factory( s, false );
end
end
if type( dnb ) == "table" then
if j then
if DNBfaith( dnb, true ) then
r = 2011;
end
else
if DNBfaith( dnb, false ) then
r = dnb.type;
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( "^ *10%.([1-9][0-9]+)/(.+) *$" );
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.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)
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)
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.linkDOI( attempt )
-- Retrieve bracketed titled external link on DOI resolver
-- Precondition:
-- attempt -- string with presumable DOI
-- Postcondition:
-- Returns external link, or false
local r = URIutil.isDOI( attempt );
if r then
r = mw.text.decode( mw.text.trim( attempt ), "PATH" );
r = string.format( "[%s%s %s]",
"http://dx.doi.org/",
mw.uri.encode( r ),
mw.text.encode( r, "<>&%]" ) );
end
return r;
end -- URIutil.linkDOI()
function URIutil.linkISBN( attempt, allow, abbr, adhere )
-- Retrieve bracketed titled wikilink on booksources page with "ISBN"
-- Precondition:
-- attempt -- string with presumable ISBN
-- allow -- true: permit invalid check digit
-- abbr -- true or string: link ISBN abbreviation
-- adhere -- true: use else: use simple space;
-- Postcondition:
-- Returns link
local lapsus;
local source = mw.text.trim( attempt );
local r = "[[Special:Booksources/" .. 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 = true;
r = r .. source;
end
r = r .. "]]";
if lapsus then
r = "<span class='invalid-ISBN'>"
.. r
.. "</span><span class=\"error\">(?!?!)</span>";
end
if adhere then
r = " " .. r;
else
r = " " .. r;
end
if abbr then
local s;
if type( abbr ) == "string" then
s = abbr;
else
s = "International Standard Book Number";
end
r = string.format( "[[%s|ISBN]]%s", s, r );
else
r = "ISBN" .. r;
end
return r;
end -- URIutil.linkISBN()
function URIutil.linkISSN( attempt, allow, abbr, adhere )
-- Retrieve bracketed titled external link on ISSN DB with "ISSN"
-- Precondition:
-- attempt -- string with presumable ISSN
-- allow -- true: permit invalid check digit
-- abbr -- true or string: link ISSN abbreviation
-- adhere -- true: use else: use simple space;
-- Postcondition:
-- Returns link
local issn = ISSNfactory( attempt );
local lapsus;
local r;
if type( issn ) == "table" then
local lucky, cnf = pcall( mw.loadData, "Module:URIutil/config" );
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 ) == "table" then
if type( cnf.issn ) == "string" then
r = string.format( "[%s %s]",
cnf.issn:gsub( "%$1", r ),
r );
end
end
else
lapsus = true;
r = attempt;
end
if lapsus then
r = "<span class='invalid-ISSN'>"
.. r
.. "</span><span class=\"error\">(?!?!)</span>";
end
if adhere then
r = " " .. r;
else
r = " " .. r;
end
if abbr then
local s;
if type( abbr ) == "string" then
s = abbr;
else
s = "International Standard Serial Number";
end
r = string.format( "[[%s|ISSN]]%s", s, r );
else
r = "ISSN" .. r;
end
return r;
end -- URIutil.linkISSN()
function URIutil.linkLCCN( attempt, achieve )
-- Retrieve bracketed titled external LCCN permalink
-- Precondition:
-- attempt -- string with presumable LCCN
-- achieve -- additional title formatting desires, like "-"
-- Postcondition:
-- Returns link, or false if bad LCCN
return LCCNforward( attempt, achieve );
end -- URIutil.linkLCCN()
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.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 pat = mw.ustring.char( 128,45,255 );
pat = "[" .. pat .. "].+$";
r = mw.ustring.match( s, pat );
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
-- 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 ns, id = s:match( "^(%w+):(.+)$" );
if ns then
r = URNnamespace( ns:lower(), id );
else
r = s;
end
elseif mw.text.trim( attempt ) == "" then
r = false;
else
r = "urn:";
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.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()
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 ) );
if lucky then
if r then
r = tostring( r );
else
r = "";
end
else
r = "<span class=\"error\">" .. r .. "</span>";
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.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.linkDOI( frame )
return Template( frame, "linkDOI" );
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.mayDOI( frame )
return Template( frame, "mayDOI" );
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.uriDOI( frame )
return Template( frame, "uriDOI" );
end
function p.URIutil()
return URIutil;
end
return p;