Difference between revisions of "Module:Card gallery"
m (Adapt for debug. Fix for empty input.) |
(I can't resist myself at using objects (or something like it).) |
||
Line 14: | Line 14: | ||
-- TLM-EN012; The Lost Millennium; UtR; UE | -- TLM-EN012; The Lost Millennium; UtR; UE | ||
-- SDJ-035; Starter Deck: Joey; C; UE; Reprint // description::Spell | -- SDJ-035; Starter Deck: Joey; C; UE; Reprint // description::Spell | ||
+ | -- S1; Yu-Gi-Oh! True Duel Monsters: Sealed Memories promotional cards; UR | ||
-- » | -- » | ||
Line 67: | Line 68: | ||
end | end | ||
return counter; | return counter; | ||
+ | end | ||
+ | |||
+ | -- @name _link | ||
+ | -- @description TODO | ||
+ | local function _link( ... ) | ||
+ | -- TODO | ||
+ | return; | ||
end | end | ||
Line 86: | Line 94: | ||
return default or ''; | return default or ''; | ||
end | 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]] | ||
-------------------- | -------------------- | ||
Line 152: | Line 240: | ||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | local function _buildStandard( arg, modifier ) | ||
local standard = {}; | local standard = {}; | ||
− | |||
− | |||
− | + | if not _trim( arg ) then | |
− | for value in gsplit( | + | return standard; |
− | + | end | |
− | + | ||
− | table.insert( standard, | + | for value in gsplit( arg, '%s*;%s*' ) do |
+ | if value then | ||
+ | table.insert( standard, _trim( value ) or '' ); | ||
end | end | ||
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 | for option in gsplit( tempOpt, '%s*;%s*' ) do | ||
local opt = _trim( option ); | local opt = _trim( option ); | ||
Line 186: | Line 276: | ||
end | 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; | return standard, modifier, options; | ||
Line 195: | Line 305: | ||
local function process( entry ) | local function process( entry ) | ||
local standard, modifier, options = splitEntry( entry ); | local standard, modifier, options = splitEntry( entry ); | ||
− | return table.concat( { | + | local fileObject = File.new( standard, modifier, options ); -- TODO |
+ | return table.concat( { -- TODO: TEST | ||
table.concat( standard ), | table.concat( standard ), | ||
− | 'modifier: ' .. modifier, | + | 'modifier: ' .. modifier or 'nil', |
type( options ) .. _count( options ) | type( options ) .. _count( options ) | ||
− | }, '\n' ); | + | }, '\n' ); |
end | end | ||
Revision as of 23:30, 2 May 2018
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;