Difference between revisions of "Module:Card gallery"
(Trying to deal with JP images with DT edition.) |
m (Fix dumb mistakes.) |
||
Line 239: | Line 239: | ||
if not self.flags.isOP and rarity == '' then | if not self.flags.isOP and rarity == '' then | ||
− | return self: | + | return self:error( 'rarity' ); |
end | end | ||
Line 257: | Line 257: | ||
if not self.flags.noEdition and not self.edition then | if not self.flags.noEdition and not self.edition then | ||
− | return self: | + | return self:error( 'edition' ); |
end | end | ||
Line 267: | Line 267: | ||
function File:initAlt() | function File:initAlt() | ||
local index = 5; | local index = 5; | ||
− | if self.flags.isOP | + | if self.flags.isOP then index = index - 1 end |
− | if not self | + | if not self.ed then index = index - 1 end |
self.alt = self._standard[ index ]; | self.alt = self._standard[ index ]; |
Revision as of 22:03, 6 May 2018
Implements {{Card gallery}}.
See also Module:Card gallery/File.
-- <pre>
-- NOTES:
-- input in the form of:
-- «
-- <card number>; <set>; <rarity>; <edition>; <alt> :: <modifier> // <option1>::<value1>; <optionN>::<valueN>
-- »
-- 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: Check edition and alt (mind cases where JP images have an edition).
--------------------
-- Global vairables:
--------------------
local CardGallery = {}; -- Export variable.
local _D = {}; -- Global data object.
----------------
-- Load modules:
----------------
local getArgs = require( 'Module:Arguments' ).getArgs;
local getName = require( 'Module:Name' ).main;
local getImgName = require( 'Module:Card image name' ).main;
local DATA = require( 'Module:Data' );
local UTIL = require( 'Module:Util' );
---------------------
-- Utility functions:
---------------------
-- mw functions:
local split = mw.text.split;
local gsplit = mw.text.gsplit;
local HTML = mw.html.create;
-- @name _error
-- @description 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 flags -> Control flags:
-- -- exists => denotes if a file is to be printed.
-- -- noEdition => if it is a Japanese or Chinese print; thus, no edition (except DT ones).
-- -- isOP => if it is an Official Proxy.
-- @attr number -> The card number.
-- @attr rg -> The region index.
-- @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 mod -> The card modifier abbreviation (OP|GC|CT|RP).
-- @attr alt -> The alt value.
-- @attr extension -> The file extension.
-- @attr description -> A short file description.
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|RP).
-- @attr _options -> Contains the trimmed input args for the options {map-like}.
File.counter = File.counter + 1;
local fileData = {};
fileData.flags = {
exists = true,
noEdition = false,
isOP = false
};
fileData._standard = std or {};
fileData._modifier = mod or '';
fileData._options = opt or {};
return setmetatable( fileData, File );
end
-- @name __tostring
-- @description [metamethod] Renders the File.
function File:__tostring()
if not self.flags.exists then
return '';
end
-- Build file:
local file = {
getImgName(), self.setAbbr, self.rg
};
if self.r then table.insert( file, self.r ) end
if self.ed then table.insert( file, self.ed ) end
if self.mod then table.insert( file, self.mod ) end
if self.alt then table.insert( file, self.alt ) end
-- Build caption: (this might get better implementation in the future)
local caption = {};
local temp1st = {};
if self.number then table.insert( temp1st, UTIL.link( self.number ) ) end
if self.rarity then
table.insert(
temp1st,
('(%s)'):format( UTIL.link( self.rarity, self.r ) )
);
end
if UTIL.count( temp1st ) ~= 0 then
table.insert( caption, table.concat( temp1st, ' ' ) );
end
if self.edition then table.insert( caption, UTIL.link( self.edition ) ) end
if self.modifier then table.insert( caption, UTIL.link( self.modifier ) ) end
table.insert(
caption,
UTIL.italics(
UTIL.link(
self.setEn,
self.setEn:match( '%(2011%)' ) and self.setEn -- or self.setEn:match( '%(series%)' )
)
)
);
if self.description then table.insert( caption, self.description ) end
-- Stringify:
local fileString = ('%s.%s'):format( table.concat( file, '-' ), self.extension );
local captionString = table.concat( caption, '<br />' );
-- Return concatenation:
return ('%s | %s'):format( fileString, captionString );
end
-- @name error
-- @description Generate consistent error messages.
function File:error( parameter )
self.flags.exists = false;
_error( ('No %s given for file input number %d!'):format( parameter, File.counter ) );
return self;
end
-- @name initRegion
-- @description Sets the «rg» attribute.
function File:initRg()
self.rg = _D.rg:upper();
self.flags.noEdition = self.rg == 'JP' or self.rg == 'JA' or self.rg == 'TC';
return self;
end
-- @name initNumber
-- @description Sets the «number» and «setAbbr» attributes.
function File:initNumber()
local cardNumber = self._standard[ 1 ];
if cardNumber == '' then
return self:error( 'set abbreviation' );
end
if cardNumber and cardNumber:match( '^%w-%-%w-$' ) then
-- Input like «TLM-EN012».
self.number = cardNumber:upper();
self.setAbbr = self.number:match( '^(%w-)%-%w-$' );
else
-- Input like «S1».
self.number = nil;
self.setAbbr = cardNumber:upper();
end
return self;
end
-- @name initSet
-- @description Sets the «setEn» and «setLn» attributes.
function File:initSet()
local set = self._standard[ 2 ];
if set == '' then
return self:error( 'set name' );
end
self.setEn = getName( set ) or set;
self.setLn = getName( set, _D.language );
return self;
end
-- @name initModifier
-- @description Sets the «modifier» and «mod» attributes.
function File:initModifier()
self.modifier = DATA.getModifier( self._modifier );
self.mod = self.modifier and DATA.getMod( self.modifier ):upper();
self.flags.isOP = self.mod == 'OP';
return self;
end
-- @name initRarity
-- @description Sets the «rarity» and «r» attributes.
function File:initRarity()
local rarity = not self.flags.isOP and self._standard[ 3 ];
if not self.flags.isOP and rarity == '' then
return self:error( 'rarity' );
end
self.rarity = DATA.getRarity( rarity );
self.r = self.rarity and DATA.getR( self.rarity ):upper();
return self;
end
-- @name initEdtion
-- @description Sets the «edition» and «ed» attributes.
function File:initEdition()
local edition = self._standard[ self.flags.isOP and 3 or 4 ];
self.edition = DATA.getEdition( edition );
self.ed = self.edition and DATA.getEd( self.edition ):upper();
if not self.flags.noEdition and not self.edition then
return self:error( 'edition' );
end
return self;
end
-- @name initAlt
-- @description Set the «alt» attribute.
function File:initAlt()
local index = 5;
if self.flags.isOP then index = index - 1 end
if not self.ed then index = index - 1 end
self.alt = self._standard[ index ];
return self;
end
-- @name initOptions
-- @description Sets the file extension.
function File:initOptions()
-- Extension:
local extension = self._options[ 'extension' ];
self.extension = UTIL.isString( extension ) and extension:lower() or 'png';
-- Description:
self.description = self._options[ 'description' ];
return self;
end
-- @name init
-- @description Initializes the attributes of the File instance.
function File:init()
return self
:initRg()
:initNumber()
:initSet()
:initModifier()
:initRarity()
:initEdition()
:initAlt()
:initOptions()
;
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:
local mwTitle = mw.title.getCurrentTitle();
_D.PAGENAME = mwTitle.text;
_D.NAMESPACE = mwTitle.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 UTIL.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()
:allDone();
end
local function _buildStandard( arg )
local standard = {};
if not UTIL.trim( arg ) then
return standard;
end
for value in gsplit( arg, '%s*;%s*' ) do
if value then
table.insert( standard, UTIL.trim( value ) or '' );
end
end
return standard;
end
local function _buildOptions( arg )
local options = {};
if not UTIL.trim( arg ) then
return options;
end
for option in gsplit( arg, '%s*;%s*' ) do
local opt = UTIL.trim( option );
if opt then
local optTemp = split( opt, '%s*::%s*' );
local optName = UTIL.trim( optTemp[ 1 ] );
local optValue = UTIL.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 values, the modifier and the options.
local function splitEntry( entry )
if not UTIL.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 standard = _buildStandard( tempStd );
local modifier = UTIL.trim( tempMod );
local options = _buildOptions( tempOpt );
return standard, modifier, options;
end
-- @name process
-- @description Processes a gallery input entry and converts it into a File object («nil» if there's no valid info).
local function process( entry )
local standard, modifier, options = splitEntry( entry );
if UTIL.count( standard ) == 0 and UTIL.count( options ) == 0 then
-- Not enough info to even try to build.
return nil;
end
local fileObject = File.new( standard, modifier, options ):init();
return fileObject.flags.exists and fileObject;
end
-- @name buildInnerGallery
-- @description Build the inner part of the gallery (between the <gallery> tags).
local function buildInnerGallery()
if not _D.args[ 1 ] then
return _error( 'Empty or no input provided for the gallery!', '' );
end
local galleryEntries = {};
for inputEntry in gsplit( _D.args[ 1 ], '\n' ) do
local entry = UTIL.trim( inputEntry ) and process( inputEntry );
if entry then
table.insert( galleryEntries, tostring( entry ) );
end
end
return table.concat( galleryEntries, '\n' );
end
-- @name buildGallery
-- @description Builds the full gallery part.
local function buildGallery()
local inner = buildInnerGallery();
return table.concat( {
'<gallery heights="175px" position="center" captionalign="center">',
inner,
'</gallery>'
}, '\n' );
end
local function buildAll( frame, errors, header, gallery )
local contatiner = HTML( 'div' ):addClass( 'card-galleries' )
:node( tostring( header ) )
:newline()
:node( errors )
:newline()
:node( frame:preprocess( gallery ) )
:allDone();
return table.concat( {
('== %s =='):format( _D.region ),
tostring( contatiner )
}, '\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 buildAll( frame, errors, header, gallery );
end
----------
-- Return:
----------
return CardGallery;
-- </pre>