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
Adding height, width, fileExists, pageCount for template use and File.metadata() for Lua use
Add webp to list of supported file types
 
(25 intermediate revisions by 7 users not shown)
Line 1: Line 1:
-- Module for handling Media files (Origin: Wikimedia Commons)
-- Module for handling Media files (Origin: Wikimedia Commons)


-- Helpers
require('strict')
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 )
-- === helper Lookup table ==========================
end
-- ==================================================
h.getWikiText = function(title, frame)
 
return '<html>' .. (frame or mw.getCurrentFrame()):expandTemplate{ title = title, args = {}}:gsub('<nowiki>.*?</nowiki>', '') .. '</html>'
local extensionMap = {
end
-- 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',
MP3  = 'audio/mpeg',
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',
WEBP = 'image/webp',
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


File = function(title)
-- Other file types not supported and to convert (a few of them may be in special administration namespaces).
local funcs = {}
DOC  = 'application/msword', -- please convert to PDF, DJVU, or Wiki
local titleInstance, metadataInstance
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'
MP4  = 'video/mp4',
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
}


function getTitle()
-- ==================================================
if titleInstance == nil then
-- === Local functions ==============================
titleInstance = mw.title.new( title )
-- ==================================================
end
return titleInstance
end


function getMetadata()
local function filename(frame)
if metadataInstance == nil then
return frame.args[1] or frame.args["file"] or frame.args["title"]
metadataInstance = getTitle().file
end
end
return metadataInstance
end


-- =p.File("Foo.bar.svg").extension()
local function getMetadata(frame)
-- @return "svg"
local fname = filename(frame)
funcs.extension = function()
local title
local parts = mw.text.split( title, '.', true )
if fname then
return parts[#parts]
        title = mw.title.new(fname, 6)
end
else
-- =p.File("Foo.bar.svg").woExtension()
        title = mw.title.getCurrentTitle()
-- 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
funcs.extensionMap = {
PNG  = "image/png",
GIF  = "image/gif",
SVG  = "image/svg+xml",
TIFF = "image/tiff",
TIF  = "image/tiff",
JPEG = "image/jpeg",
JPG  = "image/jpeg"
}
-- =p.File("Foo.bar.svg").mime()
funcs.mime = function()
local extension = funcs.extension():upper()
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 = 'File:' .. title, 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
end
funcs.metadata = function()
if title then
return getMetadata()
return title.file
else
return {exists=false}
end
end
return funcs
end
end


-- @exports
-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}
local p = {}
p.File = File
 
