Module:File link: Difference between revisions

Jump to navigation Jump to search
Content added Content deleted
(remove "theName" field from readOnlyFields)
(allow nil values as input to most of the functions, to make call-chaining with conditional variables easier)
Line 31: Line 31:
function data:format(s, filename)
function data:format(s, filename)
checkSelf(self, 'image:format')
checkSelf(self, 'image:format')
checkType('image:format', 1, s, 'string')
checkType('image:format', 1, s, 'string', true)
checkType('image:format', 2, format, 'string', true)
checkType('image:format', 2, format, 'string', true)
local validFormats = {
local validFormats = {
Line 40: Line 40:
frameless = true
frameless = true
}
}
if validFormats[s] then
if s == nil or validFormats[s] then
data.theFormat = s
data.theFormat = s
data.theFormatFilename = filename
data.theFormatFilename = filename
Line 63: Line 63:
function data:width(px)
function data:width(px)
checkSelf(self, 'image:width')
checkSelf(self, 'image:width')
checkType('image:width', 1, px, 'number')
checkType('image:width', 1, px, 'number', true)
if data.isUpright then
if px and data.isUpright then
sizeError('image:width')
sizeError('image:width')
end
end
Line 73: Line 73:
function data:height(px)
function data:height(px)
checkSelf(self, 'image:height')
checkSelf(self, 'image:height')
checkType('image:height', 1, px, 'number')
checkType('image:height', 1, px, 'number', true)
if data.isUpright then
if px and data.isUpright then
sizeError('image:height')
sizeError('image:height')
end
end
Line 81: Line 81:
end
end
function data:upright(factor)
function data:upright(isUpright, factor)
checkSelf(self, 'image:upright')
checkSelf(self, 'image:upright')
checkType('image:upright', 1, factor, 'number', true)
checkType('image:upright', 1, isUpright, 'boolean', true)
checkType('image:upright', 2, factor, 'number', true)
if data.theWidth or data.theHeight then
if isUpright and (data.theWidth or data.theHeight) then
sizeError('image:upright')
sizeError('image:upright')
end
end
data.isUpright = true
data.isUpright = isUpright
data.uprightFactor = factor
data.uprightFactor = factor
return self
return self
Line 102: Line 103:
function data:location(s)
function data:location(s)
checkSelf(self, 'image:location')
checkSelf(self, 'image:location')
checkType('image:location', 1, s, 'string')
checkType('image:location', 1, s, 'string', true)
local validLocations = {
local validLocations = {
right = true,
right = true,
Line 109: Line 110:
none = true
none = true
}
}
if validLocations[s] then
if s == nil or validLocations[s] then
data.theLocation = s
data.theLocation = s
else
else
Line 122: Line 123:
function data:alignment(s)
function data:alignment(s)
checkSelf(self, 'image:alignment')
checkSelf(self, 'image:alignment')
checkType('image:alignment', 1, s, 'string')
checkType('image:alignment', 1, s, 'string', true)
local validAlignments = {
local validAlignments = {
baseline = true,
baseline = true,
Line 133: Line 134:
bottom = true
bottom = true
}
}
if validAlignments[s] then
if s == nil or validAlignments[s] then
data.theAlignment = s
data.theAlignment = s
else
else
Line 144: Line 145:
end
end
function data:border()
function data:border(hasBorder)
checkSelf(self, 'image:border')
checkSelf(self, 'image:border')
data.hasBorder = true
checkType('image:border', 1, hasBorder, 'boolean', true)
data.hasBorder = hasBorder
return self
return self
end
end
Line 152: Line 154:
function data:link(s)
function data:link(s)
checkSelf(self, 'image:link')
checkSelf(self, 'image:link')
checkType('image:link', 1, s, 'string')
checkType('image:link', 1, s, 'string', true)
data.theLink = s
data.theLink = s
return self
return self
Line 159: Line 161:
function data:alt(s)
function data:alt(s)
checkSelf(self, 'image:alt')
checkSelf(self, 'image:alt')
checkType('image:alt', 1, s, 'string')
checkType('image:alt', 1, s, 'string', true)
data.theAlt = s
data.theAlt = s
return self
return self
Line 166: Line 168:
function data:caption(s)
function data:caption(s)
checkSelf(self, 'image:caption')
checkSelf(self, 'image:caption')
checkType('image:caption', 1, s, 'string')
checkType('image:caption', 1, s, 'string', true)
data.theCaption = s
data.theCaption = s
return self
return self

Revision as of 11:47, 30 May 2014

Documentation for this module may be created at Module:File link/doc

-- This module provides a library for formatting image wikilinks.

local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType

local image = {}

function image.new(filename)
	checkType('image.new', 1, filename, 'string', true)
	local obj, data = {}, {}
	
	local checkSelf = libraryUtil.makeCheckSelfFunction(
		'image',
		'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', true)
		checkType('image: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 'image:format' ('%s' is not a valid format)",
				s
			), 2)
		end
		return self
	end

	local function sizeError(methodName)
		-- Used for formatting duplication errors in size-related methods.
		error(string.format(
			"duplicate size argument detected in '%s'"
			.. " ('upright' cannot be used in conjunction with height or width)",
			methodName
		), 3)
	end
	
	function data:width(px)
		checkSelf(self, 'image:width')
		checkType('image:width', 1, px, 'number', true)
		if px and data.isUpright then
			sizeError('image:width')
		end
		data.theWidth = px
		return self
	end
	
	function data:height(px)
		checkSelf(self, 'image:height')
		checkType('image:height', 1, px, 'number', true)
		if px and data.isUpright then
			sizeError('image:height')
		end
		data.theHeight = px
		return self
	end
	
	function data:upright(isUpright, factor)
		checkSelf(self, 'image:upright')
		checkType('image:upright', 1, isUpright, 'boolean', true)
		checkType('image:upright', 2, factor, 'number', true)
		if isUpright and (data.theWidth or data.theHeight) then
			sizeError('image:upright')
		end
		data.isUpright = isUpright
		data.uprightFactor = factor
		return self
	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', true)
		local validLocations = {
			right = true,
			left = true,
			center = true,
			none = true
		}
		if s == nil or validLocations[s] then
			data.theLocation = s
		else
			error(string.format(
				"bad argument #1 to 'image:location' ('%s' is not a valid location)",
				s
			), 2)
		end
		return self
	end
	
	function data:alignment(s)
		checkSelf(self, 'image:alignment')
		checkType('image: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 'image:alignment' ('%s' is not a valid alignment)",
				s
			), 2)
		end
		return self
	end
	
	function data:border(hasBorder)
		checkSelf(self, 'image:border')
		checkType('image:border', 1, hasBorder, 'boolean', true)
		data.hasBorder = hasBorder
		return self
	end
	
	function data:link(s)
		checkSelf(self, 'image:link')
		checkType('image:link', 1, s, 'string', true)
		data.theLink = s
		return self
	end
	
	function data:alt(s)
		checkSelf(self, 'image:alt')
		checkType('image:alt', 1, s, 'string', true)
		data.theAlt = s
		return self
	end
	
	function data:caption(s)
		checkSelf(self, 'image:caption')
		checkType('image:caption', 1, s, 'string', true)
		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

		-- 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
		
		-- 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
	
	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

return image