Module:File link: Difference between revisions
imported>Mr. Stradivarius (remove "theName" field from readOnlyFields) |
(Created page with "-- This module provides a library for formatting file wikilinks. local yesno = require('Module:Yesno') local checkType = require('libraryUtil').checkType local p = {} function p._main(args) checkType('_main', 1, args, 'table') -- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our -- own function to get the right error level. local function checkArg(key, val, level) if type(val) ~= 'string' then error(string.format( "type error in...") |
||
(16 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
-- This module provides a library for formatting |
-- This module provides a library for formatting file wikilinks. |
||
local |
local yesno = require('Module:Yesno') |
||
local checkType = libraryUtil.checkType |
local checkType = require('libraryUtil').checkType |
||
local |
local p = {} |
||
function |
function p._main(args) |
||
checkType(' |
checkType('_main', 1, args, 'table') |
||
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) |
|||
'image', |
|||
if type(val) ~= 'string' then |
|||
'image', |
|||
obj, |
|||
'image object' |
|||
) |
|||
-- Set the filename if we were passed it as an input to image.new. |
|||
if filename then |
|||
data.theName = filename |
|||
end |
|||
function data:name(s) |
|||
checkSelf(self, 'image:name') |
|||
checkType('image:name', 1, s, 'string') |
|||
data.theName = s |
|||
return self |
|||
end |
|||
function data:format(s, filename) |
|||
checkSelf(self, 'image:format') |
|||
checkType('image:format', 1, s, 'string') |
|||
checkType('image:format', 2, format, 'string', true) |
|||
local validFormats = { |
|||
thumb = true, |
|||
thumbnail = true, |
|||
frame = true, |
|||
framed = true, |
|||
frameless = true |
|||
} |
|||
if 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)", |
||
key, type(val) |
|||
), |
), level) |
||
end |
end |
||
return self |
|||
end |
end |
||
local |
local ret = {} |
||
-- 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 |
|||
end |
|||
function data:width(px) |
|||
checkSelf(self, 'image:width') |
|||
checkType('image:width', 1, px, 'number') |
|||
if data.isUpright then |
|||
sizeError('image: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, 'image:height') |
|||
local function addNamed(key) |
|||
checkType('image:height', 1, px, 'number') |
|||
local val = args[key] |
|||
if data.isUpright then |
|||
if not val then |
|||
sizeError('image: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(factor) |
|||
checkArg('file', args.file, 3) |
|||
checkSelf(self, 'image:upright') |
|||
ret[#ret + 1] = 'File:' .. args.file |
|||
checkType('image:upright', 1, factor, 'number', true) |
|||
if data.theWidth or data.theHeight then |
|||
-- Format |
|||
sizeError('image:upright') |
|||
if args.format then |
|||
end |
|||
checkArg('format', args.format) |
|||
data.isUpright = true |
|||
if args.formatfile then |
|||
data.uprightFactor = factor |
|||
checkArg('formatfile', args.formatfile) |
|||
return self |
|||
ret[#ret + 1] = args.format .. '=' .. args.formatfile |
|||
end |
|||
function data:resetSize() |
|||
checkSelf(self, 'image:resetSize') |
|||
for i, field in ipairs{'theWidth', 'theHeight', 'isUpright', 'uprightFactor'} do |
|||
data[field] = nil |
|||
end |
|||
return self |
|||
end |
|||
function data:location(s) |
|||
checkSelf(self, 'image:location') |
|||
checkType('image:location', 1, s, 'string') |
|||
local validLocations = { |
|||
right = true, |
|||
left = true, |
|||
center = true, |
|||
none = true |
|||
} |
|||
if validLocations[s] then |
|||
data.theLocation = s |
|||
else |
else |
||
ret[#ret + 1] = args.format |
|||
"bad argument #1 to 'image:location' ('%s' is not a valid location)", |
|||
s |
|||
), 2) |
|||
end |
end |
||
return self |
|||
end |
end |
||
-- Border |
|||
function data:alignment(s) |
|||
if yesno(args.border) then |
|||
checkSelf(self, 'image:alignment') |
|||
ret[#ret + 1] = 'border' |
|||
checkType('image:alignment', 1, s, 'string') |
|||
local validAlignments = { |
|||
baseline = true, |
|||
middle = true, |
|||
sub = true, |
|||
super = true, |
|||
['text-top'] = true, |
|||
['text-bottom'] = true, |
|||
top = true, |
|||
bottom = true |
|||
} |
|||
if validAlignments[s] then |
|||
data.theAlignment = s |
|||
else |
|||
error(string.format( |
|||
"bad argument #1 to 'image:alignment' ('%s' is not a valid alignment)", |
|||
s |
|||
), 2) |
|||
end |
|||
return self |
|||
end |
end |
||
addPositional('location') |
|||
function data:border() |
|||
addPositional('alignment') |
|||
checkSelf(self, 'image:border') |
|||
addPositional('size') |
|||
data.hasBorder = true |
|||
addNamed('upright') |
|||
return self |
|||
addNamed('link') |
|||
addNamed('alt') |
|||
addNamed('page') |
|||
addNamed('class') |
|||
addNamed('lang') |
|||
addNamed('start') |
|||
addNamed('end') |
|||
addNamed('thumbtime') |
|||
addPositional('caption') |
|||
return string.format('[[%s]]', table.concat(ret, '|')) |
|||
end |
|||
function p.main(frame) |
|||
local origArgs = require('Module:Arguments').getArgs(frame, { |
|||
wrappers = 'Template:File link' |
|||
}) |
|||
if not origArgs.file then |
|||
error("'file' parameter missing from [[Template:File link]]", 0) |
|||
end |
end |
||
function data:link(s) |
|||
checkSelf(self, 'image:link') |
|||
checkType('image:link', 1, s, 'string') |
|||
data.theLink = s |
|||
return self |
|||
end |
|||
function data:alt(s) |
|||
checkSelf(self, 'image:alt') |
|||
checkType('image:alt', 1, s, 'string') |
|||
data.theAlt = s |
|||
return self |
|||
end |
|||
function data:caption(s) |
|||
checkSelf(self, 'image:caption') |
|||
checkType('image:caption', 1, s, 'string') |
|||
data.theCaption = s |
|||
return self |
|||
end |
|||
function data:render() |
|||
checkSelf(self, 'image:render') |
|||
local ret = {} |
|||
-- Image name. |
|||
if not data.theName then |
|||
error('image:render: no image name was found') |
|||
end |
|||
ret[#ret + 1] = 'File:' .. data.theName |
|||
-- Image 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 |
|||
-- Copy the arguments that were passed to a new table to avoid looking up |
|||
-- Alignment |
|||
-- every possible parameter in the frame object. |
|||
ret[#ret + 1] = data.theAlignment |
|||
local args = {} |
|||
for k, v in pairs(origArgs) do |
|||
-- Size |
|||
-- Make _BLANK a special argument to add a blank parameter. For use in |
|||
if data.isUpright and data.uprightFactor then |
|||
-- conditional templates etc. it is useful for blank arguments to be |
|||
ret[#ret + 1] = 'upright=' .. tostring(data.uprightFactor) |
|||
-- ignored, but we still need a way to specify them so that we can do |
|||
elseif data.isUpright then |
|||
-- things like [[File:Example.png|link=]]. |
|||
ret[#ret + 1] = 'upright' |
|||
if v == '_BLANK' then |
|||
v = '' |
|||
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 |
end |
||
args[k] = v |
|||
-- Link |
|||
if data.theLink then |
|||
ret[#ret + 1] = 'link=' .. data.theLink |
|||
end |
|||
-- Alt |
|||
if data.theAlt then |
|||
ret[#ret + 1] = 'alt=' .. data.theAlt |
|||
end |
|||
-- Caption |
|||
ret[#ret + 1] = data.theCaption |
|||
return string.format('[[%s]]', table.concat(ret, '|')) |
|||
end |
end |
||
return p._main(args) |
|||
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, |
|||
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 image.new, so remove it. |
|||
local function restrictedFieldError(key, restriction) |
|||
error(string.format( |
|||
"image 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 (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 |
return p |
Latest revision as of 13:41, 1 February 2025
![]() | This Lua module is used on approximately 76,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This module depends on the following other modules: |
This module is used to construct wikitext links to files. It is primarily useful for templates and modules that use complicated logic to make file links. Simple file links should be made with wikitext markup directly, as it uses less resources than calling this module. For help with wikitext file markup please refer to the documentation at mediawiki.org.
Usage from wikitext
From wikitext, this module should be called from a template, usually {{file link}}. Please see the template page for documentation. However, it can also be called using the syntax {{#invoke:File link|main|arguments}}
.
Usage from Lua
First, you need to import the module.
local mFileLink = require('Module:File link')
Then you can make file links using the _main
function.
mFileLink._main(args)
args is a table of arguments that can have the following keys:
file
- the filename. (required)format
- the file format, e.g. 'thumb', 'thumbnail', 'frame', 'framed', or 'frameless'.formatfile
- a filename to specify with the 'thumbnail' format option. The filename specified will be used instead of the automatically generated thumbnail.border
- set this to true or "yes" (or any other value recognized as true by Module:Yesno) to set a border for the image.location
- the horizontal alignment of the file, e.g. 'right', 'left', 'center', or 'none'.alignment
- the vertical alignment of the file, e.g. 'baseline', 'middle', 'sub', 'super', 'text-top', 'text-bottom', 'top', or 'bottom'.size
- the size of the image, e.g. '100px', 'x100px' or '100x100px'.upright
- the 'upright' parameter, used for setting the size of tall and thin images.link
- the page that the file should link to. Use the blank string '' to suppress the default link to the file description page.alt
- the alt text. Use the blank string '' to suppress the default alt text.caption
- a caption for the file.page
- sets a page number for multi-paged files such as PDFs.class
- adds aclass
parameter to image links. The MediaWiki software adds this parameter to theclass="..."
attribute of the image's<img />
element when the page is rendered into HTML.lang
- adds a language attribute to specify what language to render the file in.start
- specifies a start time for audio and video files.end
- specifies an end time for audio and video files.thumbtime
- specifies the time to use to generate the thumbnail image for video files.
To see the effect of each of these parameters, see the images help page on mediawiki.org.
Examples
With the file only:
mFileLink.main{file = 'Example.png'}
-- Renders as [[File:Example.png]]
With format, size, link and caption options:
mFileLink.main{
file = 'Example.png',
format = 'thumb',
size = '220px',
link = 'Wikipedia:Sandbox',
caption = 'An example.'
}
-- Renders as [[File:Example.png|thumb|220px|link=Wikipedia:Sandbox|An example.]]
With format, size, and border:
mFileLink.main{
file = 'Example.png',
format = 'frameless',
size = '220px',
border = true
}
-- Renders as [[File:Example.png|frameless|border|220px]]
-- This module provides a library for formatting file wikilinks.
local yesno = require('Module:Yesno')
local checkType = require('libraryUtil').checkType
local p = {}
function p._main(args)
checkType('_main', 1, args, 'table')
-- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our
-- own function to get the right error level.
local function checkArg(key, val, level)
if type(val) ~= 'string' then
error(string.format(
"type error in '%s' parameter of '_main' (expected string, got %s)",
key, type(val)
), level)
end
end
local ret = {}
-- Adds a positional parameter to the buffer.
local function addPositional(key)
local val = args[key]
if not val then
return nil
end
checkArg(key, val, 4)
ret[#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 addNamed(key)
local val = args[key]
if not val then
return nil
end
checkArg(key, val, 4)
ret[#ret + 1] = key .. '=' .. val
end
-- Filename
checkArg('file', args.file, 3)
ret[#ret + 1] = 'File:' .. args.file
-- Format
if args.format then
checkArg('format', args.format)
if args.formatfile then
checkArg('formatfile', args.formatfile)
ret[#ret + 1] = args.format .. '=' .. args.formatfile
else
ret[#ret + 1] = args.format
end
end
-- Border
if yesno(args.border) then
ret[#ret + 1] = 'border'
end
addPositional('location')
addPositional('alignment')
addPositional('size')
addNamed('upright')
addNamed('link')
addNamed('alt')
addNamed('page')
addNamed('class')
addNamed('lang')
addNamed('start')
addNamed('end')
addNamed('thumbtime')
addPositional('caption')
return string.format('[[%s]]', table.concat(ret, '|'))
end
function p.main(frame)
local origArgs = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:File link'
})
if not origArgs.file then
error("'file' parameter missing from [[Template:File link]]", 0)
end
-- Copy the arguments that were passed to a new table to avoid looking up
-- every possible parameter in the frame object.
local args = {}
for k, v in pairs(origArgs) do
-- Make _BLANK a special argument to add a blank parameter. 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
-- things like [[File:Example.png|link=]].
if v == '_BLANK' then
v = ''
end
args[k] = v
end
return p._main(args)
end
return p