Only you can help us build a free scout media repository!
Please create an account to start uploading your images now.

Module:File

From ScoutMedia, the free scout media repository

Scope

File title and file information. If the code here grows beyond a border line, this should be converted to an interface and the processing code should be outsourced.

Usage

Note that an error is thrown, if the title can't be constructed (e.g. a title containing invalid characters is supplied) or meta data isn't available (e.g. due to missing file or extraction error). It is your responsibility to catch them; in Lua through pcall(); from Wikitext as {{#iferror: {{#invoke:File|function|file=File:P%bar]baz.qqq}} | meaningful message}}.

From Wikitext

Search (Lua error in Module:LangSwitch at line 135: attempt to concatenate a nil value.+F) for @exports.

Examples:
{{#invoke:File|extension|file=File:Test.jpg}}jpg
{{#invoke:File|width|file=File:Test.jpg}}414
{{#invoke:File|size|file=File:Test.jpg}}6782
{{#invoke:File|mime|file=File:Test.jpg}}image/jpeg deprecated
{{#invoke:File|mimeType|file=File:Test.jpg}}image/jpeg
{{#invoke:File|dateWorkCreated|file=File:Ballot-sprite.png}}
{{#invoke:File|fileExists|file=File:Ballot-sprite.png}}
{{#invoke:File|fileExists|file=File:DOESNOTEXIST-0a8de8c83.png}}
{{#invoke:File|fileExistsRelaxed|file=File:Ba[!#llot-sprite.png}}

From Lua

<source lang="Lua"> local file = require( 'Module:File' ) local fileObj = file.File( 'File:Test.svg' ) local withoutExtension = fileObj.woExtension() -- withoutExtension is now 'Test'

local exists = fileObj.metadata().exists if exists then

  mw.log( fileObj.metadata().width )

end </source>


-- Module for handling Media files (Origin: Wikimedia Commons)

-- Helpers
local h, File = {}
h.getFile = function(f)
	return File( f.args[1] or f.args["file"] or f.args["title"] or mw.title.getCurrentTitle().text )
end
h.getWikiText = function(title, frame)
	return '<html>' .. (frame or mw.getCurrentFrame()):expandTemplate{ title = title, args = {}}:gsub('<nowiki>.*?</nowiki>', '') .. '</html>'
end

File = function(title)
	local funcs = {}
	local titleInstance, metadataInstance

	function getTitle()
		if titleInstance == nil then
			titleInstance = mw.title.new( title, 6 )
		end
		return titleInstance
	end

	function getMetadata()
		if metadataInstance == nil then
			metadataInstance = getTitle().file
		end
		return metadataInstance
	end

	-- =p.File("Foo.bar.svg").extension()
	-- @return "svg"
	funcs.extension = function()
		local parts = mw.text.split( title, '.', true )
		return parts[#parts]
	end
	-- =p.File("Foo.bar.svg").woExtension()
	-- Original author: Bawolff at [[Module:FileName]]
	-- @return "Foo.bar"
	funcs.woExtension = function()
		local parts = mw.text.split( title , '.', true )
		local upTo = #parts - 1
		if upTo == 0 then upTo = 1 end
		return table.concat( parts, '.', 1, upTo )
	end
	-- Mapping file extensions to MIME-types (only MIME types accepted for files in Commons)
	funcs.extensionMap = {

		-- File types with full support in Commons (See [[Commons:File types]])
		DJVU = "image/vnd.djvu",
		FLAC = "audio/x-flac",
		GIF  = "image/gif",
		JPEG = "image/jpeg",
		JPG  = "image/jpeg",
		MID  = "audio/midi",
		OGA  = "audio/ogg",
		OGG  = "audio/ogg",
		OGV  = "video/ogg",
		PDF  = "application/pdf",
		PNG  = "image/png",
		SVG  = "image/svg+xml",
		TIF  = "image/tiff",
		TIFF = "image/tiff",
		WEBM = "video/webm",
		WAV  = "audio/x-wav",
		XCF  = "image/xcf",

		-- Other file types with restrictions (not accepted in standard uploads on Commons but in "User:" namespace)
		-- They could be supported in Wiki pages by embedding their content in an <pre> or <source> elements
		CSS  = "text/css",
		CSV  = "text/csv",
		JS   = "application/javascript",
		JSON = "application/json",
		TXT  = "text/plain",
		XML  = "application/xml",

		-- Only generated by MediaWiki on output of some queries, restricted in all uploads
		GZ   = "application/gzip", -- delivered only only for some wiki results
		ZIP  = "application/zip", -- delivered only for some wiki data exports

		-- Other file types not supported and to convert (a few of them may be in special administration namespaces)
		DOC  = "application/msword", -- please convert to PDF, DJVU, or Wiki
		F4V  = "video/mpeg", -- (deprecated, replaced by MP4) please convert to OGV or WEBM
		FLV  = "video/x-flv", -- (deprecated, replaced by MP4) please convert to OGV or WEBM
		ICO  = "image/vnd.microsoft.icon", -- used in MediaWiki resources for "website icons"
		MP3  = "audio/mpeg", -- please convert to OGA
		MP4  = "video/mpeg", -- please convert to OGV or WEBM
		QT   = "video/quicktime", -- (deprecated, replaced by MP4) convert to OGV or WEBM
		RA   = "audio/vnd.rn-realaudio", -- (deprecated, replaced by MP3) convert to OGA
		SWF  = "video/x-flv", -- (deprecated, replaced by MP4) convert to OGV or WEBM
		WMA  = "audio/x-ms-wma", -- please convert to OGA
		WMV  = "video/x-ms-wmv", -- please convert to OGV or WEBM
		XLS  = "application/vnd.ms-excel", -- please convert to PDF, DJVU, or Wiki

	}
	-- =p.File("Foo.bar.svg").extension()
	-- @return "image/svg+xml"
	funcs.mime = function()
		local extension = funcs.extension():upper()
		mw.log( 'mime() is deprecated. Use mimeType.' )
		return funcs.extensionMap[extension] or "unknown"
	end
	-- =p.File("Foo.bar.tiff").maxthumb()
	funcs.maxthumb = function()
		local mime = funcs.mime()
		if mime == "image/png" then
			return mw.getCurrentFrame():preprocess( '{{LargePNG/limit}}' )
		elseif mime == "image/tiff" or mime == "image/gif" then
			return mw.getCurrentFrame():preprocess( '{{LargeTIFF/limit}}' )
		else
			return 'unknown @Module:File'
		end
	end
	funcs.dateWorkCreated = function(frame)
		local page, htmlparser = mw.title.new( title, 6 ).prefixedText, require("Module:HTMLParser")
		local ok, html = pcall( h.getWikiText, page, frame )
		if not ok then return nil end
		-- add a root node
		local root = htmlparser.parse(html)
		local tdElem = root('#fileinfotpl_date')
		-- We queried an ID so there should be only one result
		for td in pairs(tdElem) do
			-- We need the next sibling, which doesn't seem to be directly supported by HTMLParser
			-- ... so ask him for the parent <tr> and find the <time> element in it
			local timeElem = td.parent('time')
			for t in pairs(timeElem) do
				return t.attributes['datetime']
			end
		end
	end
	funcs.metadata = function()
		return getMetadata()
	end
	return funcs
end

-- @exports
local p = {}
p.File = File
p.extension = function(frame)
	return h.getFile(frame).extension():lower()
end
p.extensionUpper = function(frame)
	return h.getFile(frame).extension():upper()
end
p.woExtension = function(frame)
	return h.getFile(frame).woExtension()
end
p.mime = function(frame)
	return h.getFile(frame).mime()
end
p.mimeType = function(frame)
	return h.getFile(frame).metadata().mimeType
end
p.maxthumb = function(frame)
	return h.getFile(frame).maxthumb()
end
p.dateWorkCreated = function(frame)
	return h.getFile(frame).dateWorkCreated() or ''
end
p.fileExists = function(frame)
	return h.getFile(frame).metadata().exists or ''
end
-- This one won't throw errors at you
p.fileExistsRelaxed = function(frame)
	local success, metadata = pcall(h.getFile(frame).metadata)
	if success then
		return metadata.exists or ''
	else
		return ''
	end
end
p.width = function(frame)
	return h.getFile(frame).metadata().width
end
p.height = function(frame)
	return h.getFile(frame).metadata().height
end
p.size = function(frame)
	return h.getFile(frame).metadata().size
end
p.pageCount = function(frame)
	local pages = h.getFile(frame).metadata().pages or {'page'}
	return #pages
end

p.runTests = function()
	local toTest = require('Module:File/tests/all')
	local result = true
	
	for i, t in ipairs(toTest) do
		local f = File(t.fileName)
		local stringResult = ''
		local ret = true
		local results = {
			extension = (t.extension == f.extension():lower()),
			extensionUpper = (t.extensionUpper == f.extension():upper()),
			woExtension = (t.woExtension == f.woExtension()),
			mime = (t.mime == f.mime()),
			maxthumb = (not (tonumber(f.maxthumb()) == nil) == t.maxthumbIsNumber),
			dateWorkCreated = t.dateWorkCreated == f.dateWorkCreated()
		}
		for k, v in pairs(results) do
			stringResult = stringResult .. k .. ': ' .. (v and 'ok    ' or 'failed') .. ' '
			ret = ret and v
		end
		mw.log(i, ret and 'passed' or 'FAILED', t.typeOfFileName, (not ret) and ('\n >>' .. stringResult .. '\n     >> ' .. t.fileName) or '')
		result = result and ret
	end
	return result
end

return p