Module:Card gallery
Implements {{Card gallery}}.
See also Module:Card gallery/File.
-- <pre>
-- NOTES:
-- input in the form of:
-- «
-- <card number>; <set>; <rarity>; <edition>; <alt>
-- »
-- Where "rarity" and "edition" can either be in full form or abbreviated.
-- Example:
-- «
-- {{Card gallery|region=EN|
-- TLM-EN012; The Lost Millennium; SR; 1E // extension::jpg
-- TLM-EN012; The Lost Millennium; UtR; 1E // extension::jpg
-- TLM-EN012; The Lost Millennium; SR; UE
-- TLM-EN012; The Lost Millennium; UtR; UE
-- SDJ-035; Starter Deck: Joey; C; UE; Reprint // description::Spell
-- S1; Yu-Gi-Oh! True Duel Monsters: Sealed Memories promotional cards; UR
-- »
-- Ideas:
-- * propagate:
-- «
-- TLM-EN012; The Lost Millennium; SR; 1E
-- *; *; UtR; *
-- *; *; SR; UE
-- *; *; UtR; *
-- »
-- Avoids repitition. Harder with a file replace script.
-- TODO:
-- support for OP / GC / CT / etc. (<card number>; <set>; <rarity>; <edition>; <alt> :: GC|CT)
--------------------
-- Global vairables:
--------------------
local CardGallery = {};
local _D = {}; -- Global data object.
----------------
-- Load modules:
----------------
local getArgs = require( 'Module:Arguments' ).getArgs;
local DATA = require( 'Module:Data' );
local getName = require( 'Module:Name' ).main;
---------------------
-- Utility functions:
---------------------
-- mw functions:
local split = mw.text.split;
local gsplit = mw.text.gsplit;
local HTML = mw.html.create;
-- @name _trim
-- Trims white space from front and tail of string.
-- If the input is only white space, returns nil.
local function _trim( s )
if s and not s:match( '^%s*$' ) then
return mw.text.trim( s );
end
end
-- @name _count
-- @description Counts how many entries a table has.
local function _count( t )
local counter = 0;
for key, value in pairs( t ) do
counter = counter + 1;
end
return counter;
end
-- @name _link
-- @description TODO
local function _link( ... )
-- TODO
return;
end
-- @name _error
-- Generates an error and places it on the error table.
local function _error( message, default, category )
_D.errors.exists = true;
local err = HTML( 'div' ):css( 'padding-left', '1.6em' )
:tag( 'strong' ):addClass( 'error' )
:wikitext( ('Error: %s'):format( message ) )
:done()
:allDone();
local cat = category and ('[[Category:%s]]'):format( category ) or '';
table.insert(
_D.errors, table.concat( {
tostring( err ), cat
} )
);
return default or '';
end
--------------
-- File class:
--------------
-- @name File
-- @classAttr counter -> [static] Counts the number of File instances.
local File = {};
File.__index = File;
File.counter = 0;
-- @name new -> File constructor.
-- @attr exists -> Control attribute; denotes if a file is to be printed.
-- @attr number -> The card number (linked).
-- @attr region -> The region.
-- @attr setEn -> The English name for the set.
-- @attr setLn -> The localized name for the set.
-- @attr setAbbr -> The set abbreviation.
-- @attr rarity -> The rarity name.
-- @attr r -> The rarity abbreviation.
-- @attr edition -> The full edition.
-- @attr ed -> The edition abbreviation.
-- @attr modifier -> The card modifier.
-- @attr modifierAbbr -> The card modifier abbreviation (OP|GC|CT).
-- @attr alt -> The alt value.
-- @attr extension -> The file extension.
function File.new( std, mod, opt )
-- @attr _standard -> Contains the trimmed input args for the standard input {enum-like}.
-- @attr _modifier -> Contains the trimmed input arg for the modifier (OP|GC|CT).
-- @attr _options -> Contains the trimmed input args for the options {map-like}.
File.counter = File.counter + 1;
local fileData = {};
fileData.exists = true;
fileData._standard = std or {};
fileData._modifier = mod or '';
fileData._options = opt or {};
return setmetatable( fileData, File );
end
-- @name setNumber
-- @description Sets the «number» and «setAbbr» attributes.
function File:setNumber()
local cardNumber = self._standard[ 1 ];
if cardNumber == '' then
self.exists = false;
_error( ('No set abbreviation given for file input number «%d»!'):format( File.counter ) );
return '';
end
if cardNumber and cardNumber:match( '^%w%w%w%w?%-%w%w%w%w?%w?$' ) then
-- Input like «TLM-EN012».
self.number = _link( cardNumber );
self.setAbbr = cardNumber:match( '^(%w%w%w%w?)%-%w%w%w%w?%w?$' );
else
-- Input like «S1».
self.number = nil;
self.setAbbr = cardNumber;
end
return self;
end
--[[function File:setSet()
self.
end
function File:setRarity()
self.
end
function File:setEdition()
self.
end
function File:setModifier()
self.
end
function File:setAlt()
self.
end
function File:setExtension()
self.
end]]
--------------------
-- Module functions:
--------------------
-- @name getInfo
-- @description Handles generic info.
local function getInfo()
-- Region and language:
_D.rg = DATA.getRg( _D.args[ 'region' ] ) or _error(
('Invalid «region»: «%s»!'):format( _D.args[ 'region' ] or '(no region given)' ), DATA.getRg( 'en' )
);
_D.region = DATA.getRegion( _D.rg );
_D.ln = DATA.getLn( _D.rg );
_D.language = DATA.getLanguage( _D.rg );
-- Flags:
_D.flags = {};
_D.flags.notEnglish = _D.ln ~= 'en'; -- TODO may not be needed!
_D.flags.italics = not ((_D.ln == 'ja') or (_D.ln == 'zh') or (_D.ln == 'ko')) --[[and 'normal' or 'italic']];
-- Medium:
_D.cg = _D.flags.italics and 'TCG' or 'OCG'; -- TODO Probably not gonna use that.
-- Card and page:
_D.PAGENAME = mw.title.getCurrentTitle().text;
_D.NAMESPACE = mw.title.getCurrentTitle().nsText;
_D.name = getName( _D.PAGENAME, _D.language );
end
-- @name wrapInQuotes
-- @description Wraps «name» in proper quotation marks.
local function wrapInQuotes( name, std )
if not _trim( name ) then
return ''; -- Return empty string.
end
return (std or (_D.ln ~= 'ja' and _D.ln ~= 'zh'))
and table.concat( { '"', name, '"' } )
or table.concat( { '「', name, '」' } )
;
end
-- @name printErrors
-- @dascription Stringifies the errors table.
local function printErrors()
local category = '[[Category:((Card gallery)) transclusion to be checked]]';
if not _D.errors.exists then
return '';
end
table.insert( _D.errors, category );
return table.concat( _D.errors, '\n' );
end
-- @name buildHeader
-- @description builds the gallery header.
local function buildHeader()
return HTML( 'div' ):addClass( 'gallery-header' ):attr( 'id', ('%s_section'):format( _D.rg ) )
:tag( 'div' )
:wikitext( wrapInQuotes( _D.name ) )
:done()
:tag( 'div' )
:wikitext( _D.region )
:done()
:allDone();
end
local function _buildStandard( arg, modifier )
local standard = {};
if not _trim( arg ) then
return standard;
end
for value in gsplit( arg, '%s*;%s*' ) do
if value then
table.insert( standard, _trim( value ) or '' );
end
end
return standard;
end
local function _buildOptions( arg )
local options = {};
if not _trim( arg ) then
return options;
end
-- TODO
for option in gsplit( tempOpt, '%s*;%s*' ) do
local opt = _trim( option );
if opt then
local optTemp = split( opt, '%s*::%s*' );
local optName = _trim( optTemp[ 1 ] );
local optValue = _trim( optTemp[ 2 ] );
if optName and optValue then
options[ optName ] = optValue;
end
end
end
return options;
end
-- @name splitEntry
-- @description Splits an input entry into the standard valus, the modifier and the options.
local function splitEntry( entry )
if not _trim( entry ) then
return {}, '', {};
end
local temp1 = split( entry, '%s*//%s*' );
local tempOpt = temp1[ 2 ] or '';
local temp2 = split( temp1[ 1 ], '%s*::%s*' );
local tempMod = temp2[ 2 ];
local tempStd = temp2[ 1 ];
local modifier = _trim( tempMod );
local standard = _buildStandard( tempStd, modifier );
local options = _buildOptions( tempOpt );
return standard, modifier, options;
end
-- @name process
-- @description Processes a gallery input entry and converts it into raw wikitext markup.
-- TODO
local function process( entry )
local standard, modifier, options = splitEntry( entry );
local fileObject = File.new( standard, modifier, options ); -- TODO
return table.concat( { -- TODO: TEST
table.concat( standard ),
'modifier: ' .. modifier or 'nil',
type( options ) .. _count( options )
}, '\n' );
end
-- @name buildInnerGallery
-- TODO
local function buildInnerGallery()
if (_D.args[ 1 ] or '') == '' then
-- TODO: Error?
return ''
end
-- <card number>; <set>; <rarity>; <edition>; <alt> :: <modifier> // <option1>::<value1>; <optionN>::<valueN>
local galleryEntries = {};
for inputEntry in gsplit( _D.args[ 1 ], '\n' ) do
local entry = _trim( inputEntry ) and process( inputEntry );
if entry then
table.insert( galleryEntries, entry );
end
end
return table.concat( galleryEntries, '\n' );
end
-- @name buildGallery
-- TODO
local function buildGallery()
local inner = buildInnerGallery();
return table.concat( {
'<gallery heights="175px" position="center" captionalign="center">',
inner,
'</gallery>'
}, '\n' );
end
-- @name main
-- @notes exportable
-- @description To be called through #invoke.
function CardGallery.main( frame )
_D.errors = {};
_D.args = getArgs( frame, {
trim = true,
removeBlanks = true,
parentOnly = true
} );
getInfo();
local errors = printErrors();
local header = buildHeader();
local gallery = buildGallery();
return HTML( 'div' ):addClass( 'card-galleries' )
:node( tostring( header ) )
:newline()
:node( errors )
:newline()
:node( frame:preprocess( gallery ) )
:allDone();
end
return CardGallery;