Module:LCCN

require('strict')

local p = {}

local function blank_to_nil(s)

if s and #s > 0 then return s end

end

local function pad(padlen, ...)

padlen = tonumber(padlen) or 0

if 1 > select('#', ...) then

return ("0"):rep(padlen)

end

local padsrc = tostring((...))

local srclen = mw.ustring.len(padsrc)

if 1 > padlen or 1 > srclen then

return ""

end

return mw.ustring.sub(mw.ustring.rep(padsrc, math.ceil(padlen / srclen)), 1, padlen)

end

local function padleft(str, ...)

str = tostring(str)

if 1 > select('#', ...) then

return str

end

local strlen = mw.ustring.len(str)

if 1 > strlen then

return pad((...), select(2, ...))

end

return pad((tonumber((...)) or 0) - strlen, select(2, ...)) .. str

end

local function padright(str, ...)

str = tostring(str)

if 1 > select('#', ...) then

return str

end

local strlen = mw.ustring.len(str)

if 1 > strlen then

return pad((...), select(2, ...))

end

return str .. pad((tonumber((...)) or 0) - strlen , select(2, ...))

end

local function expr(...)

return mw.ext.ParserFunctions.expr( ... )

end

function p.main(frame)

local args = frame:getParent().args

local id = blank_to_nil(args[1] or args.id)

if not id then

error("Template:LCCN: You must provide an ID.")

end

local title = blank_to_nil(args[2] or args.title or args.name)

local letter_width = (id:match("^%s*[0-9][0-9]") and id:len() < 10) and 0 or 2

local left_part = id:sub(1, letter_width + 2)

local right_part = expr(padright(id, letter_width + 8, '.00000'):sub(letter_width + 3, letter_width + 8))

local url = "https://www.loc.gov/item/" .. left_part .. padleft(right_part, 6, 0)

if args.long == "yes" then

return ("Catalog record for [%s %s] at the United States Library of Congress"):format(

url, title or mw.title.getCurrentTitle().text)

end

return ("LCCN [%s %s-%s]%s"):format(

url, left_part, right_part, title and (' – ' .. title) or '')

end

return p