Module:FileMedia
Appearance
local FileMedia = { suite = "FileMedia",
serial = "2023-01-01",
item = 24765326 }
--[=[
FileMedia
]=]
local Failsafe = FileMedia
FileMedia.extension = { storage = "FileMediaExt.tab" }
FileMedia.getExtension = function ( ask )
-- Retrieve "file name extension" from file name
-- Precondition:
-- ask -- file name; string, or nil
-- Postcondition:
-- Returns string, or false
local r = false
local s = FileMedia.getTitle( ask )
if s then
s = ask:match( ".%.(%w+)%s*$" )
if s then
r = s:lower()
end
end
return r
end -- FileMedia.getExtension()
FileMedia.getHeight = function ( ask )
-- Retrieve image height
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns number, or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.height
end
end
return r
end -- FileMedia.getHeight()
FileMedia.getHeightWidth = function ( ask )
-- Retrieve image height x width
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns string like "123x456px", or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.height
if r then
r = string.format("%dx%dpx", r, d.file.width)
end
end
end
return r
end -- FileMedia.getHeightWidth()
FileMedia.getMimeType = function ( ask )
-- Retrieve file MimeType
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns string, or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.mimeType
end
end
return r
end -- FileMedia.getMimeType()
FileMedia.getPageCount = function ( ask )
-- Retrieve number of file pages (paged media fragments)
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns number (0 if not paged media), or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.pages
if r then
r = #r
elseif d.file.size then
r = 0
end
end
end
return r
end -- FileMedia.getPageCount()
FileMedia.getPages = function ( ask )
-- Retrieve table of file page sizes (paged media fragments)
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns table, or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.pages
end
end
return r
end -- FileMedia.getPages()
FileMedia.getSize = function ( ask )
-- Retrieve file size
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns number, or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.size
end
end
return r
end -- FileMedia.getSize()
FileMedia.getTitle = function ( ask )
-- Retrieve file page title from page name
-- Precondition:
-- ask -- file name; string, or nil
-- Postcondition:
-- Returns string, or false if not a valid file
local r = false
if FileMedia.isType( ask, "file" ) then
local space, s = ask:match( "^([^:]+):(.+)$" )
if space then
if FileMedia.isSpacing( space ) then
r = mw.text.trim( s )
end
else
r = mw.text.trim( ask )
end
end
return r
end -- FileMedia.getTitle()
FileMedia.getType = function ( ask )
-- Retrieve supposed file type from "file name extension"
-- Precondition:
-- ask -- file name; string, or nil
-- Postcondition:
-- Returns string, or false
-- "audio"
-- "data"
-- "paged"
-- "pixel"
-- "program"
-- "style"
-- "vector"
-- "video"
local r = false
if ask then
local s = ask:match( ".%.(%w+)%s*$" )
if s then
if not FileMedia.extension.data then
local lucky, data
lucky, data = pcall( mw.ext.data.get,
FileMedia.extension.storage )
if type( data ) == "table" then
FileMedia.extension.data = data.data
else
FileMedia.extension.data = true
end
end
if type( FileMedia.extension.data ) == "table" then
local e
s = s:lower()
for i = 1, #FileMedia.extension.data do
e = FileMedia.extension.data[ i ]
if type( e ) == "table" and
e[ 1 ] == s then
r = e[ 2 ]
break -- for i
end
end -- for i
end
end
end
return r
end -- FileMedia.getType()
FileMedia.getWidth = function ( ask )
-- Retrieve image width
-- Precondition:
-- ask -- file name or title; string, or nil
-- Postcondition:
-- Returns number, or false or nil
local r = false
local s = FileMedia.getTitle( ask )
if s then
local d = mw.title.makeTitle( "File", s )
if d and d.file then
r = d.file.width
end
end
return r
end -- FileMedia.getWidth()
FileMedia.isFile = function ( ask )
-- Is this a valid (existing) file title or file name?
-- Precondition:
-- ask -- file title or file name; string, or nil
-- Postcondition:
-- Returns boolean
-- Expensive function.
local r
local s = FileMedia.getTitle( ask )
if s then
r = mw.title.makeTitle( "File", s ).fileExists
else
r = false
end
return r
end -- FileMedia.isFile()
FileMedia.isSpacing = function ( ask )
-- Is presumed space name not conflicting with files?
-- Precondition:
-- ask -- possible space name; string, or nil
-- Postcondition:
-- Returns boolean; false: conflict
local r = true
if ask then
local space = mw.site.namespaces[ mw.text.trim( ask ) ]
if space then
space = space.canonicalName
r = ( space == "Media" or space == "File" )
end
end
return r
end -- FileMedia.isSpacing()
FileMedia.isType = function ( ask, against )
-- Does file name match type expectation?
-- Precondition:
-- ask -- file name; string, or nil
-- against -- expectation; generic or "file" or "image" or any
-- Postcondition:
-- Returns boolean
local r = false
local s = FileMedia.getType( ask )
if s then
local scope
if against == "file" then
scope = "audio paged pixel vector video"
elseif against == "image" then
scope = "paged pixel vector"
end
if scope then
local suffix = ask:match( ".%.(%w+)%s*$" )
if suffix and suffix:lower() ~= "doc" then
r = scope:match( s )
end
else
r = ( s == against )
end
if r then
s = ask:match( "^%s*([^:]+)%s*:" )
r = FileMedia.isSpacing( s )
end
end
return r
end -- FileMedia.isType()
FileMedia.setParSize = function ( assign, atleast, ahead )
-- Check or adapt transclusion parameter for size
-- Precondition:
-- assign -- size parameter; string, or nil
-- atleast -- fallback value; string, or nil
-- ahead -- start with pipe, if not empty; boolean, or nil
-- Postcondition:
-- Returns px string, if valid or corrected, else false
local r = false
if type( assign ) == "string" then
local s = mw.text.trim( assign )
if s ~= "" then
if s:match( "^[1-9]%d?%d?%d?$" ) then
r = s .. "px"
else
s = s:lower()
if s:match( "%d$" ) then
s = s .. "px"
elseif not s:match( "%dpx$" ) then
s = false
end
if s then
if s:match( "^[1-9]%d?%d?%d?px$" ) or
s:match( "^[1-9]%d?%d?%d?x[1-9]%d?%d?%d?px$" ) or
s:match( "^x[1-9]%d?%d?%d?px$" ) then
r = s
end
end
end
end
end
if not r and atleast then
r = atleast
end
if r and ahead then
r = "|" .. r
end
return r
end -- FileMedia.setParSize()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2020-08-17
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )
if type( entity ) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues( seek )
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
elseif linked then
if mw.title.getCurrentTitle().prefixedText
== mw.wikibase.getSitelink( suited ) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
end
end
if type( r ) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
-- Export
local p = { }
p.getExtension = function ( frame )
-- Retrieve "file name extension" from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getExtension,
frame.args[ 1 ] )
return r or ""
end -- p.getExtension
p.getHeight = function ( frame )
-- Retrieve image height from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getHeight,
frame.args[ 1 ] )
return r or ""
end -- p.getHeight
p.getHeightWidth = function ( frame )
-- Retrieve image height x width from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getHeightWidth,
frame.args[ 1 ] )
return r or ""
end -- p.getHeightWidth
p.getMimeType = function ( frame )
-- Retrieve MIME type from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getMimeType,
frame.args[ 1 ] )
return r or ""
end -- p.getMimeType
p.getPageCount = function ( frame )
-- Retrieve number of file pages (paged media fragments) from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getPageCount,
frame.args[ 1 ] )
return r or ""
end -- p.getPageCount
p.getSize = function ( frame )
-- Retrieve file size from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getSize,
frame.args[ 1 ] )
return r or ""
end -- p.getSize
p.getTitle = function ( frame )
-- Retrieve file title from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getTitle,
frame.args[ 1 ] )
return r or ""
end -- p.getTitle
p.getType = function ( frame )
-- Retrieve supposed file type from "file name extension"
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getType,
frame.args[ 1 ] )
return r or ""
end -- p.getType
p.getWidth = function ( frame )
-- Retrieve file width from page title or name
-- 1 -- file title or name
local lucky, r = pcall( FileMedia.getWidth,
frame.args[ 1 ] )
return r or ""
end -- p.getWidth
p.isFile = function ( frame )
-- Is this a valid (existing) file title or file name?
-- 1 -- file name; with or without namespace
-- Expensive function.
local lucky, r = pcall( FileMedia.isFile,
frame.args[ 1 ] )
return r and "1" or ""
end -- p.isFile
p.isType = function ( frame )
-- Does file name match type expectation?
-- 1 -- file name
-- 2 -- expected
local r = false
local supposed = frame.args[ 2 ]
if supposed then
supposed = supposed:match( "^%s*(%w+)%s*$" )
if supposed then
local lucky
lucky, r = pcall( FileMedia.isType,
frame.args[ 1 ],
supposed:lower() )
end
end
return r and "1" or ""
end -- p.isType
p.setParSize = function ( frame )
-- Check or adapt transclusion parameter [ 1 ] for size
-- Returns px string, if valid or corrected, else empty
-- Fallback to parameter [ 2 ]
local lead = frame.args.pipe
local r
if lead and
( lead == "" or lead == "0" ) then
lead = false
end
r = FileMedia.setParSize( frame.args[ 1 ],
frame.args[ 2 ],
lead )
return r or ""
end -- p.setParSize
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe()
p.FileMedia = function ()
return FileMedia
end -- p.FileMedia
setmetatable( p, { __call = function ( func, ... )
setmetatable( p, nil )
return Failsafe
end } )
return p