Jump to content
Toggle menu
  • 8 articles
  • 75 files
  • 7 users
  • 37.8K edits
Neodyland Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:File: Difference between revisions

From Neodyland Wiki
mNo edit summary
m fix frame parameter, reduce exports
Line 2: Line 2:


-- Helpers
-- Helpers
local h, File = {}
local h = {}
h.expandPage = function(fullPageName, args)
-- This expansion may fail, use it with pcall and inspect error status
return mw.getCurrentFrame():expandTemplate{title = ':' .. fullPageName, args}
end
h.expandPageNoFail = function(fullPageName, args)
local ok, wikiText = pcall(h.expandPage, fullPageName, args)
if ok then
return wikiText
end
return ''
end
-- Limits in megapixels are currently stored in Commons templates, they could be in this module.
-- There are possibly other limits for other mime types (djvu, flac, ogv, pdf, svg, xcf...).
h.maxthumbMap = {
-- ['image/gif'] = h.expandPageNoFail('Template:LargeTIFF/limit', {}),
['image/png' ] = h.expandPageNoFail('Template:LargePNG/limit', {}),
['image/tiff'] = h.expandPageNoFail('Template:LargeTIFF/limit', {}),
}
h.maxthumbMap['image/gif' ] = h.maxthumbMap['image/tiff']
h.extensionMap = {
-- File types with full support in Commons (See [[c: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) please convert to OGV or WEBM
RA  = 'audio/vnd.rn-realaudio', -- (deprecated, replaced by MP3) please convert to OGA
SWF  = 'video/x-flv', -- (deprecated, replaced by MP4) please 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
}
h.getFile = function(f)
h.getFile = function(f)
return File(f.args[1] or f.args["file"] or f.args["title"] or mw.title.getCurrentTitle().text)
return File(f.args[1] or f.args["file"] or f.args["title"] or mw.title.getCurrentTitle().text)
end
end
h.getWikiText = function(title, frame)
h.parse = require("Module:HTMLParser").parse
return '<html>' .. (frame or mw.getCurrentFrame()):expandTemplate{ title = title, args = {}}:gsub('<nowiki>.*?</nowiki>', '') .. '</html>'
end


File = function(title)
local File = function(title)
local funcs = {}
local funcs = {}
local titleInstance, metadataInstance
local titleInstance, metadataInstance
Line 19: Line 83:
end
end
return titleInstance
return titleInstance
end
function getFullName()
return getTitle().prefixedText
end
end


Line 45: Line 113:
end
end
-- Mapping file extensions to MIME-types (only MIME types accepted for files in Commons)
-- Mapping file extensions to MIME-types (only MIME types accepted for files in Commons).
        -- works even if file still does not exist
-- Works even if file still does not exist.
funcs.extensionMap = {
-- =p.File('Foo.bar.svg').extension()
 
-- @return 'image/svg+xml'
-- 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) please convert to OGV or WEBM
RA  = "audio/vnd.rn-realaudio", -- (deprecated, replaced by MP3) please convert to OGA
SWF  = "video/x-flv", -- (deprecated, replaced by MP4) please 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()
funcs.mime = function()
local metadata = funcs.metadata()
local metadata = funcs.metadata()
if metadata.mimeType then
if metadata.mimeType then
-- Note: does not work if file does not exist, where metadata == ['exists': false] only
-- Note: does not work if file does not exist, where metadata == {'exists': false} only
return metadata.mimeType
return metadata.mimeType
end
end
local extension = funcs.extension():upper()
-- mw.log('mime() is deprecated. Use metadata().mimeType.')
-- mw.log('mime() is deprecated. Use metadata().mimeType.')
return funcs.extensionMap[extension] or "unknown"
return h.extensionMap[funcs.extension():upper()] or 'unknown'
end
end


-- =p.File("Foo.bar.tiff").maxthumb()
-- =p.File('Foo.bar.tiff').maxthumb()
funcs.maxthumb = function()
funcs.maxthumb = function()
local mime = funcs.mime()
return h.maxthumbMap[funcs.mime()] or 'unknown @Module:File'
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
end


funcs.dateWorkCreated = function(frame)
funcs.dateWorkCreated = function()
local page, htmlparser = mw.title.new(title, 6).prefixedText, require("Module:HTMLParser")
-- Parse the expanded wiki text into an html root node and select a child node by specific ID.
local ok, html = pcall(h.getWikiText, page, frame)
local root = h.parse('<html>' ..
if not ok then return nil end
h.expandPageNoFail(getFullName(), {})
-- add a root node
:gsub('<nowiki>.*?</nowiki>', '')
local root = htmlparser.parse(html)
.. '</html>')
local tdElem = root('#fileinfotpl_date')
local tdElem = root('#fileinfotpl_date')
-- We queried an ID so there should be only one result
for td in pairs(tdElem) do -- We queried an ID so there should be only one result in this loop.
for td in pairs(tdElem) do
-- We need the next sibling, which doesn't seem to be directly supported by HTMLParser.
-- We need the next sibling, which doesn't seem to be directly supported by HTMLParser
-- ... so ask him for the parent <tr> node and find the first <time> element in it.
-- ... so ask him for the parent <tr> and find the <time> element in it
local timeElem = td.parent('time')
local timeElem = td.parent('time')
for t in pairs(timeElem) do
for t in pairs(timeElem) do
Line 172: Line 181:
end
end
p.dateWorkCreated = function(frame)
p.dateWorkCreated = function(frame)
return h.getFile(frame).dateWorkCreated() or ''
return h.getFile(frame).dateWorkCreated(frame) or ''
end
end
p.fileExists = function(frame)
p.fileExists = function(frame)
Line 179: Line 188:
-- This one won't throw errors at you
-- This one won't throw errors at you
p.fileExistsRelaxed = function(frame)
p.fileExistsRelaxed = function(frame)
local success, metadata = pcall(h.getFile(frame).metadata)
local ok, metadata = pcall(h.getFile(frame).metadata)
if success then
if ok then
return metadata.exists or ''
return metadata.exists or ''
else
else
Line 196: Line 205:
end
end
p.pageCount = function(frame)
p.pageCount = function(frame)
local pages = h.getFile(frame).metadata().pages or {'page'}
local pages = h.getFile(frame).metadata().pages or {1}
return #pages
return #pages
end
end
Line 203: Line 212:
local toTest = require('Module:File/tests/all')
local toTest = require('Module:File/tests/all')
local result = true
local result = true
for i, t in ipairs(toTest) do
for i, t in ipairs(toTest) do
local f = File(t.fileName)
local f = File(t.fileName)
Line 221: Line 229:
ret = ret and v
ret = ret and v
end
end
mw.log(i, ret and 'passed' or 'FAILED', t.typeOfFileName, (not ret) and ('\n >>' .. stringResult .. '\n     >> ' .. t.fileName) or '')
mw.log(i, ret and 'passed' or 'FAILED', t.typeOfFileName, (not ret) and ('\n\t>>\t' .. t.fileName .. '\n\t>>\t' .. stringResult) or '')
result = result and ret
result = result and ret
end
end
return result
return result
end
end
-- p.h = h -- if needed for running some tests


return p
return p

Revision as of 11:35, 19 May 2017

Module documentation[ view · edit · history · purge ]
This documentation is transcluded from Module:File/doc.

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.[Please clarify – October 2024]

Usage

Note that an error is thrown if the title can't be constructed (e.g. a title containing invalid characters is supplied) or metadata 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

Examples:

{{#invoke:File|woExtension|file=File:Test.C.JpeG}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|extension|file=File:Test.C.JpeG}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|csExtension|file=File:Test.C.JpeG}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|mime|file=File:DOESNOTEXIST-0a8de8c83.Png}}Lua error at line 72: attempt to call global 'File' (a nil value). deprecated (but works even if the file does not exist and has no metadata)
{{#invoke:File|mimeType|file=File:DOESNOTEXIST-0a8de8c83.Png}}Lua error at line 72: attempt to call global 'File' (a nil value). preferred (but will not work if the file does not exist to parse its metadata)
{{#invoke:File|fileExists|file=File:Commons-logo.png}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|fileExists|file=File:DOESNOTEXIST-0a8de8c83.png}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|fileExistsRelaxed|file=File:Ba[!#llot-sprite.png}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|width|file=File:Commons-logo.png}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|height|file=File:Commons-logo.png}}Lua error at line 72: attempt to call global 'File' (a nil value).
{{#invoke:File|dimensions|file=File:Commons-logo.png}}Script error: The function "dimensions" does not exist.
{{#invoke:File|size|file=File:Commons-logo.png}}Lua error at line 72: attempt to call global 'File' (a nil value).
-- Module for handling Media files (Origin: Wikimedia Commons)

-- Helpers
local h = {}
h.expandPage = function(fullPageName, args)
	-- This expansion may fail, use it with pcall and inspect error status
	return mw.getCurrentFrame():expandTemplate{title = ':' .. fullPageName, args}
end
h.expandPageNoFail = function(fullPageName, args)
	local ok, wikiText = pcall(h.expandPage, fullPageName, args)
	if ok then
		return wikiText
	end
	return ''
end
-- Limits in megapixels are currently stored in Commons templates, they could be in this module.
-- There are possibly other limits for other mime types (djvu, flac, ogv, pdf, svg, xcf...).
h.maxthumbMap = {
--	['image/gif'] = h.expandPageNoFail('Template:LargeTIFF/limit', {}),
	['image/png' ] = h.expandPageNoFail('Template:LargePNG/limit', {}),
	['image/tiff'] = h.expandPageNoFail('Template:LargeTIFF/limit', {}),
}
h.maxthumbMap['image/gif' ] = h.maxthumbMap['image/tiff']
h.extensionMap = {
	-- File types with full support in Commons (See [[c: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) please convert to OGV or WEBM
	RA   = 'audio/vnd.rn-realaudio', -- (deprecated, replaced by MP3) please convert to OGA
	SWF  = 'video/x-flv', -- (deprecated, replaced by MP4) please 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
}
h.getFile = function(f)
	return File(f.args[1] or f.args["file"] or f.args["title"] or mw.title.getCurrentTitle().text)
end
h.parse = require("Module:HTMLParser").parse

local 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 getFullName()
		return getTitle().prefixedText
	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).
	-- Works even if file still does not exist.
	-- =p.File('Foo.bar.svg').extension()
	-- @return 'image/svg+xml'
	funcs.mime = function()
		local metadata = funcs.metadata()
		if metadata.mimeType then
			-- Note: does not work if file does not exist, where metadata == {'exists': false} only
			return metadata.mimeType
		end
		-- mw.log('mime() is deprecated. Use metadata().mimeType.')
		return h.extensionMap[funcs.extension():upper()] or 'unknown'
	end

	-- =p.File('Foo.bar.tiff').maxthumb()
	funcs.maxthumb = function()
		return h.maxthumbMap[funcs.mime()] or 'unknown @Module:File'
	end

	funcs.dateWorkCreated = function()
		-- Parse the expanded wiki text into an html root node and select a child node by specific ID.
		local root = h.parse('<html>' ..
			h.expandPageNoFail(getFullName(), {})
				:gsub('<nowiki>.*?</nowiki>', '')
			.. '</html>')
		local tdElem = root('#fileinfotpl_date')
		for td in pairs(tdElem) do -- We queried an ID so there should be only one result in this loop.
			-- We need the next sibling, which doesn't seem to be directly supported by HTMLParser.
			-- ... so ask him for the parent <tr> node and find the first <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.csExtension = function(frame)
	return h.getFile(frame).extension()
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(frame) 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 ok, metadata = pcall(h.getFile(frame).metadata)
	if ok 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 {1}
	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()),
			extensionLower = (t.extensionLower == 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\t>>\t' .. t.fileName .. '\n\t>>\t' .. stringResult) or '')
		result = result and ret
	end
	return result
end
-- p.h = h -- if needed for running some tests

return p
Contents
Cookies help us deliver our services. By using our services, you agree to our use of cookies.