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
Fulfilling edit request by Speravir. Thanks for helping!
fix variety of errors identified through unit testing, retire functions to be called from other lua modules as most of the functions are quite trivial
Line 1: Line 1:
-- Module for handling Media files (Origin: Wikimedia Commons)
-- Module for handling Media files (Origin: Wikimedia Commons)


-- Helpers
require('Module:No globals')
local h = {}
 
h.expandPage = function(fullPageName, args)
-- ==================================================
-- This expansion may fail, use it with pcall and inspect error status
-- === helper Lookup table ==========================
return mw.getCurrentFrame():expandTemplate{title = ':' .. fullPageName, args}
-- ==================================================
end
 
h.expandPageNoFail = function(fullPageName, args)
local extensionMap = {
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 may be more limits for other supported mime types (djvu, flac, ogv, pdf, svg, webm, xcf).
h.maxthumbMap = {
-- ['image/gif'] = h.expandPageNoFail('Template:LargeTIFF/limit', {}), -- current value is '50' but higher now
['image/png' ] = h.expandPageNoFail('Template:LargePNG/limit', {}), -- current value is '2500'
['image/tiff'] = h.expandPageNoFail('Template:LargeTIFF/limit', {}), -- current value is '50' but higher now
}
h.maxthumbMap['image/gif' ] = h.maxthumbMap['image/tiff'] -- current value is '50' but higher now
h.extensionMap = {
-- File types with full support in Commons (See [[c:Commons:File types]]).
-- File types with full support in Commons (See [[c:Commons:File types]]).
DJVU = 'image/vnd.djvu',
DJVU = 'image/vnd.djvu',
Line 61: Line 46:
FLV  = 'video/x-flv', -- (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'
ICO  = 'image/vnd.microsoft.icon', -- used in MediaWiki resources for 'website icons'
MP4  = 'video/mp4', -- please convert to OGV or WEBM
MP4  = 'video/mp4',  
QT  = 'video/quicktime', -- (deprecated, replaced by MP4) 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
RA  = 'audio/vnd.rn-realaudio', -- (deprecated, replaced by MP3) please convert to OGA
Line 69: Line 54:
XLS  = 'application/vnd.ms-excel', -- please convert to PDF, DJVU, or Wiki
XLS  = 'application/vnd.ms-excel', -- please convert to PDF, DJVU, or Wiki
}
}
h.parse = require("Module:HTMLParser").parse


local File = function(title)
-- ==================================================
local funcs = {}
-- === Local functions ==============================
local titleInstance, metadataInstance
-- ==================================================
 
local function filename(frame)
return frame.args[1] or frame.args["file"] or frame.args["title"]
end


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


function getFullName()
-- ==================================================
return getTitle().prefixedText
-- === External functions ===========================
end
-- ==================================================
local p = {}


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


-- =p.File("Foo.bar.svg").woExtension()
function p.extension(frame)
-- @return "Foo.bar"
return p.csExtension(frame):lower()
-- Original author: Bawolff at [[Module:FileName]]
end
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
function getMetadata()
if metadataInstance == nil then
metadataInstance = getTitle().file
end
return metadataInstance
end
funcs.metadata = function()
return getMetadata()
end


-- Mapping file extensions to MIME-types (only MIME types accepted for files in Commons).
function p.extensionUpper(frame)
-- Works even if file still does not exist.
return p.csExtension(frame):upper()
-- =p.File('Foo.bar.svg').extension()
end
-- @return 'image/svg+xml'
funcs.mime = function()
local ok, metadata = pcall(funcs.metadata())
if ok and metadata.exists 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()
-- p.woExtension("Foo.bar.svg")
funcs.maxthumb = function()
-- @return "Foo.bar"
return h.maxthumbMap[funcs.mime()] or 'unknown @Module:File'
-- Original author: Bawolff at [[Module:FileName]]
end
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


funcs.dateWorkCreated = function()
function p.mime(frame)
-- Parse the expanded wiki text into an html root node and select a child node by specific ID.
local meta  = getMetadata(frame)
local root = h.parse('<html>' ..
if meta.exists then
h.expandPageNoFail(getFullName(), {})
return meta.mimeType
:gsub('<nowiki>.*?</nowiki>', '')
else
.. '</html>')
return extensionMap[p.extensionUpper(frame)] or 'unknown'
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
end
end


return funcs
function p.mimeType(frame)
return getMetadata(frame).mimeType
end
end
h.getFile = function(frame)
 
return File(frame.args[1] or frame.args["file"] or frame.args["title"] or mw.title.getCurrentTitle().text)
function p.fileExists(frame)
return getMetadata(frame).exists or ''
end
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.fileExists = function(frame)
return h.getFile(frame).metadata().exists or ''
end
-- This one won't throw errors at you
-- This one won't throw errors at you
p.fileExistsRelaxed = function(frame)
function p.fileExistsRelaxed(frame)
local ok, metadata = pcall(h.getFile(frame).metadata)
local ok, metadata = pcall(getMetadata(frame))
if ok then
if ok then
return metadata.exists or ''
return metadata.exists or ''
Line 185: Line 140:
end
end
end
end
p.mimeType = function(frame)
 
return h.getFile(frame).metadata().mimeType
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.maxthumb = function(frame)
 
return h.getFile(frame).maxthumb()
function p.dateWorkCreated(frame)
return '' -- no longer supported
end
end
p.dateWorkCreated = function(frame)
 
return h.getFile(frame).dateWorkCreated(frame) or ''
function p.width(frame)
return getMetadata(frame).width
end
end
p.width = function(frame)
 
return h.getFile(frame).metadata().width
function p.height(frame)
return getMetadata(frame).height
end
end
p.height = function(frame)
 
return h.getFile(frame).metadata().height
function p.dimensions(frame)
local d = getMetadata(frame)
if d.exists then
return d.width .. ' × ' .. d.height
else
return ''
end
end
end
p.dimensions = function(frame)
 
local d = h.getFile(frame).metadata()
function p.size(frame)
return d.width .. ' × ' .. d.height
return getMetadata(frame).size
end
end
p.size = function(frame)
 
return h.getFile(frame).metadata().size
function p.pageCount(frame)
end
local pages = getMetadata(frame).pages or {1}
p.pageCount = function(frame)
local pages = h.getFile(frame).metadata().pages or {1}
return #pages
return #pages
end
end
-- Module autotest
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
return p

Revision as of 04:51, 2 January 2021

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 in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|extension|file=File:Test.C.JpeG}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|csExtension|file=File:Test.C.JpeG}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|mime|file=File:DOESNOTEXIST-0a8de8c83.Png}}Lua error in package.lua at line 80: module 'Module:No globals' not found. deprecated (but works even if the file does not exist and has no metadata)
{{#invoke:File|mimeType|file=File:DOESNOTEXIST-0a8de8c83.Png}}Lua error in package.lua at line 80: module 'Module:No globals' not found. 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 in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|fileExists|file=File:DOESNOTEXIST-0a8de8c83.png}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|fileExistsRelaxed|file=File:Ba[!#llot-sprite.png}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|width|file=File:Commons-logo.png}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|height|file=File:Commons-logo.png}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|dimensions|file=File:Commons-logo.png}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
{{#invoke:File|size|file=File:Commons-logo.png}}Lua error in package.lua at line 80: module 'Module:No globals' not found.
-- Module for handling Media files (Origin: Wikimedia Commons)

require('Module:No globals')

-- ==================================================
-- === 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',
	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.