p.extension = function(frame)
-- p.csExtension("Foo.bar.svg")
return h.getFile(frame).extension():lower()
-- @return "svg"
function p.csExtension(frame)
local fname = filename(frame) or mw.title.getCurrentTitle().text
local parts = mw.text.split(fname, '.', true)
if #parts>1 then
return parts[#parts]
else
return ''
end
end
end
p.extensionUpper = function(frame)
 
return h.getFile(frame).extension():upper()
function p.extension(frame)
return p.csExtension(frame):lower()
end
end
p.woExtension = function(frame)
 
return h.getFile(frame).woExtension()
function p.extensionUpper(frame)
return p.csExtension(frame):upper()
end
end
p.mime = function(frame)
 
return h.getFile(frame).mime()
-- p.woExtension("Foo.bar.svg")
-- @return "Foo.bar"
-- Original author: Bawolff at [[Module:FileName]]
function p.woExtension(frame)
local fname = filename(frame) or mw.title.getCurrentTitle().text
local parts = mw.text.split(fname , '.', true)
local upTo = #parts - 1
if upTo == 0 then upTo = 1 end
return table.concat(parts, '.', 1, upTo)
end
end
p.maxthumb = function(frame)
 
return h.getFile(frame).maxthumb()
function p.mime(frame)
local meta  = getMetadata(frame)
if meta.exists then
return meta.mimeType
else
return extensionMap[p.extensionUpper(frame)] or 'unknown'
end
end
 
function p.mimeType(frame)
return getMetadata(frame).mimeType
end
end
p.dateWorkCreated = function(frame)
 
return h.getFile(frame).dateWorkCreated() or ''
function p.fileExists(frame)
return getMetadata(frame).exists or ''
end
end
p.fileExists = function(frame)
 
return h.getFile(frame).metadata().exists
-- This one won't throw errors at you
function p.fileExistsRelaxed(frame)
local ok, metadata = pcall(getMetadata(frame))
if ok then
return metadata.exists or ''
else
return ''
end
end
end
p.width = function(frame)
 
return h.getFile(frame).metadata().width
function p.maxthumb(frame)
-- Limits in megapixels are currently stored in Commons templates, they could be in this module.
-- There may be more limits for other supported mime types (djvu, flac, ogv, pdf, svg, webm, xcf).
local maxthumbMap = {
['image/gif']  = 1000,
['image/png' ] = 2500, -- see Template:LargePNG/limit
['image/tiff'] = 1000, -- see Template:LargeTIFF/limit
}
local mime = p.mime(frame)
return maxthumbMap[mime] or 'unknown @Module:File'
end
end
p.height = function(frame)
 
return h.getFile(frame).metadata().height
function p.dateWorkCreated(frame)
return '' -- no longer supported
end
end
p.pageCount = function(frame)
 
local pages = h.getFile(frame).metadata().pages or {'page'}
function p.width(frame)
return #pages
return getMetadata(frame).width
end
 
function p.height(frame)
return getMetadata(frame).height
end
end


p.runTests = function()
function p.dimensions(frame)
local toTest = require('Module:File/tests/all')
local d = getMetadata(frame)
local result = true
if d.exists then
return d.width .. ' × ' .. d.height 
for i, t in ipairs(toTest) do
else
local f = File(t.fileName)
return ''
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
end
return result
end
 
function p.size(frame)
return getMetadata(frame).size
end
 
function p.pageCount(frame)
local pages = getMetadata(frame).pages or {1}
return #pages
end
end


return p
return p

Latest revision as of 15:32, 29 October 2024

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

Scope

edit

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

edit

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

edit

Examples:

{{#invoke:File|woExtension|file=File:Test.C.JpeG}}File:Test.C
{{#invoke:File|extension|file=File:Test.C.JpeG}}jpeg
{{#invoke:File|csExtension|file=File:Test.C.JpeG}}JpeG
{{#invoke:File|mime|file=File:DOESNOTEXIST-0a8de8c83.Png}}image/png deprecated (but works even if the file does not exist and has no metadata)
{{#invoke:File|mimeType|file=File:DOESNOTEXIST-0a8de8c83.Png}} preferred (but will not work if the file does not exist to parse its metadata)
{{#invoke:File|fileExists|file=File:Commons-logo.png}}true
{{#invoke:File|fileExists|file=File:DOESNOTEXIST-0a8de8c83.png}}
{{#invoke:File|fileExistsRelaxed|file=File:Ba[!#llot-sprite.png}}
{{#invoke:File|width|file=File:Commons-logo.png}}114
{{#invoke:File|height|file=File:Commons-logo.png}}153
{{#invoke:File|dimensions|file=File:Commons-logo.png}}114 × 153
{{#invoke:File|size|file=File:Commons-logo.png}}5557
-- Module for handling Media files (Origin: Wikimedia Commons)

require('strict')

-- ==================================================
-- === helper Lookup table ==========================
-- ==================================================

local 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',
	MP3  = 'audio/mpeg',
	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',
	WEBP = 'image/webp',
	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'
	MP4  = 'video/mp4', 
	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
}

-- ==================================================
-- === Local functions ==============================
-- ==================================================

local function filename(frame)
	return frame.args[1] or frame.args["file"] or frame.args["title"] 
end

local function getMetadata(frame)
	local fname = filename(frame)
	local title
	if fname then
        title = mw.title.new(fname, 6)
	else
        title = mw.title.getCurrentTitle()
	end
	if title then
		return title.file
	else
		return {exists=false}
	end
end

-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}

-- p.csExtension("Foo.bar.svg")
-- @return "svg"
function p.csExtension(frame)
	local fname = filename(frame) or mw.title.getCurrentTitle().text
	local parts = mw.text.split(fname, '.', true)
	if #parts>1 then
		return parts[#parts]
	else
		return ''
	end
end

function p.extension(frame)
	return p.csExtension(frame):lower()
end

function p.extensionUpper(frame)
	return p.csExtension(frame):upper()
end

-- p.woExtension("Foo.bar.svg")
-- @return "Foo.bar"
-- Original author: Bawolff at [[Module:FileName]]
function p.woExtension(frame)
	local fname = filename(frame) or mw.title.getCurrentTitle().text
	local parts = mw.text.split(fname , '.', true)
	local upTo = #parts - 1
	if upTo == 0 then upTo = 1 end
	return table.concat(parts, '.', 1, upTo)
end

function p.mime(frame)
	local meta  = getMetadata(frame)
	if meta.exists then
		return meta.mimeType
	else
		return extensionMap[p.extensionUpper(frame)] or 'unknown'
	end
end 

function p.mimeType(frame)
	return getMetadata(frame).mimeType
end

function p.fileExists(frame)
	return getMetadata(frame).exists or ''
end

-- This one won't throw errors at you
function p.fileExistsRelaxed(frame)
	local ok, metadata = pcall(getMetadata(frame))
	if ok then
		return metadata.exists or ''
	else
		return ''
	end
end

function p.maxthumb(frame)
-- Limits in megapixels are currently stored in Commons templates, they could be in this module.
-- There may be more limits for other supported mime types (djvu, flac, ogv, pdf, svg, webm, xcf).
	local maxthumbMap = {
		['image/gif']  = 1000, 
		['image/png' ] = 2500, -- see Template:LargePNG/limit
		['image/tiff'] = 1000, -- see Template:LargeTIFF/limit
	}
	local mime = p.mime(frame)
	return maxthumbMap[mime] or 'unknown @Module:File'
end

function p.dateWorkCreated(frame)
	return '' -- no longer supported
end

function p.width(frame)
	return getMetadata(frame).width
end

function p.height(frame)
	return getMetadata(frame).height
end

function p.dimensions(frame)
	local d = getMetadata(frame)
	if d.exists then
		return d.width .. ' × ' .. d.height  
	else
		return ''
	end
end

function p.size(frame)
	return getMetadata(frame).size
end

function p.pageCount(frame)
	local pages = getMetadata(frame).pages or {1}
	return #pages
end

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