Editing Module:File link

From Guild of Archivists
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
-- This module provides a library for formatting file wikilinks.
-- This module provides a library for formatting file wikilinks.
 
local yesno = require('Module:Yesno')
local libraryUtil = require('libraryUtil')
local checkType = require('libraryUtil').checkType
local checkType = libraryUtil.checkType
 
local p = {}
local fileLink = {}
 
function p._main(args)
function fileLink.new(filename)
checkType('_main', 1, args, 'table')
checkType('fileLink.new', 1, filename, 'string', true)
 
local obj, data = {}, {}
-- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our
-- own function to get the right error level.
local checkSelf = libraryUtil.makeCheckSelfFunction(
local function checkArg(key, val, level)
'fileLink',
if type(val) ~= 'string' then
'fileLink',
obj,
'fileLink object'
)
-- Set the filename if we were passed it as an input to fileLink.new.
if filename then
data.theName = filename
end
function data:name(s)
checkSelf(self, 'name')
checkType('fileLink:name', 1, s, 'string')
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(
error(string.format(
"type error in '%s' parameter of '_main' (expected string, got %s)",
"bad argument #1 to 'fileLink:format' ('%s' is not a valid format)",
key, type(val)
s
), level)
), 2)
end
end
return self
end
end
 
local ret = {}
local function sizeError(methodName)
 
-- Used for formatting duplication errors in size-related methods.
-- Adds a positional parameter to the buffer.
error(string.format(
local function addPositional(key)
"duplicate size argument detected in '%s'"
local val = args[key]
.. " ('upright' cannot be used in conjunction with height or width)",
if not val then
methodName
return nil
), 3)
end
function data:width(px)
checkSelf(self, 'width')
checkType('fileLink:width', 1, px, 'number', true)
if px and data.isUpright then
sizeError('fileLink:width')
end
end
checkArg(key, val, 4)
data.theWidth = px
ret[#ret + 1] = val
return self
end
end
 
-- Adds a named parameter to the buffer. We assume that the parameter name
function data:height(px)
-- is the same as the argument key.
checkSelf(self, 'height')
local function addNamed(key)
checkType('fileLink:height', 1, px, 'number', true)
local val = args[key]
if px and data.isUpright then
if not val then
sizeError('fileLink:height')
return nil
end
end
checkArg(key, val, 4)
data.theHeight = px
ret[#ret + 1] = key .. '=' .. val
return self
end
end
 
-- Filename
function data:upright(isUpright, factor)
checkArg('file', args.file, 3)
checkSelf(self, 'upright')
ret[#ret + 1] = 'File:' .. args.file
checkType('fileLink:upright', 1, isUpright, 'boolean', true)
 
checkType('fileLink:upright', 2, factor, 'number', true)
-- Format
if isUpright and (data.theWidth or data.theHeight) then
if args.format then
sizeError('fileLink:upright')
checkArg('format', args.format)
end
if args.formatfile then
data.isUpright = isUpright
checkArg('formatfile', args.formatfile)
data.uprightFactor = factor
ret[#ret + 1] = args.format .. '=' .. args.formatfile
return self
end
function data:resetSize()
checkSelf(self, 'resetSize')
for i, field in ipairs{'theWidth', 'theHeight', 'isUpright', 'uprightFactor'} do
data[field] = nil
end
return self
end
function data:location(s)
checkSelf(self, 'location')
checkType('fileLink:location', 1, s, 'string', true)
local validLocations = {
right = true,
left = true,
center = true,
none = true
}
if s == nil or validLocations[s] then
data.theLocation = s
else
else
ret[#ret + 1] = args.format
error(string.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 checkTypeStringOrNum(funcName, pos, arg)
local argType = type(arg)
if argType ~= 'nil' and argType ~= 'string' and argType ~= 'number' then
error(string.format(
"bad argument #%d to '%s' (string or number expected, got %s)",
pos,
funcName,
argType
), 3)
end
end
end
end
 
-- Border
function data:startTime(time)
if yesno(args.border) then
checkSelf(self, 'startTime')
ret[#ret + 1] = 'border'
checkTypeStringOrNum('fileLink:startTime', 1, time)
data.theStartTime = time
return self
end
end
 
addPositional('location')
function data:endTime(time)
addPositional('alignment')
checkSelf(self, 'endTime')
addPositional('size')
checkTypeStringOrNum('fileLink:endTime', 1, time)
addNamed('upright')
data.theEndTime = time
addNamed('link')
return self
addNamed('alt')
end
addNamed('page')
addNamed('class')
function data:thumbTime(time)
addNamed('lang')
checkSelf(self, 'thumbTime')
addNamed('start')
checkTypeStringOrNum('fileLink:thumbTime', 1, time)
addNamed('end')
data.theThumbTime = time
addNamed('thumbtime')
return self
addPositional('caption')
end
 
return string.format('[[%s]]', table.concat(ret, '|'))
function data:caption(s)
end
checkSelf(self, 'caption')
 
checkType('fileLink:caption', 1, s, 'string', true)
function p.main(frame)
data.theCaption = s
local origArgs = require('Module:Arguments').getArgs(frame, {
return self
wrappers = 'Template:File link'
})
if not origArgs.file then
error("'file' parameter missing from [[Template:File link]]", 0)
end
end
 
-- Copy the arguments that were passed to a new table to avoid looking up
function data:render()
-- every possible parameter in the frame object.
checkSelf(self, 'render')
local args = {}
local ret = {}
for k, v in pairs(origArgs) do
-- Make _BLANK a special argument to add a blank parameter. For use in
-- Filename
-- conditional templates etc. it is useful for blank arguments to be
if not data.theName then
-- ignored, but we still need a way to specify them so that we can do
error('fileLink:render: no filename was found')
-- things like [[File:Example.png|link=]].
if v == '_BLANK' then
v = ''
end
end
args[k] = v
ret[#ret + 1] = 'File:' .. data.theName
-- Format
if data.theFormat and data.theFormatFilename then
ret[#ret + 1] = data.theFormat .. '=' .. data.theFormatFilename
elseif data.theFormat then
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=' .. tostring(data.uprightFactor)
elseif data.isUpright then
ret[#ret + 1] = 'upright'
elseif data.theWidth and data.theHeight then
ret[#ret + 1] = string.format('%dx%dpx', data.theWidth, data.theHeight)
elseif data.theWidth then
ret[#ret + 1] = tostring(data.theWidth) .. 'px'
elseif data.theHeight then
ret[#ret + 1] = string.format('x%dpx', data.theHeight)
end
-- Render named parameters.
-- That includes link, alt, page, class, lang, start, end, and thumbtime.
do
local namedParameters = {
{'link', 'theLink'},
{'alt', 'theAlt'},
{'page', 'thePage'},
{'class', 'theClass'},
{'lang', 'theLang'},
{'start', 'theStartTime'},
{'end', 'theEndTime'},
{'thumbtime', 'theThumbTime'}
}
for i, t in ipairs(namedParameters) do
local parameter = t[1]
local value = data[t[2]]
if value then
ret[#ret + 1] = parameter .. '=' .. tostring(value)
end
end
end
-- Caption
ret[#ret + 1] = data.theCaption
return string.format('[[%s]]', table.concat(ret, '|'))
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 it.
local function restrictedFieldError(key, restriction)
error(string.format(
"fileLink object field '%s' is %s",
tostring(key),
restriction
), 3)
end
end
return p._main(args)
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 (t)
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
end
 
return p
return fileLink
Please note that all contributions to Guild of Archivists may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see GoArch:Copyrights for details). Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)

Templates used on this page: