-- This module provides a library for formatting file wikilinks.
local libraryUtil checkType = require('libraryUtil')local checkType = libraryUtil.checkType
local fileLink p = {}
function fileLinkp.new_main(filenameargs) checkType('fileLink.new_main', 1, filenameargs, 'stringtable', true) local obj, data = {}, {} local checkSelf = -- This is basically libraryUtil.makeCheckSelfFunction( 'fileLink'checkTypeForNamedArg, 'fileLink', obj, 'fileLink object' ) but we are rolling our -- Set own function to get the filename if we were passed it as an input to fileLink.newright error level. if filename then data.theName = filename end local function data:namecheckArg(s) checkSelf(selfkey, val, 'name'level) checkTypeif type('fileLink:name', 1, s, 'string'val) data.theName ~= s return self end function data:format(s, filename) checkSelf(self, 'format') checkType('fileLink:format', 1, s, 'string', true) checkType('fileLink:format', 2, format, 'string', true) local validFormats = { thumb = true, thumbnail = true, frame = true, framed = true, frameless = true } if s == nil or validFormats[s] then data.theFormat = s data.theFormatFilename = filename else
error(string.format(
"bad argument #1 to type error in 'fileLink:format%s' parameter of '_main' ('expected string, got %s' is not a valid format)", skey, type(val) ), 2level)
end
return self
end
local function sizeError(methodName)ret = {} -- Used for formatting duplication errors in size-related methods. error(string.format( "duplicate size argument detected in '%s'" Adds a positional parameter to the buffer.. " ('upright' cannot be used in conjunction with height or width)", methodName ), 3) end local function data:widthaddPositional(pxkey) checkSelf(self, 'width') checkType('fileLink:width', 1, px, 'number', true)local val = args[key] if px and data.isUpright not val then sizeError('fileLink:width')return nil
end
data.theWidth = pxcheckArg(key, val, 4) return selfret[#ret + 1] = val
end
-- Adds a named parameter to the buffer. We assume that the parameter name -- is the same as the argument key. local function data:height(px) checkSelfaddNamed(self, 'height'key) checkType('fileLink:height', 1, px, 'number', true)local val = args[key] if px and data.isUpright not val then sizeError('fileLink:height')return nil
end
datacheckArg(key, val, 4) ret[#ret + 1] = key ..theHeight '= px return self' .. val
end
-- Filename function data:upright(isUpright, factor) checkSelfcheckArg(self, 'upright') checkType('fileLink:uprightfile', 1, isUpright, 'boolean'args.file, true3) checkType( ret[#ret + 1] = 'fileLinkFile:upright', 2, factor, 'number', true) if isUpright and (data.theWidth or data.theHeight) then sizeError('fileLink:upright') end dataargs.isUpright = isUpright data.uprightFactor = factorfile return self end-- Format function data:resetSize()if args.format then checkSelfcheckArg(self, 'resetSizeformat', args.format) for i, field in ipairs{'theWidth', 'theHeight', 'isUpright', 'uprightFactor'} doif args.formatfile then data[field] = nil end return self end function data:location(s) checkSelfcheckArg(self, 'location') checkType('fileLink:locationformatfile', 1, s, 'string', trueargs.formatfile) local validLocations = { right = true, left = true, center = true, none = true } if s == nil or validLocationsret[s#ret + 1] then data= args.format ..theLocation '= s' .. args.formatfile
else
error(stringret[#ret + 1] = args.format( "bad argument #1 to 'fileLink:location' ('%s' is not a valid location)", s ), 2)
end
return self
end
function data:alignment(s)
checkSelf(self, 'alignment')
checkType('fileLink:alignment', 1, s, 'string', true)
local validAlignments = {
baseline = true,
middle = true,
sub = true,
super = true,
['text-top'] = true,
['text-bottom'] = true,
top = true,
bottom = true
}
if s == nil or validAlignments[s] then
data.theAlignment = s
else
error(string.format(
"bad argument #1 to 'fileLink:alignment' ('%s' is not a valid alignment)",
s
), 2)
end
return self
end
function data:border(hasBorder)
checkSelf(self, 'border')
checkType('fileLink:border', 1, hasBorder, 'boolean', true)
data.hasBorder = hasBorder
return self
end
function data:link(s)
checkSelf(self, 'link')
checkType('fileLink:link', 1, s, 'string', true)
data.theLink = s
return self
end
function data:alt(s)
checkSelf(self, 'alt')
checkType('fileLink:alt', 1, s, 'string', true)
data.theAlt = s
return self
end
function data:page(num)
checkSelf(self, 'page')
checkType('fileLink:page', 1, num, 'number', true)
data.thePage = s
return self
end
function data:class(s)
checkSelf(self, 'class')
checkType('fileLink:class', 1, s, 'string', true)
data.theClass = s
return self
end
function data:lang(s)
checkSelf(self, 'lang')
checkType('fileLink:lang', 1, s, 'string', true)
data.theLang = s
return self
end
local function checkTypeStringOrNumaddPositional(funcName, pos, arg'border') local argType = type addPositional(arg) if argType ~= 'nillocation' and argType ~= 'string' and argType ~= 'number' then) error(string.format addPositional( "bad argument #%d to '%salignment' (string or number expected, got %s)", pos, funcName, argType ), 3) end end function data:startTimeaddPositional(time'size') checkSelf addNamed(self, 'startTimeupright') checkTypeStringOrNum addNamed('fileLink:startTimelink', 1, time) data.theStartTime = time return self end function data:endTimeaddNamed(time'alt') checkSelf addNamed(self, 'endTimepage') checkTypeStringOrNum addNamed('fileLink:endTimeclass', 1, time) data.theEndTime = time return self end function data:thumbTime(time) checkSelfaddNamed(self, 'thumbTimelang') checkTypeStringOrNum addNamed('fileLink:thumbTimestart', 1, time) data.theThumbTime = time return self end function data:caption(s) checkSelfaddNamed(self, 'captionend') checkType addNamed('fileLink:captionthumbtime', 1, s, 'string', true) data.theCaption = s return self end function data:renderaddPositional() checkSelf(self, 'rendercaption') local ret = {} -- Filename if not data return string.theName then errorformat('fileLink:render: no filename was found') end ret[#ret + 1[%s] = 'File:' .. data.theName -- Format if data.theFormat and data.theFormatFilename then ret[#ret + 1] = data.theFormat .. '=' , table.. data.theFormatFilename elseif data.theFormat then concat(ret[#ret + 1] = data.theFormat end -- Border if data.hasBorder then ret[#ret + 1] = , 'border|')) end -- Location ret[#ret + 1] = data.theLocation
-- Alignment ret[#ret + 1] = data.theAlignment -- Size if data.isUpright and data.uprightFactor then ret[#ret + 1] = 'upright=' .function p. tostringmain(data.uprightFactorframe) elseif data.isUpright then ret[#ret + 1] local origArgs = require('uprightModule:Arguments' elseif data).theWidth and data.theHeight then ret[#ret + 1] = string.formatgetArgs('%dx%dpx'frame, data.theWidth, data.theHeight){ elseif data.theWidth then ret[#ret + 1] wrappers = tostring(data.theWidth) .. 'pxTemplate:File link' elseif data.theHeight then ret[#ret + 1] = string.format('x%dpx', data.theHeight }) end -- Render named parameters.Copy the arguments that were passed to a new table to avoid looking up -- That includes link, alt, page, class, lang, start, end, and thumbtimeevery possible parameter in the frame object. do local namedParameters args = { {'link', 'theLink'}, {'alt', 'theAlt'}, {'page', 'thePage'}, {'class', 'theClass'}, {'lang', 'theLang'}, {'start', 'theStartTime'}, {'end', 'theEndTime'}, {'thumbtime', 'theThumbTime'} } for ik, t v in ipairspairs(namedParametersorigArgs) do local -- Make _BLANK a special argument to add a blank parameter = t[1]. For use in -- conditional templates etc. it is useful for blank arguments to be -- ignored, but we still need a way to specify them so that we can do local value = data -- things like [t[2File:Example.png|link=]]. if value v == '_BLANK' then ret[#ret + 1] v = parameter .. '=' .. tostring(value) end end
end
-- Caption retargs[#ret + 1k] = data.theCaption return string.format('[[%s]]', table.concat(ret, '|'))v
end
local privateFields = { theName = true, theFormat = true, theFormatFilename = true, theWidth = true, theHeight = true, isUpright = true, uprightFactor = true, theLocation = true, theAlignment = true, hasBorder = true, theLink = true, theAlt = true, thePage = true, theClass = true, theLang = true, theCaption = true } local readOnlyFields = {} for field in pairs(data) do readOnlyFields[field] = true end readOnlyFields.theName = nil -- This is set if a filename is given to fileLink.new, so remove itreturn p. local function restrictedFieldError(key, restriction) error(string.format( "fileLink object field '%s' is %s", tostring(key), restriction ), 3) end setmetatable(obj, { __index = function (t, key) if privateFields[key] then restrictedFieldError(key, 'private') else return data[key] end end, __newindex = function (t, key, value) if privateFields[key] then restrictedFieldError(key, 'private') elseif readOnlyFields[key] then restrictedFieldError(key, 'read-only') else data[key] = value end end, __tostring = function _main(targs) return t:render() end, __pairs = function () local temp = {} for k, v in pairs(data) do if not privateFields[k] then temp[k] = v end end return pairs(temp) end }) return obj
end
return fileLinkp