require ('strict');
local data = mw.loadData ('Module:Format ISBN/data'); -- fetch separator positioning data local hyphen_pos_t = data.hyphen_pos_t; -- the hyphen positioning data k/v table local index_t = data.index_t; -- an index sequence into the hyphen positioning data table; used by binary_search local idx_count = data.count; -- from count = #index_t; in ~/data; used by binary_search
----------------------------< B I N A R Y _ S E A R C H >----------------------------------------------------
do a binary search for the hyphen positioning data for
accepts one input
returns index into
local function binary_search (target_isbn) target_isbn = tonumber (target_isbn); -- convert to number because index_t[x] values are numbers
if (index_t[1] >= target_isbn) or (index_t[idx_count] < target_isbn) then -- invalid; out of range; 9780000000000 to whatever the last value is return; -- TODO: return something meaningful? end local idx_bot = 1; -- initialize to index 1 (first element in
----------------------------< C O N V E R T _ T O _ I S B N 1 0 >--------------------------------------------
convert 13-digit isbn to 10-digit isbn; removes 978 GS1 prefix and recalculates the check digit
takes a single input; the 13-digit isbn as a string without separators
assumes that the GS1 prefix is 978; there is no mapping between isbn10 and 979-prefixed isbn13. calling functionsare required to ensure that
local function convert_to_isbn10 (isbn13) local isbn9 = isbn13:sub (4, 12); -- get the 9 digits of
local check = 0; -- initialize the check digit calculation local i = 1; -- index for j=10, 2, -1 do --
check = check % 11; -- remainder of the weighted-digit-products divided by 11
if 0
check) and 'X' or check); -- when
----------------------------< C O N V E R T _ T O _ I S B N 1 3 >--------------------------------------------
convert 10-digit isbn to 13-digit isbn; adds 978 GS1 prefix and recalculates the check digit
takes a single input; the 10-digit isbn as a string (no separators)
local function convert_to_isbn13 (isbn10) local isbn12 = '978'.. isbn10:sub(1, 9); -- concatenate '978' with first 9 digits of
--out=) on success; initial
local function _format_isbn (isbn_str, show_err_msg, separator, output_format, template_name) if (not isbn_str) or (
local isbn_str_raw = isbn_str; -- this will be the return value if unable to format isbn_str = isbn_str:gsub ('[^%dX]', ); -- strip all formatting (spaces and hyphens) from the isbn/sbn
local flags = ; -- a convenient place for flag stuff if '13'
output_format then flags.out10 = true; end
if 9
if 13
#isbn_str then -- if isbn10 or sbn flags.isbn10_check_digit = isbn_str:sub (-1); -- extract the check digit for later isbn_str = convert_to_isbn13 (isbn_str); -- convert isbn10 to isbn13 for formatting end local index = binary_search (isbn_str); -- look for the formatting that applies to
isbn_str = table.concat (result_t, separator and ' ' or '-'); -- assemble formatted
if flags.isbn10_check_digit then -- if we saved the check digit from an sbn or isbn10 if flags.sbn then -- when input is an sbn isbn_str = isbn_str:gsub ('^978%-0%-', ):gsub ('%d$', flags.isbn10_check_digit); -- remove GS1 prefix element and registration group element; restore check digit else -- when input is an isbn10 if not flags.out13 then isbn_str = isbn_str:gsub ('^978%-', ):gsub ('%d$', flags.isbn10_check_digit); -- remove GS1 prefix element; restore check digit end end end
return isbn_str; -- return formatted
return isbn_str_raw; -- should never actually be reached; but, if we do, return original input stringend
--2 template |isbn= params, no point in causing confusion due to multiple error messages
|separator=space – render formatted ISBN with spaces instead of hyphens |out= – takes either of 10 or 13 to specify the output format if different from the default
local function format_plain (frame) local args_t = require ('Module:Arguments').getArgs (frame); -- get template and invoke parameters local isbn_str = args_t[1]; local separator = 'space'
return _format_isbn (isbn_str, nil, separator, output_format); -- no error messagingend
--suppress-errors=yes – suppress error messages |separator=space – render formatted ISBN with spaces instead of hyphens |out= – takes either of 10 or 13 to specify the output format if different from the default
local function format_linked (frame) local args_t = require ('Module:Arguments').getArgs (frame); -- get template and invoke parameters local isbn_str = args_t[1]; local show_err_msg = 'yes' ~= args_t['suppress-errors']; -- always show errors unless |suppress-errors=yes local separator = 'space'
local formatted_isbn_str, err_msg = _format_isbn (isbn_str, show_err_msg, separator, output_format, args_t.template_name); -- show error messages unless suppressed if err_msg then return formatted_isbn_str .. ' ' .. err_msg; -- return unformatted, unlinked isbn and error message else return '' .. formatted_isbn_str ..''; -- return formatted and linked isbn endend
----------------------------< E X P O R T S >----------------------------------------------------------------
return