mirror of
https://github.com/msikma/pokesprite.git
synced 2026-09-07 09:55:12 -05:00
Delete old PHP version
This commit is contained in:
@@ -1,161 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
// These are the default settings. They should not be modified.
|
||||
// If you want to use different settings, type: ./pokesprite.php --help
|
||||
|
||||
$s = array();
|
||||
|
||||
// Include Pokémon sprites
|
||||
$s['include_pkmn'] = true;
|
||||
// Include regular (non-shiny) sprites
|
||||
$s['include_pkmn_nonshiny'] = true;
|
||||
// Include (unofficial) shiny sprites
|
||||
$s['include_pkmn_shiny'] = true;
|
||||
// Include forms and gender differences
|
||||
$s['include_pkmn_forms'] = true;
|
||||
// Include right-facing sprites (0 = None, 1 = Only unique icons, 2 = All)
|
||||
$s['include_pkmn_right'] = 1;
|
||||
// Include the icon sets
|
||||
$s['include_icon_sets'] = true;
|
||||
// Include the special icons (egg, unknown Pokémon)
|
||||
$s['include_special_icons'] = true;
|
||||
|
||||
// Language used for Pokémon names
|
||||
$s['pkmn_language'] = 'eng';
|
||||
// Language used for Pokémon slugs
|
||||
$s['pkmn_language_slugs'] = 'eng';
|
||||
// Language used by the program
|
||||
$s['i18n_language'] = 'en_us';
|
||||
// Slug language of the icon files (should not be changed)
|
||||
$s['img_slug_lang'] = 'eng';
|
||||
|
||||
// Copyright strings
|
||||
$s['copy_a'] = '2014';
|
||||
$s['copy_z'] = date('Y');
|
||||
$s['title_str'] = 'PokéSprite';
|
||||
$s['revision'] = '[unknown]';
|
||||
$s['website'] = 'https://github.com/msikma/pokesprite';
|
||||
$s['website_txt'] = '<'.$s['website'].'>';
|
||||
$s['main_contributor'] = 'Michiel Sikma <michiel@sikma.org>';
|
||||
$s['other_contributors'] = 'PokéSprite contributors';
|
||||
$s['contributors'] = implode(' and ', array($s['main_contributor'], $s['other_contributors']));
|
||||
$s['copyright_str'] = '(C) '.($s['copy_a'] != $s['copy_z'] ? $s['copy_a'].'-'.$s['copy_z'] : $s['copy_a']).', '.$s['contributors'];
|
||||
$s['copyright_gf'] = '(C) 1995-'.$s['copy_z'].' Nintendo/Creatures Inc./GAME FREAK Inc.';
|
||||
$s['copyright_contrib_notice'] = 'For a full list of contributors, view the project commit history.';
|
||||
$s['script_date'] = date('Y-m-d H:i:s');
|
||||
|
||||
// Base URL for direct links to icon files.
|
||||
$s['icon_url_info_base'] = 'https://github.com/msikma/pokesprite/tree/master/';
|
||||
$s['icon_url_img_base'] = 'https://raw.githubusercontent.com/msikma/pokesprite/master/';
|
||||
|
||||
// Icons base directory
|
||||
$s['dir_base'] = './icons/';
|
||||
// Pokémon sprites base directory
|
||||
$s['dir_pkmn'] = 'pokemon/';
|
||||
// Regular sprites directory
|
||||
$s['dir_pkmn_regular'] = 'regular/';
|
||||
// Shiny sprites directory
|
||||
$s['dir_pkmn_shiny'] = 'shiny/';
|
||||
// Special sprites directory
|
||||
$s['dir_pkmn_special'] = '';
|
||||
// Female sprites directory
|
||||
$s['dir_pkmn_female'] = 'female/';
|
||||
// Right-facing sprites directory
|
||||
$s['dir_pkmn_right'] = 'right/';
|
||||
// Permitted extensions for images
|
||||
$s['file_exts'] = array('png');
|
||||
// Data directory
|
||||
$s['dir_data'] = './data/';
|
||||
// File containing Pokémon data
|
||||
$s['file_pkmn_data'] = 'pkmn.json';
|
||||
// File containing data for other icons
|
||||
$s['file_icon_data'] = 'item-icons.json';
|
||||
// Output directory (created if nonexistent)
|
||||
$s['dir_output'] = './output/';
|
||||
// Mode at which the directory is created
|
||||
$s['dir_mode'] = 0777;
|
||||
// If set, which Pokémon to include (debugging only)
|
||||
$s['pkmn_range'] = null;
|
||||
// If set, which icons to include (debugging only)
|
||||
$s['icon_range'] = null;
|
||||
// Whether to index numbers instead of slugs in the overview (debugging only)
|
||||
$s['html_no_slugs'] = false;
|
||||
// Github project base directory
|
||||
$s['github_base_dir'] = 'https://raw.github.com/msikma/pokesprite/master/';
|
||||
|
||||
// List of icon sets that are to be included aside from the Pokémon icons.
|
||||
// This searches for the directory in the icons base directory.
|
||||
// If all images have the same size, their width and height is set only
|
||||
// once in the SCSS code for efficiency.
|
||||
$s['etc_icon_sets'] = array(
|
||||
'apricorn', 'ball', 'battle-item', 'berry', 'body-style', 'etc', 'ev-item',
|
||||
'evo-item', 'flute', 'fossil', 'gem', 'hm', 'hold-item', 'incense',
|
||||
'other-item', 'key-item', 'mail', 'medicine', 'mega-stone', 'mulch',
|
||||
'plate', 'scarf', 'shard', 'tm', 'valuable-item',
|
||||
'wonder-launcher', 'z-crystals', 'memory', 'roto', 'petal'
|
||||
);
|
||||
|
||||
// Pokémon icon width
|
||||
$s['pkmn_img_width'] = 40;
|
||||
// Pokémon icon height
|
||||
$s['pkmn_img_height'] = 30;
|
||||
// Pokémon icon padding
|
||||
$s['pkmn_img_padding'] = 1;
|
||||
// Amount of icons in one row of the sprite
|
||||
$s['pkmn_row_count'] = 32;
|
||||
|
||||
// Print feedback on image inclusion
|
||||
$s['debug_img_inclusion'] = false;
|
||||
// Display colors in feedback
|
||||
$s['debug_monochrome'] = false;
|
||||
|
||||
// Whether to pngcrush the resulting image
|
||||
$s['generate_optimized'] = true;
|
||||
// Temporary image file name
|
||||
$s['img_output_tmp'] = 'pokesprite_tmp.png';
|
||||
// Output name of the image
|
||||
$s['img_output'] = 'pokesprite.png';
|
||||
// Output name of the SCSS file
|
||||
$s['scss_output'] = 'pokesprite.scss';
|
||||
// Output name of the JS file
|
||||
$s['js_output'] = 'pokesprite.js';
|
||||
// Output name of the HTML overview
|
||||
$s['html_output'] = 'overview.html';
|
||||
// Output name of the HTML file with build information
|
||||
$s['html_build_output'] = 'files.html';
|
||||
// Output name of the Markdown overview
|
||||
$s['md_output'] = 'overview.md';
|
||||
// Resources directory name
|
||||
$s['resources_dir'] = './resources/';
|
||||
// SCSS template file
|
||||
$s['scss_tpl'] = 'pokesprite-tpl.scss';
|
||||
// JS template file
|
||||
$s['js_tpl'] = 'pokesprite-tpl.js';
|
||||
// HTML template file
|
||||
$s['html_tpl'] = 'overview-tpl.html';
|
||||
// HTML template file for the build information
|
||||
$s['html_build_tpl'] = 'files-tpl.html';
|
||||
// Relative link back to the overview for the docs
|
||||
$s['html_rel_home'] = '/pokesprite/';
|
||||
// Usage template file
|
||||
$s['usage_tpl'] = 'usage.tpl';
|
||||
// Version template file
|
||||
$s['version_tpl'] = 'version.tpl';
|
||||
// Whether to generate a Markdown overview
|
||||
$s['generate_markdown'] = false;
|
||||
|
||||
|
||||
// Base CSS selector (identifies an element as ours)
|
||||
$s['css_base_selector'] = 'pkspr';
|
||||
// Base SCSS/JS variable name
|
||||
$s['var_base_name'] = 'pkspr';
|
||||
|
||||
// External tools
|
||||
$s['pngcrush_path'] = './tools/pngcrush';
|
||||
$s['sass_path'] = 'sass';
|
||||
$s['closure_path'] = 'wipwipwip';
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Formats a number of bytes for human readability.
|
||||
*
|
||||
* @param int $bytes Amount of bytes to format.
|
||||
* @param int $precision Precision of the output.
|
||||
*/
|
||||
function format_bytes($bytes, $precision=2)
|
||||
{
|
||||
// Taken from Stack Overflow <http://stackoverflow.com/a/2510459/2582271>.
|
||||
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
||||
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
|
||||
$bytes /= (1 << (10 * $pow));
|
||||
|
||||
return round($bytes, $precision).' '.$units[$pow];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a lowercase slug (URL-ready name) from a string.
|
||||
*
|
||||
* Designed to work only for Latin-based character sets.
|
||||
*
|
||||
* @param string $text Text to slugify.
|
||||
*/
|
||||
function slugify($text)
|
||||
{
|
||||
// Taken from Stack Overflow <http://stackoverflow.com/a/2955878/2582271>.
|
||||
$text = preg_replace('~[^\\pL\d]+~u', '-', $text);
|
||||
$text = trim($text, '-');
|
||||
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
|
||||
$text = strtolower($text);
|
||||
$text = preg_replace('~[^-\w]+~', '', $text);
|
||||
return $text;
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Growing Bin Packer algorithm for positioning icons in a spritesheet
|
||||
* using space as efficiently as possible.
|
||||
*
|
||||
* This code is a rewritten version of Jake Gordon's GrowingPacker algorithm.
|
||||
* See <http://codeincomplete.com/posts/2011/5/7/bin_packing/> for more info.
|
||||
* The algorithm has been adapted from Javascript to PHP and modified lightly.
|
||||
*/
|
||||
class GrowingPacker
|
||||
{
|
||||
public $root;
|
||||
|
||||
private $permit_growth_w;
|
||||
private $permit_growth_h;
|
||||
private $img_padding;
|
||||
|
||||
/**
|
||||
* Fits size sorted blocks using a binary tree packing algorithm.
|
||||
*
|
||||
* Note that $blocks needs to be converted to a StdObject temporarily
|
||||
* as arrays cannot be properly passed by reference. This algorithm
|
||||
* cannot work in PHP using arrays.
|
||||
*
|
||||
* For the best effects, $blocks needs to be sorted by max(width, height),
|
||||
* descending (with the largest elements appearing first).
|
||||
* The algorithm fails if a block is larger than the previous one.
|
||||
*
|
||||
* If no extra arguments are passed, the initial size is determined from
|
||||
* the first element, and growth is permitted in both directions.
|
||||
*
|
||||
* @param mixed[] $blocks Blocks to fit.
|
||||
* @param ?int $initial_w Initial width.
|
||||
* @param ?int $initial_h Initial height.
|
||||
* @param ?boolean $permit_growth_w Permits the stack to grow in width.
|
||||
* @param ?boolean $permit_growth_h Permits the stack to grow in height.
|
||||
*/
|
||||
public function fit(&$blocks, $initial_w=null, $initial_h=null, $permit_growth_w=true, $permit_growth_h=true)
|
||||
{
|
||||
$len = count($blocks);
|
||||
$first_block = @reset($blocks);
|
||||
|
||||
$this->permit_growth_w = $permit_growth_w;
|
||||
$this->permit_growth_h = $permit_growth_h;
|
||||
$this->img_padding = Settings::get('pkmn_img_padding');
|
||||
|
||||
// Set the initial sizes.
|
||||
$w = isset($first_block) ? $first_block->w + $this->img_padding : 0;
|
||||
$h = isset($first_block) ? $first_block->h + $this->img_padding : 0;
|
||||
$w = isset($initial_w) ? $initial_w : $w;
|
||||
$h = isset($initial_h) ? $initial_h : $h;
|
||||
|
||||
// Create the root object.
|
||||
$this->root = (object)array(
|
||||
'x' => 0,
|
||||
'y' => 0,
|
||||
'w' => $w,
|
||||
'h' => $h,
|
||||
'used' => false,
|
||||
);
|
||||
|
||||
// Iterate over all our blocks and then either split or grow
|
||||
// nodes on the tree.
|
||||
foreach ($blocks as &$block) {
|
||||
$block_w = $block->w + $this->img_padding;
|
||||
$block_h = $block->h + $this->img_padding;
|
||||
|
||||
$node = $this->find_node($this->root, $block_w, $block_h);
|
||||
|
||||
if ($node) {
|
||||
$block->fit = $this->split_node($node, $block_w, $block_h);
|
||||
}
|
||||
else {
|
||||
$block->fit = $this->grow_node($block_w, $block_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function find_node(&$root, $w, $h)
|
||||
{
|
||||
if (@$root->used) {
|
||||
$node = $this->find_node($root->right, $w, $h);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
$node = $this->find_node($root->down, $w, $h);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (($w <= $root->w) && ($h <= $root->h)) {
|
||||
return $root;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function split_node(&$node, $w, $h)
|
||||
{
|
||||
$node->used = true;
|
||||
$node->down = (object)array(
|
||||
'x' => $node->x,
|
||||
'y' => $node->y + $h,
|
||||
'w' => $node->w,
|
||||
'h' => $node->h - $h,
|
||||
);
|
||||
$node->right = (object)array(
|
||||
'x' => $node->x + $w,
|
||||
'y' => $node->y,
|
||||
'w' => $node->w - $w,
|
||||
'h' => $h,
|
||||
);
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function grow_node($w, $h)
|
||||
{
|
||||
$can_grow_down = ($w <= $this->root->w) && $this->permit_growth_h !== false;
|
||||
$can_grow_right = ($h <= $this->root->h) && $this->permit_growth_w !== false;
|
||||
|
||||
$should_grow_right = $can_grow_right && ($this->root->h >= ($this->root->w + $w));
|
||||
$should_grow_down = $can_grow_down && ($this->root->w >= ($this->root->h + $h));
|
||||
|
||||
if ($should_grow_right) {
|
||||
return $this->grow_right($w, $h);
|
||||
}
|
||||
else
|
||||
if ($should_grow_down) {
|
||||
return $this->grow_down($w, $h);
|
||||
}
|
||||
else
|
||||
if ($can_grow_right) {
|
||||
return $this->grow_right($w, $h);
|
||||
}
|
||||
else
|
||||
if ($can_grow_down) {
|
||||
return $this->grow_down($w, $h);
|
||||
}
|
||||
else {
|
||||
// Error: couldn't grow. This is likely because the input blocks
|
||||
// weren't sorted by size. They must be sorted by (preferably)
|
||||
// max(width, height), with the largest elements appearing first.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function grow($args, $w, $h)
|
||||
{
|
||||
$this->root = $args;
|
||||
$node = $this->find_node($this->root, $w, $h);
|
||||
if ($node) {
|
||||
return $this->split_node($node, $w, $h);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function grow_right($w, $h)
|
||||
{
|
||||
$args = (object)array(
|
||||
'used' => true,
|
||||
'x' => 0,
|
||||
'y' => 0,
|
||||
'w' => $this->root->w + $w,
|
||||
'h' => $this->root->h,
|
||||
'down' => $this->root,
|
||||
'right' => (object)array(
|
||||
'x' => $this->root->w,
|
||||
'y' => 0,
|
||||
'w' => $w,
|
||||
'h' => $this->root->h,
|
||||
)
|
||||
);
|
||||
return $this->grow($args, $w, $h);
|
||||
}
|
||||
|
||||
private function grow_down($w, $h)
|
||||
{
|
||||
$args = (object)array(
|
||||
'used' => true,
|
||||
'x' => 0,
|
||||
'y' => 0,
|
||||
'w' => $this->root->w,
|
||||
'h' => $this->root->h + $h,
|
||||
'down' => $this->root,
|
||||
'right' => (object)array(
|
||||
'x' => 0,
|
||||
'y' => $this->root->h,
|
||||
'w' => $this->root->w,
|
||||
'h' => $h,
|
||||
)
|
||||
);
|
||||
return $this->grow($args, $w, $h);
|
||||
}
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Used to internationalize the application.
|
||||
*/
|
||||
class I18n
|
||||
{
|
||||
/** @var mixed[] Language strings. */
|
||||
private static $lines = array();
|
||||
|
||||
/** @var string Default language. */
|
||||
private static $default_lang = 'en_us';
|
||||
|
||||
/** @var string Current language. */
|
||||
private static $curr_lang = '';
|
||||
|
||||
/** @var mixed[] Output filters. */
|
||||
private static $filters = array();
|
||||
|
||||
/** @var string[] Default language strings. */
|
||||
private static $DEFAULTS = array(
|
||||
// American English (en_us).
|
||||
'en_us' => array(
|
||||
'dex_prefix' => '#',
|
||||
'overview_id' => '#',
|
||||
'overview_dex' => 'Dex',
|
||||
'overview_name' => 'Name',
|
||||
'overview_icon' => 'Icon',
|
||||
'overview_html' => 'HTML',
|
||||
'overview_class' => 'Class',
|
||||
'overview_file' => 'File',
|
||||
'generated_on' => "Generated on %s.",
|
||||
'info' => "<frm=cyan::bold>%s v%s (%s) %s</frm>\n<frm=purple>Generates optimized Pokémon SCSS sprite\n%s\n\n</frm>",
|
||||
'icon_dir_failure' => "<frm=red>Couldn't open icon directory (%s). Skipping.</frm>\n",
|
||||
'dir_create' => "Creating output directory.\n",
|
||||
'dir_error' => "<frm=red>Couldn't create directories.</frm>\n",
|
||||
'gd_error' => "<frm=red>Error: GD functions seem to be missing, e.g. imagecreatefrompng(). Install them or recompile PHP with GD support, then try again.</frm>\n",
|
||||
'dir_success' => "<frm=green>Dirs successfully created.</frm>\n",
|
||||
'no_cli' => "<frm=red>We don't seem to be running via the command line. Keep in mind this tool was designed for command line usage, and hasn't been tested in other situations.</frm>\n",
|
||||
'pngcrush_missing' => "<frm=red>pngcrush seems to be missing (path: %s). By default, it needs to be in the tools directory, chmodded to be executable, and at least version 1.7.60.\nImage will not be optimized by pngcrush.</frm>\n",
|
||||
'no_images' => "<frm=red>Couldn't find the source images. Make sure they're in %sregular/ and %sshiny/.</frm>\n",
|
||||
'no_icon_images' => "<frm=red>Couldn't find the icon images.</frm>\n",
|
||||
'no_data' => "<frm=red>Couldn't find the Pokémon data file. Make sure it's named %s and is placed in the %s directory.</frm>\n",
|
||||
'no_icons_data' => "<frm=red>Couldn't find the icons data file. Make sure it's named %s and is placed in the %s directory.</frm>\n",
|
||||
'sprite_stats' => "\nGenerating %dx%d sprite composed of %d images.\nMemory usage will be about %s.\n",
|
||||
'sprite_ready' => "\n<frm=green>Finished preparing the sprite image.</frm>\n",
|
||||
'sprite_saving' => "Saving sprite image to %s.\n",
|
||||
'icons_added' => "\nAdded %d images.\n",
|
||||
'icons_skipped' => "<frm=red>Failed to add %d images.</frm>\n",
|
||||
'icons_skipped_hint' => "<frm=red>Failed to add %d images. Use --verbose for details.</frm>\n",
|
||||
'pngcrush_start' => "Using pngcrush to optimize the image...\n",
|
||||
'pngcrush_success' => "<frm=green>Successfully optimized the image.\n Old size: %s\n New size: %s\n</frm>",
|
||||
'pngcrush_error' => "<frm=red>Couldn't optimize the image.</frm>\n",
|
||||
'sprite_del_old' => "Deleting the old image.\n",
|
||||
'scss_generating' => "Generating SCSS...\n",
|
||||
'js_generating' => "Generating JS...\n",
|
||||
'html_generating' => "\nGenerating HTML overview...\n",
|
||||
'markdown_generating' => "Generating Markdown overview...\n",
|
||||
'all_done' => "\n<frm=cyan::bold>All done!</frm>\n",
|
||||
'entry_skipped' => " Couldn't find file %s for entry %s. Skipping.\n",
|
||||
'entry_added' => "<frm=green> Added file </frm><frm=green::bold>%s</frm><frm=green> for entry </frm><frm=green::bold>%s</frm><frm=green>.</frm>\n",
|
||||
'arg_error_unknown' => 'unknown error',
|
||||
'arg_error_include_right' => '--include-right must be 0, 1 or 2, e.g. --include-right=1',
|
||||
'arg_error_icon_sets' => '--icon-sets must be a comma-separated list, e.g. --icon-sets=apricorn,ball',
|
||||
'arg_error_file_exts' => '--file-exts must be a comma-separated list, e.g. --file-exts=png,jpg',
|
||||
'arg_error_tpl' => "\n<frm=red>Error: %s</frm>\n",
|
||||
'tasks_overview' => "List of tasks to perform:\n",
|
||||
'task_pkmn' => " Add Pokémon icons to sprite sheet (pkmn=%s, regular=%s, shiny=%s, forms=%s, right=%s, lang=%s)\n",
|
||||
'task_icon_sets' => " Add item icons to sprite sheet\n",
|
||||
'task_optimize' => " Optimize image\n",
|
||||
'task_html' => " Generate HTML overview page\n",
|
||||
'task_markdown' => " Generate Markdown overview page\n",
|
||||
'task_js' => " Generate JS file with image coordinates\n",
|
||||
'task_scss' => " Generate SCSS file with basic styling attributes\n",
|
||||
),
|
||||
// Japanese (ja).
|
||||
'ja' => array(
|
||||
'dex_prefix' => '#',
|
||||
'overview_id' => '#',
|
||||
'overview_dex' => '図鑑',
|
||||
'overview_name' => '名前',
|
||||
'overview_icon' => 'アイコン',
|
||||
'overview_html' => 'HTML',
|
||||
'overview_class' => 'クラス',
|
||||
'overview_file' => 'ファイル',
|
||||
'generated_on' => "Generated on %s.",
|
||||
'info' => "<frm=cyan::bold>%s</frm>\n<frm=purple>Generates optimized Pokémon SCSS sprite\n%s\n\n</frm>",
|
||||
'icon_dir_failure' => "<frm=red>Couldn't open icon directory (%s). Skipping.</frm>\n",
|
||||
'dir_create' => "Creating output directory.\n",
|
||||
'dir_error' => "<frm=red>Couldn't create directories.</frm>\n",
|
||||
'dir_success' => "<frm=green>Dirs successfully created.</frm>\n",
|
||||
'no_cli' => "<frm=red>We don't seem to be running via the command line. Keep in mind this tool was designed for command line usage, and hasn't been tested in other situations.</frm>\n",
|
||||
'pngcrush_missing' => "<frm=red>pngcrush seems to be missing (path: %s). By default, it needs to be in the tools directory, chmodded to be executable, and at least version 1.7.60.\nImage will not be optimized by pngcrush.</frm>\n",
|
||||
'no_images' => "<frm=red>Couldn't find the source images. Make sure they're in %sregular/ and %sshiny/.</frm>\n",
|
||||
'no_icon_images' => "<frm=red>Couldn't find the icon images.</frm>\n",
|
||||
'no_data' => "<frm=red>Couldn't find the Pokémon data file. Make sure it's named %s and is placed in the %s directory.</frm>\n",
|
||||
'no_icons_data' => "<frm=red>Couldn't find the icons data file. Make sure it's named %s and is placed in the %s directory.</frm>\n",
|
||||
'sprite_stats' => "\nGenerating %dx%d sprite composed of %d images.\nMemory usage will be about %s.\n",
|
||||
'sprite_ready' => "\n<frm=green>Finished preparing the sprite image.</frm>\n",
|
||||
'sprite_saving' => "Saving sprite image to %s.\n",
|
||||
'icons_added' => "\nAdded %d images.\n",
|
||||
'icons_skipped' => "<frm=red>Failed to add %d images.</frm>\n",
|
||||
'icons_skipped_hint' => "<frm=red>Failed to add %d images. Use --verbose for details.</frm>\n",
|
||||
'pngcrush_start' => "Using pngcrush to optimize the image...\n",
|
||||
'pngcrush_success' => "<frm=green>Successfully optimized the image.\n Old size: %s\n New size: %s\n</frm>",
|
||||
'pngcrush_error' => "<frm=red>Couldn't optimize the image.</frm>\n",
|
||||
'sprite_del_old' => "Deleting the old image.\n",
|
||||
'scss_generating' => "Generating SCSS...\n",
|
||||
'js_generating' => "Generating JS...\n",
|
||||
'html_generating' => "\nGenerating HTML overview...\n",
|
||||
'markdown_generating' => "\nGenerating Markdown overview...\n",
|
||||
'all_done' => "\n<frm=cyan::bold>All done!</frm>\n",
|
||||
'entry_skipped' => " Couldn't find file %s for entry %s. Skipping.\n",
|
||||
'entry_added' => "<frm=green> Added file </frm><frm=green::bold>%s</frm><frm=green> for entry </frm><frm=green::bold>%s</frm><frm=green>.</frm>\n",
|
||||
'arg_error_unknown' => 'unknown error',
|
||||
'arg_error_include_right' => '--include-right must be 0, 1 or 2, e.g. --include-right=1',
|
||||
'arg_error_icon_sets' => '--icon-sets must be a comma-separated list, e.g. --icon-sets=apricorn,ball',
|
||||
'arg_error_file_exts' => '--file-exts must be a comma-separated list, e.g. --file-exts=png,jpg',
|
||||
'arg_error_tpl' => "\n<frm=red>Error: %s</frm>\n",
|
||||
'tasks_overview' => "List of tasks to perform:\n",
|
||||
'task_pkmn' => " Add Pokémon icons to sprite sheet (pkmn=%s, regular=%s, shiny=%s, forms=%s, right=%s, lang=%s)\n",
|
||||
'task_icon_sets' => " Add item icons to sprite sheet\n",
|
||||
'task_optimize' => " Optimize image\n",
|
||||
'task_html' => " Generate HTML overview page\n",
|
||||
'task_markdown' => " Generate Markdown overview page\n",
|
||||
'task_js' => " Generate JS file with image coordinates\n",
|
||||
'task_scss' => " Generate SCSS file with basic styling attributes\n",
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Populates the language array, optionally for a specific language.
|
||||
*
|
||||
* If no language is given, the default is used.
|
||||
*
|
||||
* @param mixed[] $lines Lines to merge into the language array.
|
||||
* @param string $lang Language to populate.
|
||||
*/
|
||||
public static function set_lines($lines, $lang=null)
|
||||
{
|
||||
if (empty($lang)) {
|
||||
$lang = static::$curr_lang;
|
||||
}
|
||||
if (empty(static::$lines[$lang])) {
|
||||
static::$lines[$lang] = array();
|
||||
}
|
||||
static::$lines[$lang] = array_merge(static::$lines[$lang], $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to the i18n output.
|
||||
*
|
||||
* This allows you to automatically run formatting functions on the
|
||||
* output of the i18n output.
|
||||
*
|
||||
* @param mixed[] $ref Function reference.
|
||||
*/
|
||||
public static function add_output_filter($ref)
|
||||
{
|
||||
static::$filters[] = $ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies queued output filters to a string.
|
||||
*
|
||||
* @param string $str String to filter.
|
||||
*/
|
||||
private static function apply_output_filters($str)
|
||||
{
|
||||
foreach (static::$filters as $filter) {
|
||||
$str = call_user_func($filter, $str);
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted language string by its key, the
|
||||
* vsprintf replacement arguments, and optionally its language.
|
||||
*
|
||||
* @param string $line Line key to retrieve the value for.
|
||||
* @param mixed[] $args Replacement arguments (vsprintf()).
|
||||
* @param string $lang Language to retrieve the value for.
|
||||
*/
|
||||
public static function lf($line, $args=array(), $lang=null)
|
||||
{
|
||||
if (empty($lang)) {
|
||||
$lang = static::$curr_lang;
|
||||
}
|
||||
$line_str = static::l($line, $lang);
|
||||
return vsprintf($line_str, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a line from the language lines array by its key, and
|
||||
* optionally a language.
|
||||
*
|
||||
* @param string $line Line key to retrieve the value for.
|
||||
* @param string $lang Language to retrieve the value for.
|
||||
*/
|
||||
public static function l($line, $lang=null)
|
||||
{
|
||||
if (empty($lang)) {
|
||||
$lang = static::$curr_lang;
|
||||
}
|
||||
return static::apply_output_filters(static::$lines[$lang][$line]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active program language.
|
||||
*
|
||||
* @param string $lang Language to set as the active one.
|
||||
*/
|
||||
public static function set_language($lang)
|
||||
{
|
||||
static::$curr_lang = $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the defaults into the language array.
|
||||
*/
|
||||
public static function set_default_lines()
|
||||
{
|
||||
if (empty(static::$curr_lang)) {
|
||||
static::set_language(static::$default_lang);
|
||||
}
|
||||
foreach (static::$DEFAULTS as $lang => $lines) {
|
||||
static::set_lines($lines, $lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
require_once 'icontplfactory.php';
|
||||
|
||||
/**
|
||||
* Generates the JS file for our sprite.
|
||||
*/
|
||||
class IconJS extends IconTplFactory
|
||||
{
|
||||
/** @var mixed[] A tree structure of our icons. */
|
||||
public $icons;
|
||||
/** @var mixed[] A list icon set sizes. */
|
||||
public $icon_sizes;
|
||||
/** @var mixed[] Data on the two sections of the sprite image (pkmn, etc). */
|
||||
public $sections;
|
||||
/** @var ?string The generated JS. */
|
||||
public $js;
|
||||
|
||||
/**
|
||||
* Sets the tree structure of the icon information and coordinates.
|
||||
*
|
||||
* @param mixed[] $tree Pokémon icon tree structure.
|
||||
*/
|
||||
public function set_icon_tree($tree)
|
||||
{
|
||||
$this->icons = $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sizes of various icon sets.
|
||||
*
|
||||
* @param mixed[] $sizes Icon set size data.
|
||||
*/
|
||||
public function set_icon_sizes($sizes)
|
||||
{
|
||||
$this->icon_sizes = $sizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sprite sections.
|
||||
*
|
||||
* @param mixed[] $sections Sprite section data.
|
||||
*/
|
||||
public function set_sprite_sections($sections)
|
||||
{
|
||||
$this->sections = $sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns generated JS code.
|
||||
*
|
||||
* @return string JS code.
|
||||
*/
|
||||
public function get_js()
|
||||
{
|
||||
if (empty($this->js)) {
|
||||
$this->generate_js();
|
||||
}
|
||||
return $this->js;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates JS code corresponding to our Pokémon icons.
|
||||
*/
|
||||
public function generate_js()
|
||||
{
|
||||
// Prevent warnings in case they're empty.
|
||||
if (empty($this->icons['pkmn'])) {
|
||||
$this->icons['pkmn'] = array();
|
||||
}
|
||||
if (empty($this->icons['etc'])) {
|
||||
$this->icons['etc'] = array();
|
||||
}
|
||||
|
||||
// Determine the coordinates of each Pokémon icon.
|
||||
$coords = array();
|
||||
$right_exc = array();
|
||||
foreach ($this->icons['pkmn'] as $slug => $variations) {
|
||||
// Get one item to ascertain this Pokémon's index number.
|
||||
// It's three levels deep.
|
||||
$first = reset(reset(reset($variations)));
|
||||
$idx = sprintf('%03d', $first['idx']);
|
||||
|
||||
foreach ($variations as $variation => $versions) {
|
||||
foreach ($versions as $version => $subvariations) {
|
||||
foreach ($subvariations as $subvariation => $icon) {
|
||||
$type = $icon['type'];
|
||||
// When generating faux right-facing sprites, the
|
||||
// "flipped" subvariation should be renamed "right".
|
||||
// This is because it's identical to the JS.
|
||||
if ($subvariation == 'flipped') {
|
||||
$subvariation = 'right';
|
||||
}
|
||||
|
||||
$data = $this->get_icon_display_data($icon);
|
||||
$coords[$type][$slug][$variation][$subvariation][$version] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Determine the coordinates of other icons.
|
||||
foreach ($this->icons['etc'] as $type => $items) {
|
||||
foreach ($items as $slug => $item) {
|
||||
$data = $this->get_icon_display_data($item);
|
||||
$coords[$type][$slug] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
// Encode values as JSON.
|
||||
$json_opts = JSON_NUMERIC_CHECK | JSON_FORCE_OBJECT;
|
||||
$sizes_json = json_encode($this->icon_sizes, $json_opts);
|
||||
$coords_json = json_encode($coords, $json_opts);
|
||||
|
||||
// Decorate our template with the generated values.
|
||||
|
||||
if (Settings::get('include_pkmn_nonshiny')) {
|
||||
$fallback_color = 'regular';
|
||||
}
|
||||
else {
|
||||
$fallback_color = 'shiny';
|
||||
}
|
||||
$js_output_min = str_replace(
|
||||
'.js',
|
||||
'.min.js',
|
||||
Settings::get('js_output')
|
||||
);
|
||||
$js = $this->decorate_tpl_with_defaults($this->tpl, array(
|
||||
'sizes_json' => $sizes_json,
|
||||
'coords_json' => $coords_json,
|
||||
'js_output_min' => $js_output_min,
|
||||
'fallback_color' => $fallback_color,
|
||||
'var_base_name' => Settings::get('var_base_name'),
|
||||
));
|
||||
|
||||
$this->js = $this->process_output($js);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves size and coordinate information for an icon.
|
||||
*
|
||||
* In case the icon's type has a defined set size, the width
|
||||
* and height will not be returned.
|
||||
*
|
||||
* @param mixed[] $icon Icon data.
|
||||
* @return int[] Icon coordinates and optionally width.
|
||||
*/
|
||||
public function get_icon_display_data($icon)
|
||||
{
|
||||
// If this icon refers to an original (i.e. it's a form that is
|
||||
// identical to the standard icon), refer to the original's data.
|
||||
if (@$icon['original']) {
|
||||
$x = $icon['original']['fit']['x'];
|
||||
$y = $icon['original']['fit']['y'];
|
||||
$w = $icon['original']['w'];
|
||||
$h = $icon['original']['h'];
|
||||
}
|
||||
else {
|
||||
$x = $icon['x'];
|
||||
$y = $icon['y'];
|
||||
$w = $icon['w'];
|
||||
$h = $icon['h'];
|
||||
}
|
||||
// At least return x and y coordinates.
|
||||
$data = array(
|
||||
'x' => intval($x),
|
||||
'y' => intval($y),
|
||||
);
|
||||
// If this type isn't part of a set with a set size, add the size.
|
||||
$type = $icon['type'] == 'etc' ? $icon['set'] : $icon['type'];
|
||||
if (!isset($this->icon_sizes[$type]['w'])) {
|
||||
$data['w'] = intval($w);
|
||||
$data['h'] = intval($h);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,466 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
require_once 'icontplfactory.php';
|
||||
|
||||
/**
|
||||
* Builds an HTML overview of all icons.
|
||||
*/
|
||||
class IconOverview extends IconTplFactory
|
||||
{
|
||||
/** @var mixed[] A list of our icons. */
|
||||
public $icon_list;
|
||||
/** @var ?string[] The generated overview markup, by format. */
|
||||
public $overview;
|
||||
/** @var ?string[] The generated build overview markup, by format. */
|
||||
public $build_overview;
|
||||
/** @var string Empty cell content. */
|
||||
public $empty_cell = '–';
|
||||
|
||||
/**
|
||||
* Sets the tree structure of the icon information and coordinates.
|
||||
*
|
||||
* @param mixed[] $tree Pokémon icon tree structure.
|
||||
*/
|
||||
public function set_icon_list($tree)
|
||||
{
|
||||
$this->icon_list = $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns overview markup code.
|
||||
*
|
||||
* @param string $format The format to generate the overview in.
|
||||
* @return string Overview markup code.
|
||||
*/
|
||||
public function get_overview($format='html')
|
||||
{
|
||||
if (empty($this->overview[$format])) {
|
||||
$this->generate_overview($format);
|
||||
}
|
||||
return $this->overview[$format];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns build overview markup code.
|
||||
*
|
||||
* @param string $format The format to generate the overview in.
|
||||
* @return string Overview markup code.
|
||||
*/
|
||||
public function get_build_overview($format='html')
|
||||
{
|
||||
if (empty($this->build_overview[$format])) {
|
||||
$this->generate_build_overview($format);
|
||||
}
|
||||
return $this->build_overview[$format];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates overview markup code.
|
||||
*
|
||||
* @param string $format The format to generate the overview in.
|
||||
*/
|
||||
public function generate_overview($format='html')
|
||||
{
|
||||
if ($format == 'html') {
|
||||
$this->generate_overview_html();
|
||||
}
|
||||
else
|
||||
if ($format == 'markdown') {
|
||||
$this->generate_overview_markdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates build overview markup code.
|
||||
*
|
||||
* @param string $format The format to generate the overview in.
|
||||
*/
|
||||
public function generate_build_overview($format='html')
|
||||
{
|
||||
if ($format == 'html') {
|
||||
// Actually, this is the only one we do.
|
||||
$this->generate_build_overview_html();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates overview markup code, Markdown version.
|
||||
*
|
||||
* This overview includes every single icon individually rather than
|
||||
* using the generated sprite image.
|
||||
*
|
||||
* @return string Overview markup code.
|
||||
*/
|
||||
public function generate_overview_markdown()
|
||||
{
|
||||
// Initialize containers.
|
||||
$cols = array('dex', 'name', 'icon', 'class');
|
||||
foreach ($cols as $col) {
|
||||
${$col.'_col'} = array();
|
||||
}
|
||||
|
||||
$github_base_dir = Settings::get('github_base_dir');
|
||||
|
||||
// Iterate over all icons and their variants and add them to the list.
|
||||
foreach ($this->icon_list as $icon) {
|
||||
$idx_str = $this->get_icon_idx_str($icon);
|
||||
$name_str = $this->get_icon_name_str($icon);
|
||||
$classes = $this->get_icon_classes($icon);
|
||||
|
||||
// Check to ensure we're not linking to a non-existent file.
|
||||
if ($icon['is_duplicate_from']) {
|
||||
$img_file = $icon['original']['file'];
|
||||
}
|
||||
else {
|
||||
$img_file = $icon['file'];
|
||||
}
|
||||
|
||||
$icon_str = vsprintf('<img src="%s%s" alt="%s" title="%s" width="%d" height="%d" />', array(
|
||||
$github_base_dir,
|
||||
$this->remove_dot_base($img_file),
|
||||
htmlspecialchars($name_str),
|
||||
$this->remove_dot_base($img_file),
|
||||
$icon['w'],
|
||||
$icon['h'],
|
||||
));
|
||||
$class_str = vsprintf('**`%s`**', array(implode(' ', $classes)));
|
||||
|
||||
// Add an entry in every column.
|
||||
$dex_col[] = $idx_str;
|
||||
$name_col[] = $name_str;
|
||||
$icon_col[] = $icon_str;
|
||||
$class_col[] = $class_str;
|
||||
}
|
||||
|
||||
// Retrieve the string contents of every column.
|
||||
$dex_col = $this->md_table_col(I18n::l('overview_dex'), $dex_col, 'left');
|
||||
$name_col = $this->md_table_col(I18n::l('overview_name'), $name_col);
|
||||
$class_col = $this->md_table_col(I18n::l('overview_class'), $class_col);
|
||||
|
||||
// Add characters to the icon column to force the icons
|
||||
// to display as 40x30.
|
||||
$icon_col = $this->md_table_col(
|
||||
' '.I18n::l('overview_icon').' ', $icon_col, 'center'
|
||||
);
|
||||
|
||||
// Integrate the columns.
|
||||
$table = $this->md_table(array(
|
||||
$dex_col, $name_col, $icon_col, $class_col, $file_col,
|
||||
));
|
||||
|
||||
$this->overview['markdown'] = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Markdown table out of a list of columns.
|
||||
*
|
||||
* Assumes all columns have the same amount of rows.
|
||||
*
|
||||
* @param string[] $cols Columns that make up the content of the table.
|
||||
* @return string Markdown table consisting of data from the columns.
|
||||
*/
|
||||
private function md_table($cols)
|
||||
{
|
||||
$lines = array();
|
||||
|
||||
// First, find out how many rows we have.
|
||||
// We assume all columns have the same amount of rows.
|
||||
$first = reset($cols);
|
||||
$amount = count($first);
|
||||
|
||||
// Iterate over every row, adding lines from every column.
|
||||
for ($a = 0; $a < $amount; ++$a) {
|
||||
$line = '';
|
||||
foreach ($cols as $col) {
|
||||
$line .= $col[$a];
|
||||
}
|
||||
$line .= '|';
|
||||
$lines[] = $line;
|
||||
}
|
||||
return implode("\n", $lines)."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the ./ base from a path in case it exists.
|
||||
*
|
||||
* @param string $path Path to a file or directory.
|
||||
* @return string Path without ./ prefix.
|
||||
*/
|
||||
private function remove_dot_base($path)
|
||||
{
|
||||
if (strpos($path, './') === 0) {
|
||||
$path = substr($path, 2);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rendered Markdown table column as an array of strings.
|
||||
*
|
||||
* Every string in the array will have the same length.
|
||||
*
|
||||
* @param string $name Header title of the column.
|
||||
* @param string[] $rows Column rows.
|
||||
* @param string $align Column alignment (left|center|right).
|
||||
* @return string[] Column lines.
|
||||
*/
|
||||
private function md_table_col($name, $rows, $align='left')
|
||||
{
|
||||
// First, find out what the length of every line should be.
|
||||
$len = strlen((string)$name);
|
||||
foreach ($rows as $row) {
|
||||
$row_len = mb_strlen((string)$row);
|
||||
if ($len < $row_len) {
|
||||
$len = $row_len;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the templates.
|
||||
$tpl_row = '| %'.($align == 'right' ? '' : '-').$len.'s ';
|
||||
$tpl_sep = '|%s%\'-'.$len.'s%s';
|
||||
$colon_l = ($align == 'left' || $align == 'center') ? ':' : ' ';
|
||||
$colon_r = ($align == 'right' || $align == 'center') ? ':' : ' ';
|
||||
|
||||
// Now render the lines.
|
||||
// Fixme: this doesn't work very well with Unicode strings.
|
||||
$col = array();
|
||||
$col[] = sprintf($tpl_row, $name);
|
||||
$col[] = sprintf($tpl_sep, $colon_l, '-', $colon_r);
|
||||
foreach ($rows as $row) {
|
||||
$col[] = sprintf($tpl_row, $row);
|
||||
}
|
||||
return $col;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the classes required to get an icon to display in HTML.
|
||||
*
|
||||
* @return string[] Icon HTML classes.
|
||||
*/
|
||||
private function get_icon_classes($icon)
|
||||
{
|
||||
// Base icon selection classes.
|
||||
$cls_base = Settings::get('css_base_selector');
|
||||
$cls_shiny = 'color-shiny';
|
||||
$cls_female = 'gender-female';
|
||||
$cls_right = 'dir-right';
|
||||
|
||||
// Whether to use slug classes or Pokédex classes in the overview.
|
||||
// (For debugging only.)
|
||||
$use_idx_classes = Settings::get('html_no_slugs');
|
||||
|
||||
// If we're only using shiny icons, omit the "color-shiny" class,
|
||||
// as no regular icons means the fallback will always be shiny.
|
||||
$only_shiny = (
|
||||
Settings::get('include_pkmn_nonshiny') == false &&
|
||||
Settings::get('include_pkmn_shiny') == true
|
||||
);
|
||||
|
||||
$classes = array($cls_base);
|
||||
|
||||
if ($icon['type'] == 'pkmn') {
|
||||
// For Pokémon sprite icons.
|
||||
if ($use_idx_classes) {
|
||||
$classes[] = $icon['type'].'-'.$icon['id'];
|
||||
}
|
||||
else {
|
||||
$classes[] = $icon['type'].'-'.$icon['slug'];
|
||||
}
|
||||
if ($icon['version'] != 'regular' && !$only_shiny) {
|
||||
$classes[] = $cls_shiny;
|
||||
}
|
||||
if ($icon['variation'] != '.') {
|
||||
$classes[] = 'form-'.$icon['variation'];
|
||||
}
|
||||
if ($icon['subvariation'] == 'female') {
|
||||
$classes[] = $cls_female;
|
||||
}
|
||||
if ($icon['subvariation'] == 'right'
|
||||
|| $icon['subvariation'] == 'flipped') {
|
||||
$classes[] = $cls_right;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For all other icon types.
|
||||
$classes[] = $icon['set'].'-'.$icon['slug'];
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon's Pokédex number, or an empty string.
|
||||
*
|
||||
* @return string Dex number, or empty string.
|
||||
*/
|
||||
private function get_icon_idx_str($icon)
|
||||
{
|
||||
$idx = $icon['idx'];
|
||||
$idx_dex = sprintf(I18n::l('dex_prefix').'%03d', $idx);
|
||||
return empty($idx) ? $this->empty_cell_content : $idx_dex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon's name string.
|
||||
*
|
||||
* @return string Name string.
|
||||
*/
|
||||
private function get_icon_name_str($icon)
|
||||
{
|
||||
$name = $icon['name_display'];
|
||||
return empty($name) ? $this->empty_cell_content : $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates build overview markup code, HTML version.
|
||||
*
|
||||
* @return string Build overview markup code.
|
||||
*/
|
||||
public function generate_build_overview_html()
|
||||
{
|
||||
// Allow the template to use the minified version too.
|
||||
$js_output_min = str_replace(
|
||||
'.js',
|
||||
'.min.js',
|
||||
Settings::get('js_output')
|
||||
);
|
||||
|
||||
// Decorate the template with our generated markup.
|
||||
$markup = $this->decorate_tpl_with_defaults($this->tpl, array(
|
||||
'resources_dir' => Settings::get('resources_dir'),
|
||||
'js_output' => Settings::get('js_output'),
|
||||
'js_output_min' => str_replace('.js', '.min.js', Settings::get('js_output')),
|
||||
'html_rel_home' => Settings::get('html_rel_home'),
|
||||
'icons_amount' => htmlspecialchars(count($this->icon_list)),
|
||||
'script_date' => Settings::get('script_date'),
|
||||
'css_output' => str_replace('.scss', '.css', Settings::get('scss_output')),
|
||||
'css_output_min' => str_replace('.scss', '.min.css', Settings::get('scss_output')),
|
||||
'title_str_html' => htmlspecialchars(Settings::get('title_str')),
|
||||
'script_date_html' => htmlspecialchars(Settings::get('script_date')),
|
||||
'website_html' => htmlspecialchars(Settings::get('website')),
|
||||
));
|
||||
|
||||
$this->build_overview['html'] = $this->process_output($markup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates overview markup code, HTML version.
|
||||
*
|
||||
* @return string Overview markup code.
|
||||
*/
|
||||
public function generate_overview_html()
|
||||
{
|
||||
// Keep track of which Pokémon we're at, to use rowspan.
|
||||
$curr_pkmn = '';
|
||||
$first_icon = true;
|
||||
|
||||
// Empty cells will get this content.
|
||||
$empty_cell = $this->empty_cell_content;
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<table class="table pkspr-overview">
|
||||
<tr>
|
||||
<th class="n"><p><?= I18n::l('overview_id'); ?><span class="spacer">000</span></p></th>
|
||||
<th class="idx"><p><?= I18n::l('overview_dex'); ?></p></th>
|
||||
<th class="name"><p><?= I18n::l('overview_name'); ?></p></th>
|
||||
<th class="icon"><p><?= I18n::l('overview_icon'); ?></p></th>
|
||||
<th class="example"><p><?= I18n::l('overview_html'); ?></p></th>
|
||||
</tr>
|
||||
<?php
|
||||
$n = 0;
|
||||
// Iterate over all icons and their variants and add them to the list.
|
||||
foreach ($this->icon_list as $icon) {
|
||||
if ($curr_pkmn === '') {
|
||||
$curr_pkmn = $icon['id'];
|
||||
$first_icon = true;
|
||||
|
||||
// How many more icons does this ID get?
|
||||
$pokeid_icons = 0;
|
||||
for ($m = $n; $m < count($this->icon_list); ++$m) {
|
||||
if ($this->icon_list[$m]['id'] !== $curr_pkmn) {
|
||||
break;
|
||||
}
|
||||
$pokeid_icons += 1;
|
||||
}
|
||||
}
|
||||
|
||||
$idx_str = $this->get_icon_idx_str($icon);
|
||||
$name_str = $this->get_icon_name_str($icon);
|
||||
$classes = $this->get_icon_classes($icon);
|
||||
|
||||
$classes_str = implode(' ', $classes);
|
||||
$classes_str_safe = htmlspecialchars($classes_str);
|
||||
$html_id = 'icon_'.$n;
|
||||
|
||||
if ($icon['is_duplicate_from']) {
|
||||
$img_file = $icon['original']['file'];
|
||||
}
|
||||
else {
|
||||
$img_file = $icon['file'];
|
||||
}
|
||||
|
||||
$img_str = '<span id="'.$html_id.'" class="'.$classes_str.'"></span>';
|
||||
$decorator = '<script>PkSpr.decorate(\''.$html_id.'\');</script>';
|
||||
$example_str = '<pre><code>'.htmlspecialchars('<span class="').'<span class="class">'.$classes_str_safe.'</span>'.htmlspecialchars('"></span>').'</code></pre>';
|
||||
$file_link = Settings::get('icon_url_img_base').$this->remove_dot_base($img_file);
|
||||
?>
|
||||
<tr>
|
||||
<td class="n"><p><a href="<?= $file_link; ?>"><?= $n; ?></a></p></td>
|
||||
<?php
|
||||
if ($first_icon) {
|
||||
?>
|
||||
<td class="idx" rowspan="<?= $pokeid_icons; ?>"><p class="idx"><?= $idx_str; ?></p></td>
|
||||
<td class="name" rowspan="<?= $pokeid_icons; ?>"><p><?= $name_str; ?></p></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<td class="icon"><p><?= $img_str.$decorator; ?></p></td>
|
||||
<td class="example"><?= $example_str; ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
$n += 1;
|
||||
$pokeid_icons -= 1;
|
||||
$first_icon = false;
|
||||
if ($pokeid_icons <= 0) {
|
||||
$curr_pkmn = '';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
<?php
|
||||
$icons = ob_get_clean();
|
||||
|
||||
// Allow the template to use the minified version too.
|
||||
$js_output_min = str_replace(
|
||||
'.js',
|
||||
'.min.js',
|
||||
Settings::get('js_output')
|
||||
);
|
||||
|
||||
// Decorate the template with our generated markup.
|
||||
$markup = $this->decorate_tpl_with_defaults($this->tpl, array(
|
||||
'icons' => $this->indent_lines($icons, 4),
|
||||
'resources_dir' => Settings::get('resources_dir'),
|
||||
'js_output' => Settings::get('js_output'),
|
||||
'js_output_min' => $js_output_min,
|
||||
'html_rel_home' => Settings::get('html_rel_home'),
|
||||
'script_date' => Settings::get('script_date'),
|
||||
'css_output' => str_replace('.scss', '.css', Settings::get('scss_output')),
|
||||
'css_output_min' => str_replace('.scss', '.min.css', Settings::get('scss_output')),
|
||||
'title_str_html' => htmlspecialchars(Settings::get('title_str')),
|
||||
'script_date_html' => htmlspecialchars(Settings::get('script_date')),
|
||||
'icons_amount' => htmlspecialchars(count($this->icon_list)),
|
||||
'website_html' => htmlspecialchars(Settings::get('website')),
|
||||
));
|
||||
|
||||
$this->overview['html'] = $this->process_output($markup);
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Generates an image file containing all sprites.
|
||||
*/
|
||||
class IconSprite
|
||||
{
|
||||
/** @var mixed The sprite image object. */
|
||||
public $sprite;
|
||||
/** @var mixed[] Data on the two sections of the sprite image (pkmn, etc). */
|
||||
public $sections;
|
||||
/** @var mixed[] Copies of primary Pokémon positioning data for use with duplicates. */
|
||||
public $std_pkmn;
|
||||
/** @var boolean Whether to be verbose in giving feedback. */
|
||||
public $verbose;
|
||||
/** @var mixed[] Default sprites (base for a duplicate). */
|
||||
public $std_sprites = array();
|
||||
/** @var int Image padding. */
|
||||
public $img_padding;
|
||||
|
||||
/**
|
||||
* Initializes the sprite.
|
||||
*
|
||||
* @param int $width Width of the sprite.
|
||||
* @param int $height Height of the sprite.
|
||||
* @param mixed[] $sections Image sprite section data.
|
||||
* @param boolean $verbose Verbosity in giving feedback.
|
||||
*/
|
||||
function __construct($width, $height, $sections, $verbose=false)
|
||||
{
|
||||
$this->img_padding = Settings::get('pkmn_img_padding');
|
||||
$this->sprite = @imagecreatetruecolor($width, $height);
|
||||
imagesavealpha($this->sprite, true);
|
||||
$trnsp = @imagecolorallocatealpha($this->sprite, 0, 0, 0, 127);
|
||||
imagefill($this->sprite, 0, 0, $trnsp);
|
||||
|
||||
$this->sections = $sections;
|
||||
$this->verbose = $verbose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets standard icons for use with duplicates.
|
||||
*
|
||||
* @param mixed[] $pkmn Standard icons info.
|
||||
*/
|
||||
function set_pkmn_std_icons($pkmn)
|
||||
{
|
||||
$this->std_sprites = $pkmn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single icon to the stack.
|
||||
*
|
||||
* @param mixed[] $icon Icon (pkmn or etc group).
|
||||
*/
|
||||
function add($icon)
|
||||
{
|
||||
$x = $icon['fit']['x'] + $this->img_padding;
|
||||
$y = $icon['fit']['y'] + $this->img_padding;
|
||||
$w = $icon['w'];
|
||||
$h = $icon['h'];
|
||||
$file = $icon['file'];
|
||||
$slug = $icon['slug'];
|
||||
$type = $icon['type'];
|
||||
|
||||
// Put the other icons underneath the Pokémon icons.
|
||||
if ($icon['section'] != 'pkmn') {
|
||||
$y += $this->sections['pkmn'];
|
||||
}
|
||||
// Remove the padding we added to the Pokémon icons earlier.
|
||||
// Hackish, I know...
|
||||
if ($icon['section'] == 'pkmn') {
|
||||
$w -= $this->img_padding;
|
||||
$h -= $this->img_padding;
|
||||
}
|
||||
|
||||
$indicator = ($type == 'pkmn' ? $icon['name_display'].' (variation='.$icon['variation'].', subvariation='.$icon['subvariation'].', version='.$icon['version'].')' : $slug);
|
||||
|
||||
if ($icon['is_duplicate_from']) {
|
||||
// If this is a duplicate, we don't need to add it.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_file($file)) {
|
||||
// If the file does not exist, skip this entry.
|
||||
if ($this->verbose) {
|
||||
print(I18n::lf('entry_skipped', array($file, $indicator)));
|
||||
}
|
||||
// Image not added.
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ($this->verbose) {
|
||||
print(I18n::lf('entry_added', array($file, $indicator)));
|
||||
}
|
||||
}
|
||||
|
||||
// Open the image data.
|
||||
$tmp = @imagecreatefrompng($file);
|
||||
|
||||
// If we're adding a faux right-facing image, we have to manually
|
||||
// flip the image before copying it to the sprite.
|
||||
if (@$icon['subvariation'] == 'flipped') {
|
||||
$tmp = $this->x_imageflip($tmp, 'v');
|
||||
}
|
||||
|
||||
// Copy the image to the sprite.
|
||||
@imagecopy($this->sprite, $tmp, $x, $y, 0, 0, $w, $h);
|
||||
@imagedestroy($tmp);
|
||||
|
||||
// Image added.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the image.
|
||||
*
|
||||
* If $compress is false, only the lowest compression
|
||||
* ratio will be applied, as we'll be using pngcrush later.
|
||||
*
|
||||
* @param string $location Where to save the (temporary) file.
|
||||
* @param boolean $compress Whether to apply significant compression.
|
||||
*/
|
||||
function output($location, $compress=true)
|
||||
{
|
||||
imagepng($this->sprite, $location, $compress === true ? 9 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips an image horizontally, vertically or both.
|
||||
*
|
||||
* Used to generated flipped images of Pokémon icons from their
|
||||
* original icons. Note that, for some inexplicable reason, the position is
|
||||
* off by 1px normally. This function accounts for the difference. However,
|
||||
* exactly why this happens is unknown. If the PHP version is >= 5.5.0,
|
||||
* the native GD imageflip() function is used instead.
|
||||
*
|
||||
* This was adapted from the code provided on <http://php.net/manual/en/function.imagecopy.php#85992> by xafford.
|
||||
*
|
||||
* @param mixed $imgsrc Image source.
|
||||
* @param string $direction Direction in which to flip (h|v|b).
|
||||
*
|
||||
*/
|
||||
function x_imageflip($imgsrc, $direction='b')
|
||||
{
|
||||
// If we've got a native function, use that.
|
||||
if (function_exists('imageflip')) {
|
||||
// This hasn't been verified to be accurate, though...
|
||||
imageflip($imgsrc,
|
||||
$direction == 'h' ? IMG_FLIP_HORIZONTAL :
|
||||
($direction == 'v' ? IMG_FLIP_VERTICAL :
|
||||
($direction == 'b' ? IMG_FLIP_BOTH : -1))
|
||||
);
|
||||
return $imgsrc;
|
||||
}
|
||||
$width = imagesx($imgsrc);
|
||||
$height = imagesy($imgsrc);
|
||||
|
||||
$src_x = 0;
|
||||
$src_y = 0;
|
||||
$src_width = $width;
|
||||
$src_height = $height;
|
||||
|
||||
switch ($direction) {
|
||||
case 'h':
|
||||
$src_y = floor($height - 1);
|
||||
$src_height = floor(-$height - 1);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
$src_x = floor($width - 1);
|
||||
$src_width = floor(-$width - 1);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
$src_x = $width - 1;
|
||||
$src_y = $height - 1;
|
||||
$src_width = -$width - 1;
|
||||
$src_height = -$height - 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return $imgsrc;
|
||||
}
|
||||
|
||||
$imgdest = imagecreatetruecolor($width, $height);
|
||||
imagesavealpha($imgdest, true);
|
||||
$trnsp = @imagecolorallocatealpha($imgdest, 0, 0, 0, 127);
|
||||
imagefill($imgdest, 0, 0, $trnsp);
|
||||
|
||||
if (imagecopyresampled($imgdest, $imgsrc, 0, 0, $src_x, $src_y, $width, $height, $src_width, $src_height)) {
|
||||
return $imgdest;
|
||||
}
|
||||
|
||||
return $imgsrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the image object.
|
||||
*/
|
||||
function destroy()
|
||||
{
|
||||
imagedestroy($this->sprite);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,145 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
require_once 'icontplfactory.php';
|
||||
|
||||
/**
|
||||
* Generates the SCSS file for our sprite.
|
||||
*/
|
||||
class IconStyler extends IconTplFactory
|
||||
{
|
||||
/** @var mixed[] A list of our icons. */
|
||||
public $icon_list;
|
||||
/** @var mixed[] A list icon set sizes. */
|
||||
public $icon_sizes;
|
||||
/** @var ?string The generated SCSS. */
|
||||
public $scss;
|
||||
|
||||
/**
|
||||
* Sets the tree structure of the icon information and coordinates.
|
||||
*
|
||||
* @param mixed[] $tree Pokémon icon tree structure.
|
||||
*/
|
||||
public function set_icon_list($tree)
|
||||
{
|
||||
$this->icon_list = $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sizes of various icon sets.
|
||||
*
|
||||
* @param mixed[] $sizes Icon set size data.
|
||||
*/
|
||||
public function set_icon_sizes($sizes)
|
||||
{
|
||||
$this->icon_sizes = $sizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns generated SCSS code.
|
||||
*
|
||||
* @return string SCSS code.
|
||||
*/
|
||||
public function get_scss()
|
||||
{
|
||||
if (empty($this->scss)) {
|
||||
$this->generate_scss();
|
||||
}
|
||||
return $this->scss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates SCSS code corresponding to our Pokémon icons.
|
||||
*/
|
||||
public function generate_scss()
|
||||
{
|
||||
$var_base_name = Settings::get('var_base_name');
|
||||
|
||||
// Generate the variables.
|
||||
ob_start();
|
||||
?>
|
||||
$<?= $var_base_name; ?>-types: (
|
||||
<?php
|
||||
foreach ($this->icon_sizes as $var => $size) {
|
||||
// Check whether this icon type has variable sizes or not.
|
||||
if (isset($size['w']) && isset($size['h'])) {
|
||||
?>
|
||||
<?= $var; ?>: (
|
||||
w: <?= $size['w']; ?>, h: <?= $size['h']; ?>,
|
||||
),
|
||||
<?php
|
||||
}
|
||||
else {
|
||||
?>
|
||||
<?= $var; ?>: (),
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
);
|
||||
$<?= $var_base_name; ?>-coords: (
|
||||
<?php
|
||||
// Go over each icon and save its coordinates and size.
|
||||
foreach ($this->icon_list as $pos) {
|
||||
// If this icon is a duplicate,
|
||||
// refer to the original icon's coordinates.
|
||||
if (isset($pos['original'])) {
|
||||
$x = $pos['original']['fit']['x'];
|
||||
$y = $pos['original']['fit']['y'];
|
||||
}
|
||||
else {
|
||||
$x = $pos['fit']['x'];
|
||||
$y = $pos['fit']['y'];
|
||||
}
|
||||
// We'll add the width and height variables to each item
|
||||
// for completeness purposes, even though in practice the
|
||||
// size will be dictated by the item type.
|
||||
// (Except in the case of icon collections containing
|
||||
// images of multiple sizes.)
|
||||
$attrs = array(
|
||||
'x' => intval($x),
|
||||
'y' => intval($y),
|
||||
'w' => intval($pos['w']),
|
||||
'h' => intval($pos['h']),
|
||||
);
|
||||
$attr_list = array();
|
||||
foreach ($attrs as $k => $v) {
|
||||
$attr_list[] = $k.': '.$v;
|
||||
}
|
||||
?>
|
||||
<?= $pos['var']; ?>: (<?= implode(', ', $attr_list); ?>),
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
);
|
||||
<?php
|
||||
$item_vars = ob_get_clean();
|
||||
|
||||
// Go over each icon type and save its size.
|
||||
ob_start();
|
||||
foreach ($this->icon_sizes as $var => $size) {
|
||||
?>
|
||||
&[class*='<?= $var; ?>-'] {
|
||||
@include <?= $var_base_name; ?>-type('<?= $var; ?>');
|
||||
}
|
||||
<?php
|
||||
}
|
||||
$type_sizes = ob_get_clean();
|
||||
|
||||
// Add all our generated code to the tempalte file.
|
||||
$scss = $this->decorate_tpl_with_defaults($this->tpl, array(
|
||||
'item_vars' => $item_vars,
|
||||
'type_sizes' => $this->indent_lines($type_sizes, 2),
|
||||
'var_base_name' => $var_base_name,
|
||||
'img_output' => Settings::get('img_output'),
|
||||
));
|
||||
|
||||
$this->scss = $this->process_output($scss);
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Base class for loading in templates and replacing placeholder variables.
|
||||
*/
|
||||
class IconTplFactory
|
||||
{
|
||||
/** @var string Contents of the template file. */
|
||||
public $tpl;
|
||||
/** @var string Path to the template file. */
|
||||
public $tpl_file;
|
||||
/** @var mixed[] Variables used to render the output. */
|
||||
public $tpl_vars;
|
||||
|
||||
/**
|
||||
* Loads the template file into a buffer.
|
||||
*/
|
||||
public function register_tpl($file)
|
||||
{
|
||||
$this->tpl_file = $file;
|
||||
$this->tpl = file_get_contents($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an array of variables, to be used later when
|
||||
* rendering the output.
|
||||
*/
|
||||
public function register_vars($vars)
|
||||
{
|
||||
$this->tpl_vars = $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace placeholders in a template with the provided values.
|
||||
*
|
||||
* For example, in a template containing {{$my_key}}, passing
|
||||
* array('my_key' => 'hi') will replace the key with 'hi'.
|
||||
*
|
||||
* @param string $tpl Template string to process.
|
||||
* @param mixed[] $args Arguments to use for replacement.
|
||||
* @return string Decorated template.
|
||||
*/
|
||||
public function decorate_tpl($tpl, $args)
|
||||
{
|
||||
foreach ($args as $k => $v) {
|
||||
$tpl = str_replace('{{$'.$k.'}}', $v, $tpl);
|
||||
}
|
||||
return $tpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the final modifications to the output.
|
||||
*
|
||||
* @param string $str String to process.
|
||||
* @param boolean $write_bom Whether to write a BOM to the file.
|
||||
* @return string Processed output.
|
||||
*/
|
||||
public function process_output($str, $write_bom=false)
|
||||
{
|
||||
$str = $this->normalize_lines($str);
|
||||
|
||||
// Write the BOM. We assume the input is UTF-8.
|
||||
if ($write_bom) {
|
||||
$bom = chr(239).chr(187).chr(191);
|
||||
$str = $bom.$str;
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the decorate_tpl() function with a template name and
|
||||
* an array of variables.
|
||||
*
|
||||
* Prior to performing the decoration, the passed variables
|
||||
* are merged with the default variables.
|
||||
*
|
||||
* @param string $tpl Template string to process.
|
||||
* @param mixed[] $args Arguments to use for replacement.
|
||||
* @return string Decorated template.
|
||||
*/
|
||||
public function decorate_tpl_with_defaults($tpl, $args)
|
||||
{
|
||||
$args = array_merge($this->tpl_vars, $args);
|
||||
return $this->decorate_tpl($tpl, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indents lines using either tabs or spaces.
|
||||
*
|
||||
* By default, spaces are used.
|
||||
*
|
||||
* @param string $str String to indent.
|
||||
* @param int $level Level of indentation.
|
||||
* @param string $char Character to use for indentation.
|
||||
* @return string Indented string.
|
||||
*/
|
||||
public function indent_lines($str, $level=2, $char=' ')
|
||||
{
|
||||
$lines = preg_split('/\n|\r/', $str, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($lines as &$line) {
|
||||
$line = str_repeat($char, $level).$line;
|
||||
}
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all linebreaks with cross-platform \r\n sequences.
|
||||
*
|
||||
* @param string $str Lines to normalize.
|
||||
* @return string Normalized lines.
|
||||
*/
|
||||
private function normalize_lines($str)
|
||||
{
|
||||
$str = preg_replace('~\R~u', "\r\n", $str);
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
set_time_limit(0);
|
||||
date_default_timezone_set('UTC');
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Container for program settings.
|
||||
*/
|
||||
class Settings {
|
||||
/** @var mixed[] Current settings. */
|
||||
public static $settings = array();
|
||||
|
||||
/**
|
||||
* Loads settings from a file and merges its contents with the
|
||||
* current settings.
|
||||
*
|
||||
* @param string $filename Name of the settings file.
|
||||
*/
|
||||
public static function load_settings_file($filename)
|
||||
{
|
||||
// Turn on output buffering to prevent accidental output.
|
||||
ob_start();
|
||||
include($filename);
|
||||
ob_get_clean();
|
||||
|
||||
// We should now have an array $s with which to merge
|
||||
// the current settings.
|
||||
if (!empty($s)) {
|
||||
static::load_settings($s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the new settings into the old settings.
|
||||
*
|
||||
* @param mixed[] $new_settings New settings array.
|
||||
*/
|
||||
public static function load_settings($new_settings)
|
||||
{
|
||||
// The old variables are maintained unless overwritten.
|
||||
static::$settings = array_merge(static::$settings, $new_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a setting value by its key.
|
||||
*
|
||||
* @param string $key Settings key to return.
|
||||
* @return ?mixed Settings value.
|
||||
*/
|
||||
public static function get($key)
|
||||
{
|
||||
return @static::$settings[$key];
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Used to replace variables in template files.
|
||||
*/
|
||||
class TemplateFormatter
|
||||
{
|
||||
/** @var string Current usage template. */
|
||||
public $tpl = '';
|
||||
|
||||
/** @var string Rendered template buffer. */
|
||||
public $buffer = '';
|
||||
|
||||
/** @var mixed[] Template replacement variables. */
|
||||
public $tpl_vars = array();
|
||||
|
||||
/**
|
||||
* Loads a usage template from a file.
|
||||
*
|
||||
* @param string $filename Name of the template file.
|
||||
*/
|
||||
public function load_tpl_file($filename)
|
||||
{
|
||||
$contents = @file_get_contents($filename);
|
||||
if (!empty($contents)) {
|
||||
$this->tpl = $contents;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges new variables into the template replacement variables array.
|
||||
*
|
||||
* @param mixed[] $vars Array of new template replacement variables.
|
||||
*/
|
||||
public function register_vars($vars)
|
||||
{
|
||||
$this->tpl_vars = array_merge($this->tpl_vars, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the template by replacing variables and storing the result
|
||||
* in the buffer.
|
||||
*
|
||||
* Optionally, one can pass an array of template replacement variables.
|
||||
*
|
||||
* @param mixed[] $vars Array of new template replacement variables.
|
||||
*/
|
||||
public function render($vars=array())
|
||||
{
|
||||
if (!empty($vars)) {
|
||||
$this->register_vars($vars);
|
||||
}
|
||||
$this->buffer = $this->var_repl($this->tpl, $this->tpl_vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces template variables with their values, as taken
|
||||
* from the $tpl_vars array.
|
||||
*
|
||||
* @param string $tpl Template to decorate.
|
||||
* @param mixed[] $vars Array of replacement variables.
|
||||
*/
|
||||
private function var_repl($tpl, $vars)
|
||||
{
|
||||
foreach ($vars as $k => $v) {
|
||||
$tpl = str_replace('{{$'.$k.'}}', $v, $tpl);
|
||||
}
|
||||
return $tpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rendered template file.
|
||||
*
|
||||
* @return string The current output buffer.
|
||||
*/
|
||||
public function get_buffer()
|
||||
{
|
||||
return $this->buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the rendered template file.
|
||||
*/
|
||||
public function output_buffer($str)
|
||||
{
|
||||
print($this->buffer);
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Simple formatter for data display in a terminal.
|
||||
*
|
||||
* See the TerminalFormatter->format() function for an explanation
|
||||
* of the markup system.
|
||||
*/
|
||||
class TerminalFormatter
|
||||
{
|
||||
/**
|
||||
* Adds ISO 6429 terminal color escape sequences to a string.
|
||||
*
|
||||
* There are eight defined colors: white, red, green, yellow, blue, purple,
|
||||
* cyan, and white. Aside from the colors, the text can be set to
|
||||
* three effects: bold, underline, blink.
|
||||
*
|
||||
* @param string $str String to be enclosed in the escape sequence.
|
||||
* @param string $fg Foreground color (default: white).
|
||||
* @param string $bg Background color (default: null).
|
||||
* @param string[] $effects Array of effects to use (default: null).
|
||||
*/
|
||||
public function term_color($str, $fg='white', $bg=null, $effects=array())
|
||||
{
|
||||
// Terminal colors and effects as defined by the ISO 6429 standard.
|
||||
// To get a foreground color, add 30; for a background color, add 40.
|
||||
$iso_colors = array(
|
||||
'black' => 0,
|
||||
'red' => 1,
|
||||
'green' => 2,
|
||||
'yellow' => 3,
|
||||
'blue' => 4,
|
||||
'purple' => 5,
|
||||
'cyan' => 6,
|
||||
'white' => 7,
|
||||
);
|
||||
$iso_effects = array(
|
||||
'bold' => 1,
|
||||
'underline' => 4,
|
||||
'blink' => 5,
|
||||
);
|
||||
|
||||
// Iterate over the user's desired effects and put the numbers in a list.
|
||||
$parsed_effects = array();
|
||||
if (!empty($effects)) {
|
||||
foreach ($effects as $effect) {
|
||||
$parsed_effects[] = $iso_effects[$effect];
|
||||
}
|
||||
}
|
||||
|
||||
// Check if our foreground and background colors are sane.
|
||||
if (!in_array($fg, array_keys($iso_colors))) {
|
||||
$fg = 'white';
|
||||
}
|
||||
if (!in_array($bg, array_keys($iso_colors))) {
|
||||
$bg = null;
|
||||
}
|
||||
// Turn the color strings into ISO color numbers.
|
||||
// The background color can be blank, but the foreground color must be set.
|
||||
$fg_color = 30 + $iso_colors[$fg];
|
||||
$bg_color = $bg == null ? '' : 40 + $iso_colors[$bg].';';
|
||||
|
||||
// Prepare and return the formatted string.
|
||||
$color_str = $bg_color.$fg_color;
|
||||
$effects_str = implode(';', $parsed_effects);
|
||||
|
||||
return vsprintf("\033[%s;%sm%s\033[0m", array(
|
||||
$effects_str,
|
||||
$color_str,
|
||||
$str,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string for display in a terminal in accordance with our
|
||||
* internal formatting schema.
|
||||
*
|
||||
* Text can be marked up using the following schema:
|
||||
* <frm=[foreground color][:background color][:list of effects]>text</frm>.
|
||||
* The foreground and background colors may be one of the ISO 6429
|
||||
* terminal colors: white, red, green, yellow, blue, purple, cyan,
|
||||
* and black. If a background color is defined, the foreground color
|
||||
* must be defined too. The list of effects must be comma-separated and
|
||||
* may include bold, underline and blink.
|
||||
*
|
||||
* Some examples follow.
|
||||
*
|
||||
* <frm=red:yellow>Red text with yellow background</frm>
|
||||
* <frm=red::bold>Bold red text</frm>
|
||||
* <frm=blue:yellow:bold,underline>Blue/yellow, bold and underlined</frm>
|
||||
* <frm=::blink>Blinking text (default color)</frm>
|
||||
*
|
||||
* Nesting of these tags is not possible. So to follow red text
|
||||
* up with red text with a yellow background, do the following:
|
||||
*
|
||||
* This is <frm=red>red text, and now </frm><frm=red:yellow>with a
|
||||
* background too</frm>.
|
||||
*
|
||||
* @param string $str The string to format.
|
||||
*/
|
||||
public function format($str)
|
||||
{
|
||||
$str = preg_replace_callback(
|
||||
'/<frm=(.+?)>(.+?)<\/frm>/is',
|
||||
array(self, 'cb_format_style'),
|
||||
$str
|
||||
);
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Styles a regular expression string match. (Callback.)
|
||||
*
|
||||
* @param string[] $matches Regular expression matches.
|
||||
*/
|
||||
private function cb_format_style($matches)
|
||||
{
|
||||
$style = self::parse_format_arg($matches[1]);
|
||||
return self::term_color(
|
||||
$matches[2],
|
||||
$style['fg'],
|
||||
$style['bg'],
|
||||
$style['effects']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses styling values extracted out of the <frm> tag.
|
||||
*
|
||||
* @param string $arg Argument taken from the <frm> tag.
|
||||
*/
|
||||
private function parse_format_arg($arg)
|
||||
{
|
||||
$bits = explode(':', $arg);
|
||||
$fg = @empty($bits[0]) ? null : $bits[0];
|
||||
$bg = @empty($bits[1]) ? null : $bits[1];
|
||||
$effects = empty($bits[2]) ? null : @explode(',', $bits[2]);
|
||||
return array('fg' => $fg, 'bg' => $bg, 'effects' => $effects);
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// The use of this source code is governed by the MIT license.
|
||||
// See the COPYRIGHT file for more information.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
/**
|
||||
* Used to display program usage information.
|
||||
*
|
||||
* Requires an external template file to determine what to display.
|
||||
*/
|
||||
class Usage extends TemplateFormatter
|
||||
{
|
||||
/** @var string[] Arguments that require a value. */
|
||||
public static $ARG_REQ = array(
|
||||
'dir-icons:', 'dir-data:', 'file-data:', 'file-icons-data:',
|
||||
'dir-output:', 'file-output-img-tmp:', 'file-output-img:',
|
||||
'file-output-scss:', 'file-output-html:', 'file-output-md:',
|
||||
'tpl-scss:', 'tpl-html:', 'css-base-sel:', 'css-shiny-sel:',
|
||||
'css-female-sel:', 'css-right-sel:', 'css-inline-sel:',
|
||||
'css-block-sel:', 'path-pngcrush:', 'dir-pkmn:', 'dir-resources:',
|
||||
'pkmn-lang:', 'lang:',
|
||||
// Undocumented (debugging only):
|
||||
'pkmn-range:',
|
||||
);
|
||||
/** @var string[] Arguments that may have a value. */
|
||||
public static $ARG_OPT = array(
|
||||
'include-right::',
|
||||
'file-exts::',
|
||||
'icon-sets::',
|
||||
);
|
||||
/** @var string[] Arguments that can have no value. */
|
||||
public static $ARG_NONE = array(
|
||||
'exclude-pkmn', 'exclude-shiny', 'exclude-regular', 'exclude-forms',
|
||||
'exclude-icon-sets', 'verbose', 'monochrome', 'help', 'no-pngcrush',
|
||||
'generate-markdown', 'no-padding', 'exclude-special-icons', 'version',
|
||||
// Undocumented (debugging only):
|
||||
'html-no-slugs',
|
||||
);
|
||||
|
||||
/** @var mixed[] Settings parsed from the command-line options. */
|
||||
public $opt_settings = array();
|
||||
|
||||
/** @var boolean Whether the user should be shown the usage overview. */
|
||||
public $needs_usage = false;
|
||||
/** @var boolean Whether the user should be shown the version number. */
|
||||
public $needs_version = false;
|
||||
/** @var boolean Whether invalid or unknown arguments were passed. */
|
||||
public $argument_error = false;
|
||||
/** @var string|null Error identifier. */
|
||||
public $error_id = null;
|
||||
|
||||
/**
|
||||
* Returns command-line arguments.
|
||||
*
|
||||
* @return mixed[] Command-line arguments.
|
||||
*/
|
||||
private function get_opts()
|
||||
{
|
||||
// Only long-style options are supported.
|
||||
$long = array_merge(
|
||||
static::$ARG_REQ,
|
||||
static::$ARG_OPT,
|
||||
static::$ARG_NONE
|
||||
);
|
||||
$opts = getopt('', $long);
|
||||
return $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the user's passed command-line arguments and makes
|
||||
* a determination of whether the user invoked the script correctly.
|
||||
*/
|
||||
private function parse_opts()
|
||||
{
|
||||
// The user's arguments will create a settings file that can
|
||||
// be used to directly overwrite the current settings.
|
||||
$s = array();
|
||||
// Whether an argument error has occurred.
|
||||
$argument_error = false;
|
||||
// Error explanation identifier.
|
||||
$error_id = 'arg_error_unknown';
|
||||
|
||||
$opts = $this->get_opts();
|
||||
|
||||
// Iterate over the command-line arguments.
|
||||
foreach ($opts as $arg => $val) {
|
||||
if ($arg == 'help') {
|
||||
$this->needs_usage = true;
|
||||
break;
|
||||
}
|
||||
if ($arg == 'version') {
|
||||
$this->needs_version = true;
|
||||
break;
|
||||
}
|
||||
if ($arg == 'monochrome') {
|
||||
$s['debug_monochrome'] = true;
|
||||
}
|
||||
if ($arg == 'verbose') {
|
||||
$s['debug_img_inclusion'] = true;
|
||||
}
|
||||
if ($arg == 'exclude-icon-sets') {
|
||||
$s['include_icon_sets'] = false;
|
||||
}
|
||||
if ($arg == 'exclude-special-icons') {
|
||||
$s['include_special_icons'] = false;
|
||||
}
|
||||
if ($arg == 'exclude-forms') {
|
||||
$s['include_pkmn_forms'] = false;
|
||||
}
|
||||
if ($arg == 'exclude-shiny') {
|
||||
$s['include_pkmn_shiny'] = false;
|
||||
}
|
||||
if ($arg == 'exclude-regular') {
|
||||
$s['include_pkmn_nonshiny'] = false;
|
||||
}
|
||||
if ($arg == 'exclude-pkmn') {
|
||||
$s['include_pkmn'] = false;
|
||||
}
|
||||
if ($arg == 'no-pngcrush') {
|
||||
$s['generate_optimized'] = false;
|
||||
}
|
||||
if ($arg == 'no-padding') {
|
||||
$s['pkmn_img_padding'] = 0;
|
||||
}
|
||||
if ($arg == 'generate-markdown') {
|
||||
$s['generate_markdown'] = true;
|
||||
}
|
||||
if ($arg == 'html-no-slugs') {
|
||||
$s['html_no_slugs'] = true;
|
||||
}
|
||||
if ($arg == 'include-right') {
|
||||
$val_int = intval($val);
|
||||
if (!is_numeric($val) || $val_int < 0 || $val_int > 2) {
|
||||
$argument_error = true;
|
||||
$error_id = 'arg_error_include_right';
|
||||
break;
|
||||
}
|
||||
$s['include_pkmn_right'] = $val_int;
|
||||
}
|
||||
if ($arg == 'icon-sets') {
|
||||
$val = trim(trim($val), ',');
|
||||
if ($val != '') {
|
||||
$val = explode(',', $val);
|
||||
}
|
||||
if (empty($val)) {
|
||||
$argument_error = true;
|
||||
$error_id = 'arg_error_icon_sets';
|
||||
break;
|
||||
}
|
||||
$s['etc_icon_sets'] = $val;
|
||||
}
|
||||
if ($arg == 'file-exts') {
|
||||
$val = explode(',', trim(trim($val), ','));
|
||||
if (empty($val)) {
|
||||
$argument_error = true;
|
||||
$error_id = 'arg_error_file_exts';
|
||||
break;
|
||||
}
|
||||
$s['file_exts'] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// When not adding Pokémon icons, exclude the special icons too.
|
||||
if ($s['include_pkmn'] === false) {
|
||||
$s['include_special_icons'] = false;
|
||||
}
|
||||
|
||||
// These are settings values that are directly replaced by the values
|
||||
// of the command-line arguments.
|
||||
$var_replacements = array(
|
||||
'path-pngcrush' => 'pngcrush_path',
|
||||
'tpl-html' => 'html_tpl',
|
||||
'tpl-scss' => 'scss_tpl',
|
||||
'dir-resources' => 'resources_dir',
|
||||
'file-output-html' => 'html_output',
|
||||
'file-output-md' => 'md_output',
|
||||
'file-output-scss' => 'scss_output',
|
||||
'file-output-img' => 'img_output',
|
||||
'file-output-img-tmp' => 'img_output_tmp',
|
||||
'dir-output' => 'dir_output',
|
||||
'file-data' => 'file_pkmn_data',
|
||||
'file-icons' => 'file_icon_data',
|
||||
'dir-data' => 'dir_data',
|
||||
'dir-pkmn' => 'dir_pkmn',
|
||||
'dir-icons' => 'dir_base',
|
||||
'pkmn-range' => 'pkmn_range',
|
||||
'icon-range' => 'icon_range',
|
||||
'pkmn-lang' => 'pkmn_language',
|
||||
'lang' => 'i18n_language',
|
||||
);
|
||||
foreach ($opts as $arg => $val) {
|
||||
if (in_array($arg, array_keys($var_replacements))) {
|
||||
$var = $var_replacements[$arg];
|
||||
$s[$var] = $val;
|
||||
}
|
||||
}
|
||||
// Check for the language setting: set the slug language to the
|
||||
// Pokémon name language by default. However, if romanized Japanese
|
||||
// names are requested (jpn_ro), the slug language should be jpn.
|
||||
if (isset($s['pkmn_language'])) {
|
||||
$s['pkmn_language_slugs'] = $s['pkmn_language'];
|
||||
}
|
||||
if ($s['pkmn_language'] == 'jpn_ro') {
|
||||
$s['pkmn_language_slugs'] = 'jpn';
|
||||
}
|
||||
|
||||
if ($argument_error == true) {
|
||||
$this->needs_usage = true;
|
||||
}
|
||||
|
||||
$this->opt_settings = $s;
|
||||
$this->argument_error = $argument_error;
|
||||
$this->error_id = $error_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of user-defined settings to override the
|
||||
* current settings with, based on passed command-line arguments.
|
||||
*
|
||||
* @return mixed[] Settings array populated by command-line arguments.
|
||||
*/
|
||||
public function get_user_settings()
|
||||
{
|
||||
if (empty($this->opt_settings)) {
|
||||
$this->parse_opts();
|
||||
}
|
||||
|
||||
return $this->opt_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the usage template prior to its decoration for proper display.
|
||||
*/
|
||||
private function trim_usage_tpl()
|
||||
{
|
||||
$this->tpl = "\n".trim($this->tpl)."\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the version number.
|
||||
*/
|
||||
public function display_version()
|
||||
{
|
||||
$usage_vars = array(
|
||||
'website' => Settings::get('website'),
|
||||
'revision' => Settings::get('revision'),
|
||||
'version' => Settings::get('version'),
|
||||
);
|
||||
$trmfrm = new TerminalFormatter();
|
||||
$this->render($usage_vars);
|
||||
$usage = $this->get_buffer();
|
||||
$usage = $trmfrm->format($usage);
|
||||
print($usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the program usage.
|
||||
*/
|
||||
public function display_usage()
|
||||
{
|
||||
$this->trim_usage_tpl();
|
||||
|
||||
// Retrieve the proper error string in case we've got an error.
|
||||
if ($this->argument_error) {
|
||||
$error_str = I18n::lf('arg_error_tpl',
|
||||
array(I18n::l($this->error_id))
|
||||
);
|
||||
}
|
||||
|
||||
$usage_vars = array(
|
||||
'website' => Settings::get('website'),
|
||||
'revision' => Settings::get('revision'),
|
||||
'version' => Settings::get('version'),
|
||||
'error' => $error_str,
|
||||
'copyright' => (
|
||||
Settings::get('copyright_str').
|
||||
"\n".Settings::get('copyright_gf')
|
||||
),
|
||||
);
|
||||
|
||||
// We'll replace variables and finally format the output
|
||||
// for use in a terminal.
|
||||
$trmfrm = new TerminalFormatter();
|
||||
$this->render($usage_vars);
|
||||
$usage = $this->get_buffer();
|
||||
$usage = $trmfrm->format($usage);
|
||||
print($usage);
|
||||
}
|
||||
}
|
||||
1577
package-lock.json
generated
1577
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -1,7 +1,19 @@
|
||||
{
|
||||
"name": "pokesprite-src",
|
||||
"version": "1.0.0",
|
||||
"description": "Pokésprite icon collection repository and database",
|
||||
"files": [
|
||||
"license.md",
|
||||
"package.json",
|
||||
"readme.md",
|
||||
"/icons",
|
||||
"/data"
|
||||
],
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"node-sass": "^4.6.0"
|
||||
}
|
||||
"keywords": ["Icons", "Sprites", "SCSS", "Pokémon", "NodeJS"],
|
||||
"author": "Michiel Sikma <michiel@sikma.org>",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
437
pokesprite.php
437
pokesprite.php
@@ -1,437 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
// PokéSprite
|
||||
// ----------
|
||||
// This simple script generates an image sprite containing small icons of
|
||||
// all Pokémon in the National Pokédex (along with several other types of
|
||||
// icons), and the pertaining SCSS and JS files. It was built for people
|
||||
// working on websites or online applications related to Pokémon. The main
|
||||
// Pokémon icons are arranged sequentially, and a growing packer algorithm
|
||||
// is used to arrange other images inside the sprite.
|
||||
//
|
||||
// Aside from the regular box sprites (which have been sourced from
|
||||
// Pokémon X/Y), this package includes unofficial custom designed shiny
|
||||
// versions of those sprites.
|
||||
//
|
||||
// The data for the Pokémon icons is taken from the `./data/pkmn.json` file.
|
||||
// The other icon sets have their data generated based on the directory
|
||||
// structure and file names.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// (C) 2014-2016 Michiel Sikma <michiel@sikma.org> and PokéSprite contributors
|
||||
//
|
||||
// For a full list of contributors, view the project commit history.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// All files in the `icons` directory are included in this package for reasons
|
||||
// of convenience and are (C) 1995-2014 Nintendo/Creatures Inc./GAME FREAK Inc.
|
||||
|
||||
namespace PkSpr;
|
||||
|
||||
error_reporting(0);
|
||||
|
||||
require_once 'includes/templateformatter.php';
|
||||
require_once 'includes/terminalformatter.php';
|
||||
require_once 'includes/settings.php';
|
||||
require_once 'includes/scaffolding.php';
|
||||
require_once 'includes/i18n.php';
|
||||
require_once 'includes/usage.php';
|
||||
require_once 'includes/iconstack.php';
|
||||
require_once 'includes/functions.php';
|
||||
require_once 'includes/iconoverview.php';
|
||||
require_once 'includes/iconstyler.php';
|
||||
require_once 'includes/iconjs.php';
|
||||
require_once 'includes/iconsprite.php';
|
||||
|
||||
// 1. Parsing of command line arguments and basic program feedback
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Load the default settings.
|
||||
Settings::load_settings_file('includes/defaults.php');
|
||||
|
||||
// Parse the user's command line arguments and determine whether the user
|
||||
// is in need of seeing the usage guide.
|
||||
$usage = new Usage();
|
||||
$cl_settings = $usage->get_user_settings();
|
||||
|
||||
// Check the current revision number for user feedback and for
|
||||
// inclusion in the output files.
|
||||
$revision = trim(shell_exec('git rev-list HEAD --count 2> /dev/null'));
|
||||
$revision = $revision ? 'r'.$revision : '[unknown]';
|
||||
$cl_settings['revision'] = $revision;
|
||||
|
||||
// Retrieve the version number from the pkg-info.json file.
|
||||
$pkg_info = json_decode(file_get_contents(Settings::get('resources_dir').'pkg-info.json'), true);
|
||||
$version = $pkg_info['version'];
|
||||
$cl_settings['version'] = $version;
|
||||
|
||||
// Merge the user's command line arguments into the settings.
|
||||
Settings::load_settings($cl_settings);
|
||||
|
||||
if ($usage->needs_version) {
|
||||
// Display version and exit.
|
||||
$usage->load_tpl_file(
|
||||
Settings::get('resources_dir').
|
||||
Settings::get('version_tpl')
|
||||
);
|
||||
$usage->display_version();
|
||||
exit;
|
||||
}
|
||||
if ($usage->needs_usage) {
|
||||
// Display usage and exit.
|
||||
$usage->load_tpl_file(
|
||||
Settings::get('resources_dir').
|
||||
Settings::get('usage_tpl')
|
||||
);
|
||||
$usage->display_usage();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Export the settings variables so that we can use them here.
|
||||
$vars = array_keys(Settings::$settings);
|
||||
foreach ($vars as $var) {
|
||||
$$var = Settings::get($var);
|
||||
}
|
||||
|
||||
// Set the default lines.
|
||||
I18n::set_language($i18n_language);
|
||||
I18n::set_default_lines();
|
||||
$termfrm = new TerminalFormatter();
|
||||
I18n::add_output_filter(array('PkSpr\TerminalFormatter', 'format'));
|
||||
|
||||
// Check if we have GD.
|
||||
if (!function_exists('imagecreatefrompng')) {
|
||||
print(I18n::l('gd_error'));
|
||||
die();
|
||||
}
|
||||
|
||||
// Print basic program info.
|
||||
print(I18n::lf('info', array(
|
||||
$title_str,
|
||||
$version,
|
||||
$revision,
|
||||
$website_txt,
|
||||
$copyright_gf
|
||||
)));
|
||||
$generated_on = I18n::lf('generated_on', array($script_date));
|
||||
|
||||
// Check if we're running via anything other than the command line.
|
||||
if (php_sapi_name() != 'cli') {
|
||||
print(I18n::l('no_cli'));
|
||||
}
|
||||
|
||||
// Check if pngcrush exists, in case we need it.
|
||||
if ($generate_optimized === true) {
|
||||
if (!is_file($pngcrush_path)) {
|
||||
print(I18n::lf('pngcrush_missing', array($pngcrush_path)));
|
||||
$generate_optimized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the output directory exist and create them if necessary.
|
||||
if (!is_dir($dir_output)) {
|
||||
print(I18n::l('dir_create'));
|
||||
if (!mkdir($dir_output, $dir_mode, true)) {
|
||||
print(I18n::l('dir_error'));
|
||||
die();
|
||||
}
|
||||
print(I18n::l('dir_success'));
|
||||
}
|
||||
|
||||
// Print a quick overview of what we'll be doing.
|
||||
print(I18n::l('tasks_overview'));
|
||||
if ($include_pkmn) {
|
||||
print(I18n::lf('task_pkmn', array(
|
||||
$include_pkmn ? 'true' : 'false',
|
||||
$include_pkmn_nonshiny ? 'true' : 'false',
|
||||
$include_pkmn_shiny ? 'true' : 'false',
|
||||
$include_pkmn_forms ? 'true' : 'false',
|
||||
$include_pkmn_right,
|
||||
$pkmn_language
|
||||
)));
|
||||
}
|
||||
if ($include_icon_sets) {
|
||||
print(I18n::l('task_icon_sets'));
|
||||
}
|
||||
if ($generate_optimized) {
|
||||
print(I18n::l('task_optimize'));
|
||||
}
|
||||
print(I18n::l('task_html'));
|
||||
if ($generate_markdown) {
|
||||
print(I18n::l('task_markdown'));
|
||||
}
|
||||
print(I18n::l('task_scss'));
|
||||
print(I18n::l('task_js'));
|
||||
|
||||
// 2. Pokémon data parsing and icon stack generation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
$icon_stack = new IconStack();
|
||||
|
||||
// Retrieve Pokémon name and idx information from the data file.
|
||||
if ($include_pkmn) {
|
||||
$icon_stack->parse_data_file($dir_data.$file_pkmn_data, $pkmn_range);
|
||||
$pkmn_data = $icon_stack->get_pkmn_data();
|
||||
|
||||
// Check if the data is there.
|
||||
$has_data = $icon_stack->has_pkmn_data();
|
||||
$has_imgs = $icon_stack->has_pkmn_images();
|
||||
|
||||
if (!$has_data) {
|
||||
print(I18n::lf('no_data', array($file_pkmn_data, $dir_data)));
|
||||
die();
|
||||
}
|
||||
if (!$has_imgs) {
|
||||
print(I18n::l('no_images'));
|
||||
die();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If we aren't including Pokémon, keep an empty array
|
||||
// to avoid iteration warnings.
|
||||
$pkmn_data = array();
|
||||
}
|
||||
|
||||
// Retrieve icons from the set.
|
||||
if ($include_icon_sets) {
|
||||
$icon_stack->parse_icons_data_file($dir_data.$file_icon_data, $icon_range);
|
||||
$icon_data = $icon_stack->get_icon_data();
|
||||
|
||||
// Check if the data is there.
|
||||
$has_data = $icon_stack->has_icon_data();
|
||||
$has_imgs = $icon_stack->has_icon_images();
|
||||
|
||||
if (!$has_data) {
|
||||
print(I18n::lf('no_icons_data', array($file_icon_data, $dir_data)));
|
||||
die();
|
||||
}
|
||||
if (!$has_imgs) {
|
||||
print(I18n::l('no_icon_images'));
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
// Generate and return the entire Pokémon icon stack.
|
||||
$pkmn_icons = $icon_stack->get_pkmn_icon_stack();
|
||||
$pkmn_std_icons = $icon_stack->get_pkmn_std_icons();
|
||||
|
||||
// Get the total size of the Pokémon icons. We'll position the rest of the
|
||||
// images using the same width, and an arbitrary height.
|
||||
$pkmn_sect_fit = $icon_stack->get_pkmn_icon_stack_size();
|
||||
|
||||
// We'll keep images other than Pokémon icons inside of a separate array.
|
||||
// Position them using a binary tree packing algorithm.
|
||||
$etc_icons = $icon_stack->get_etc_icon_stack();
|
||||
$etc_sets = $icon_stack->get_etc_icon_sets();
|
||||
$etc_sect_fit = $icon_stack->get_etc_icon_stack_size();
|
||||
|
||||
// Full sprite attributes
|
||||
$stack_size = $icon_stack->get_combined_stack_size();
|
||||
$sprite_width = $stack_size['w'];
|
||||
$sprite_height = $stack_size['h'];
|
||||
|
||||
// Now we'll generate the sprite sheet.
|
||||
// About how much memory will this use?
|
||||
$mb_estimate = format_bytes($sprite_width * $sprite_height * 32);
|
||||
print(I18n::lf('sprite_stats', array(
|
||||
$sprite_width,
|
||||
$sprite_height,
|
||||
count($etc_icons) + count($pkmn_icons),
|
||||
$mb_estimate,
|
||||
)));
|
||||
|
||||
// 3. Generation of the icon sprite
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
$sprite_sections = array(
|
||||
'pkmn' => $pkmn_sect_fit['h'],
|
||||
'etc' => $etc_sect_fit['h'],
|
||||
);
|
||||
$icon_sprite = new IconSprite(
|
||||
$sprite_width,
|
||||
$sprite_height,
|
||||
$sprite_sections,
|
||||
$debug_img_inclusion
|
||||
);
|
||||
// Pass on data on which icons are the standard variants.
|
||||
$icon_sprite->set_pkmn_std_icons($pkmn_std_icons);
|
||||
|
||||
// Array of both the Pokémon icons and the other icons.
|
||||
$all_icons = $icon_stack->get_all_icons();
|
||||
|
||||
// For the sprite image itself, iterate over all icons and add them.
|
||||
$added = 0;
|
||||
$total = count($all_icons);
|
||||
for ($a = 0; $a < count($all_icons); ++$a) {
|
||||
// IconSprite returns true if successful, false if the image
|
||||
// could not be used somehow.
|
||||
$icon = $all_icons[$a];
|
||||
if ($icon_sprite->add($icon)) {
|
||||
$added += 1;
|
||||
}
|
||||
}
|
||||
print(I18n::lf('icons_added', array($added)));
|
||||
|
||||
// Send some feedback in case we couldn't add all icons.
|
||||
if (($added - $total) > 0) {
|
||||
if ($debug_img_inclusion) {
|
||||
print(I18n::lf('icons_skipped', array($added - $total)));
|
||||
}
|
||||
else {
|
||||
print(I18n::lf('icons_skipped_hint', array($added - $total)));
|
||||
}
|
||||
}
|
||||
|
||||
print(I18n::l('sprite_ready'));
|
||||
print(I18n::lf('sprite_saving', array(
|
||||
$generate_optimized ? $dir_output.$img_output_tmp : $dir_output.$img_output,
|
||||
)));
|
||||
|
||||
// Save the initial result to output directory.
|
||||
if (file_exists($dir_output.$img_output_tmp)) {
|
||||
unlink($dir_output.$img_output_tmp);
|
||||
}
|
||||
$icon_sprite->output($dir_output.$img_output_tmp, $generate_optimized !== true);
|
||||
$icon_sprite->destroy();
|
||||
|
||||
// Use pngcrush to minimize the image.
|
||||
if ($generate_optimized === true) {
|
||||
print(I18n::l('pngcrush_start'));
|
||||
if (file_exists($dir_output.$img_output)) {
|
||||
unlink($dir_output.$img_output);
|
||||
}
|
||||
$crush_cmd = $pngcrush_path.' -l 9 -q -text b author "Pokémon Sprite Generator v'.$version.' r'.$revision.'" -text b copyright "'.$copyright_gf.'" '.$dir_output.$img_output_tmp.' '.$dir_output.$img_output;
|
||||
exec($crush_cmd);
|
||||
|
||||
if (file_exists($dir_output.$img_output)) {
|
||||
// Seems like pngcrush was successful. Let's review the results.
|
||||
$size_before = filesize($dir_output.$img_output_tmp);
|
||||
$size_after = filesize($dir_output.$img_output);
|
||||
print(I18n::lf('pngcrush_success', array(
|
||||
format_bytes($size_before),
|
||||
format_bytes($size_after),
|
||||
)));
|
||||
// Delete the unoptimized image.
|
||||
print(I18n::l('sprite_del_old'));
|
||||
unlink($dir_output.$img_output_tmp);
|
||||
}
|
||||
else {
|
||||
// We couldn't use pngcrush for some reason.
|
||||
print(I18n::l('pngcrush_error'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If we're not using pngcrush, just rename it to the final filename.
|
||||
rename($dir_output.$img_output_tmp, $dir_output.$img_output);
|
||||
}
|
||||
|
||||
// 4. Generation of the HTML, SCSS and JS files pertaining to the sprites
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// We're going to be making a map of positioning values, styling information
|
||||
// as well as an HTML overview of every icon.
|
||||
$icon_overview = new IconOverview();
|
||||
$icon_styler = new IconStyler();
|
||||
$icon_js = new IconJS();
|
||||
|
||||
// Create a tree structure of our icon sets based on their subtype information.
|
||||
// This will be given to the SCSS, JS and overview generators.
|
||||
$icon_tree = $icon_stack->get_icon_type_tree();
|
||||
$set_sizes = $icon_stack->get_set_sizes();
|
||||
|
||||
$icon_overview->set_icon_list($all_icons);
|
||||
$icon_styler->set_icon_list($all_icons);
|
||||
$icon_styler->set_icon_sizes($set_sizes);
|
||||
$icon_js->set_sprite_sections($sprite_sections);
|
||||
$icon_js->set_icon_tree($icon_tree);
|
||||
$icon_js->set_icon_sizes($set_sizes);
|
||||
|
||||
// For the generation of the HTML, SCSS and JS files, a number of
|
||||
// base variables are used.
|
||||
$base_vars = array(
|
||||
'title_str' => $title_str,
|
||||
'revision' => $revision,
|
||||
'version' => $version,
|
||||
'website_txt' => $website_txt,
|
||||
'copyright_str' => $copyright_str,
|
||||
'copyright_gf' => $copyright_gf,
|
||||
'copyright_contrib_notice' => $copyright_contrib_notice,
|
||||
'generated_on' => $generated_on,
|
||||
'css_base_selector' => $css_base_selector,
|
||||
);
|
||||
|
||||
// Generate the HTML overview of all icons we've just added.
|
||||
print(I18n::l('html_generating'));
|
||||
$icon_overview->register_vars($base_vars);
|
||||
$icon_overview->register_tpl($resources_dir.$html_tpl);
|
||||
$overview = $icon_overview->get_overview('html');
|
||||
if (file_exists($dir_output.$html_output)) {
|
||||
unlink($dir_output.$html_output);
|
||||
}
|
||||
file_put_contents($dir_output.$html_output, $overview);
|
||||
|
||||
// If requested, generate a Markdown overview too.
|
||||
if ($generate_markdown) {
|
||||
print(I18n::l('markdown_generating'));
|
||||
$overview_md = $icon_overview->get_overview('markdown');
|
||||
if (file_exists($dir_output.$md_output)) {
|
||||
unlink($dir_output.$md_output);
|
||||
}
|
||||
file_put_contents($dir_output.$md_output, $overview_md);
|
||||
}
|
||||
|
||||
// Generate a page about the build too.
|
||||
$icon_overview->register_tpl($resources_dir.$html_build_tpl);
|
||||
$overview = $icon_overview->get_build_overview('html');
|
||||
if (file_exists($dir_output.$html_build_output)) {
|
||||
unlink($dir_output.$html_build_output);
|
||||
}
|
||||
file_put_contents($dir_output.$html_build_output, $overview);
|
||||
|
||||
// With the image and the overview done, let's generate the SCSS.
|
||||
print(I18n::l('scss_generating'));
|
||||
$icon_styler->register_vars($base_vars);
|
||||
$icon_styler->register_tpl($resources_dir.$scss_tpl);
|
||||
$scss = $icon_styler->get_scss();
|
||||
if (file_exists($dir_output.$scss_output)) {
|
||||
unlink($dir_output.$scss_output);
|
||||
}
|
||||
file_put_contents($dir_output.$scss_output, $scss);
|
||||
|
||||
// Finally, the JS.
|
||||
print(I18n::l('js_generating'));
|
||||
$icon_js->register_vars($base_vars);
|
||||
$icon_js->register_tpl($resources_dir.$js_tpl);
|
||||
$js = $icon_js->get_js();
|
||||
if (file_exists($dir_output.$js_output)) {
|
||||
unlink($dir_output.$js_output);
|
||||
}
|
||||
file_put_contents($dir_output.$js_output, $js);
|
||||
|
||||
// All done!
|
||||
print(I18n::l('all_done'));
|
||||
exit;
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
@@ -1,56 +0,0 @@
|
||||
PokéSprite
|
||||
==========
|
||||
|
||||
This is the Node module version of [PokéSprite](https://github.com/msikma/pokesprite).
|
||||
|
||||
See [the documentation](http://msikma.github.io/pokesprite/) for a full icon overview.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
TODO
|
||||
|
||||
```js
|
||||
var PkSpr = require('pokesprite').PkSpr;
|
||||
var icon = PkSpr.decorate({slug: "pikachu"}); // see docs for more attributes
|
||||
|
||||
console.log(icon);
|
||||
|
||||
/*
|
||||
{ request: { slug: 'pikachu' },
|
||||
attributes:
|
||||
{ type: 'pkmn',
|
||||
slug: 'pikachu',
|
||||
color: null,
|
||||
form: null,
|
||||
gender: null,
|
||||
dir: null },
|
||||
exactMatch: true,
|
||||
found: true,
|
||||
data: { coords: { x: 1, y: 63 }, props: { flipped: false } },
|
||||
size: { w: 40, h: 30 } }
|
||||
*/
|
||||
```
|
||||
|
||||
With this information, you can construct a DOM node that displays the icon. `coords` is the x and y starting positions of the icon in the image, so you should set `background-position` to *minus* those values. If `flipped` is `true`, you should display the node horizontally mirrored (this is true if `dir` is set to `right` and the icon does not have a unique right-facing sprite).
|
||||
|
||||
If an icon could not be found, `found` will be `false`. If an icon was found, but it isn't precisely the one you requested, `exactMatch` will be `false`. For example, this happens if you request `gender: 'female'` for a Pokémon that doesn't have a separate icon.
|
||||
|
||||
### ES6
|
||||
|
||||
To import in ES6:
|
||||
|
||||
```js
|
||||
import { PkSpr } from 'pokesprite';
|
||||
```
|
||||
|
||||
### AMD
|
||||
|
||||
It should also work with AMD syntax, but I haven't tested this.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The source icons are © Nintendo/Creatures Inc./GAME FREAK Inc.
|
||||
|
||||
Everything else, and usage of the programming code, is governed by the [MIT license](http://opensource.org/licenses/MIT).
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "pokesprite",
|
||||
"description": "Pokémon icon database and sprite sheet",
|
||||
"version": "1.6.0",
|
||||
"main" : "pokesprite.min.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/msikma/pokesprite.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/msikma/pokesprite/issues"
|
||||
},
|
||||
"author": "Michiel Sikma <michiel@sikma.org>",
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -1,795 +0,0 @@
|
||||
/** @preserve
|
||||
* {{$title_str}} v{{$version}} ({{$revision}}) {{$website_txt}}
|
||||
* {{$copyright_str}}
|
||||
* {{$copyright_gf}}
|
||||
* {{$copyright_contrib_notice}}
|
||||
* {{$generated_on}}
|
||||
*
|
||||
*/
|
||||
(function (global, factory) {
|
||||
if (typeof module === "object" && typeof module.exports === "object") {
|
||||
if (global.document) {
|
||||
module.exports = factory(global, true);
|
||||
}
|
||||
else {
|
||||
module.exports = function (w) {
|
||||
if (!w.document) {
|
||||
throw new Error("PokéSprite requires a window with a document");
|
||||
}
|
||||
return factory(w);
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
factory(global);
|
||||
}
|
||||
}(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
|
||||
|
||||
// Extends polyfill.
|
||||
var _extends = Object.assign || function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
// PokéSprite code starts here.
|
||||
var PkSpr = {
|
||||
};
|
||||
/**
|
||||
* Base CSS class that identifies an element as ours.
|
||||
*
|
||||
* @const
|
||||
* @type {!string}
|
||||
*/
|
||||
PkSpr.PKSPR_BASE_CLASS = "{{$css_base_selector}}";
|
||||
|
||||
/**
|
||||
* List of types and their sizes.
|
||||
*
|
||||
* @const
|
||||
* @type {!Object}
|
||||
*/
|
||||
PkSpr.PKSPR_TYPES = {{$sizes_json}};
|
||||
|
||||
/**
|
||||
* Coordinate and size data for every single icon. Size data is
|
||||
* not included if the type's size can already be found
|
||||
* in the PKSPR_TYPES constant.
|
||||
*
|
||||
* @const
|
||||
* @type {!Object}
|
||||
*/
|
||||
PkSpr.PKSPR_DATA = {{$coords_json}};
|
||||
|
||||
/**
|
||||
* Index linking Pokédex numbers to slugs. Generated on runtime.
|
||||
*
|
||||
* @type {?Object}
|
||||
*/
|
||||
var pkmn_idx_to_slug;
|
||||
|
||||
/**
|
||||
* Regular Expression used to check whether an identifier
|
||||
* is a valid dex number.
|
||||
*
|
||||
* @type {?RegExp}
|
||||
*/
|
||||
var numeric_regexp;
|
||||
|
||||
/**
|
||||
* Schedules the DOM to be processed completely as soon as it's ready.
|
||||
*/
|
||||
PkSpr["process_dom"] = function()
|
||||
{
|
||||
PkSpr.content_loaded(window, PkSpr.process_container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates a list of objects.
|
||||
*
|
||||
* This is to be called by the user in case they want to decorate
|
||||
* specific items without having the script scan the DOM.
|
||||
*
|
||||
* The argument must either be an ID string (in which case the node
|
||||
* is fetched using document.getElementById()), or a node, or
|
||||
* an array of ID strings, or an array of nodes.
|
||||
*
|
||||
* @param {(string|Element|Array.<string, Element>)} val Item or items to be decorated.
|
||||
* @return {?object} An object, if we received an object.
|
||||
*/
|
||||
PkSpr["decorate"] = function(val)
|
||||
{
|
||||
// If we've received an object, return an object with the information
|
||||
// necessary to construct a DOM object of an icon manually.
|
||||
if (PkSpr.is_object(val)) {
|
||||
return PkSpr.decorate_object(val);
|
||||
}
|
||||
// Determine what the user passed.
|
||||
var is_arr = PkSpr.is_array(val);
|
||||
// If it's not an array, turn it into one so we can iterate over it.
|
||||
if (is_arr === false) {
|
||||
val = [val];
|
||||
}
|
||||
|
||||
var a, z;
|
||||
var obj, node, is_str, is_node;
|
||||
for (a = 0, z = val.length; a < z; ++a) {
|
||||
obj = val[a];
|
||||
is_str = typeof obj === "string" || obj instanceof String;
|
||||
is_node = obj.nodeName !== null;
|
||||
|
||||
// Fetch the object by its ID if necessary.
|
||||
if (is_str) {
|
||||
node = document.getElementById(obj);
|
||||
}
|
||||
else {
|
||||
node = obj;
|
||||
}
|
||||
|
||||
// We either have a parent object that contains icons,
|
||||
// or an icon itself.
|
||||
if (PkSpr.has_class(node, PkSpr.PKSPR_BASE_CLASS)) {
|
||||
// It's an icon.
|
||||
PkSpr.decorate_node(node);
|
||||
}
|
||||
else {
|
||||
// It's a parent object.
|
||||
PkSpr.process_container(null, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a message in the console in case of decoration failure.
|
||||
*
|
||||
* @param {Object} attrs The icon attributes.
|
||||
*/
|
||||
PkSpr.decoration_error = function(attrs)
|
||||
{
|
||||
window.console && console.warn("Couldn't decorate icon with the "+
|
||||
"following properties: %o", attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the computed icon attributes match
|
||||
* the user's requested attributes.
|
||||
*
|
||||
* @param {Object} attrs User attributes
|
||||
* @param {Object} missing Computed values (missing in the data)
|
||||
* @return {Object} Whether we have an exact match and the changed values
|
||||
*/
|
||||
PkSpr.check_exact_match = function(attrs, missing)
|
||||
{
|
||||
var exactMatch = true;
|
||||
var changedValues = {};
|
||||
for (var defaultVal in attrs) {
|
||||
if (!attrs.hasOwnProperty(defaultVal) || attrs[defaultVal] == null) {
|
||||
continue;
|
||||
}
|
||||
for (var finalVal in missing) {
|
||||
if (!missing.hasOwnProperty(finalVal) || defaultVal !== finalVal) {
|
||||
continue;
|
||||
}
|
||||
if (attrs[defaultVal] !== missing[finalVal]) {
|
||||
exactMatch = false;
|
||||
changedValues[finalVal] = missing[finalVal];
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
"exact": exactMatch,
|
||||
"changedValues": changedValues
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates an object. See decorate_node() for details.
|
||||
*
|
||||
* @param {Object} info Our settings, e.g. name, direction, gender...
|
||||
* @return {Object} Necessary information needed to display the icon.
|
||||
*/
|
||||
PkSpr.decorate_object = function(info)
|
||||
{
|
||||
var defaults = {
|
||||
"type": "pkmn",
|
||||
"slug": null,
|
||||
"color": null,
|
||||
"form": null,
|
||||
"gender": null,
|
||||
"dir": null
|
||||
};
|
||||
var attrs = _extends(defaults, info);
|
||||
var size = PkSpr.get_type_size(attrs.type);
|
||||
var data = PkSpr.get_icon_data(attrs);
|
||||
|
||||
// Check if we have an exact match or not.
|
||||
var match = PkSpr.check_exact_match(attrs, data["missing"]);
|
||||
attrs = _extends(attrs, match["changedValues"]);
|
||||
|
||||
var custom_size = size == null || size["w"] == null;
|
||||
if (data["coords"] == null) {
|
||||
return {
|
||||
"request": info,
|
||||
"attributes": attrs,
|
||||
"exactMatch": null,
|
||||
"found": false,
|
||||
"data": null,
|
||||
"size": null
|
||||
};
|
||||
}
|
||||
if (custom_size) {
|
||||
size = {"w": data["coords"]["w"], "h": data["coords"]["h"]};
|
||||
}
|
||||
delete data["missing"];
|
||||
return {
|
||||
"request": info,
|
||||
"attributes": attrs,
|
||||
"exactMatch": match["exact"],
|
||||
"found": true,
|
||||
"data": data,
|
||||
"size": size
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates a single node
|
||||
*
|
||||
* @param {Element} node The node to be decorated.
|
||||
* @return {boolean} Whether decoration was successful.
|
||||
*/
|
||||
PkSpr.decorate_node = function(node)
|
||||
{
|
||||
// Check to make sure it hasn't been decorated before.
|
||||
if (PkSpr.is_decorated(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the node's base attributes.
|
||||
var attrs = PkSpr.get_node_attrs(node);
|
||||
var size = PkSpr.get_type_size(attrs.type);
|
||||
var data = PkSpr.get_icon_data(attrs);
|
||||
var coords = data["coords"];
|
||||
var props = data["props"];
|
||||
|
||||
// If we were not able to gauge its size from the type,
|
||||
// that means this icon's size is stored alongside
|
||||
// the coordinate data.
|
||||
var custom_size = size == null || size["x"] == null;
|
||||
|
||||
// Check whether this node's icon really exists.
|
||||
if (coords == null) {
|
||||
// If not, error out.
|
||||
PkSpr.decoration_error(attrs);
|
||||
return false;
|
||||
}
|
||||
if (custom_size) {
|
||||
size = {"w": coords["w"], "h": coords["h"]};
|
||||
}
|
||||
|
||||
// Create the inner element that is the icon itself.
|
||||
var inner = PkSpr.create_inner_node(node);
|
||||
// Set background coordinates.
|
||||
PkSpr.set_icon_coords(inner, coords);
|
||||
// Set the size, if we're dealing with a custom sized icon.
|
||||
if (custom_size) {
|
||||
PkSpr.set_icon_size(node, inner, size);
|
||||
}
|
||||
// Flip the icon if we're showing a faux right-facing icon.
|
||||
if (props["flipped"]) {
|
||||
PkSpr.set_icon_direction(node, "right");
|
||||
}
|
||||
|
||||
// Indicate that this node has been decorated so we don't
|
||||
// accidentally decorate it twice.
|
||||
PkSpr.set_decorated(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a class to the icon signifying it is to be mirrored in CSS.
|
||||
*
|
||||
* @param {Element} node The icon node.
|
||||
* @param {string} dir Direction the icon should face.
|
||||
*/
|
||||
PkSpr.set_icon_direction = function(node, dir)
|
||||
{
|
||||
PkSpr.add_class(node, "{{$var_base_name}}-faux-"+dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the inner node, which is an extra child element inside the
|
||||
* icon node that contains the actual icon itself.
|
||||
*
|
||||
* @param {Element} node The icon node.
|
||||
* @return {Element} The newly created inner node.
|
||||
*/
|
||||
PkSpr.create_inner_node = function(node)
|
||||
{
|
||||
var inner = document.createElement("i");
|
||||
node.appendChild(inner);
|
||||
return inner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background-position value of an icon.
|
||||
*
|
||||
* @param {Element} inner The inner node (<i> element of the icon object).
|
||||
* @param {!Object} coords The coordinates.
|
||||
*/
|
||||
PkSpr.set_icon_coords = function(inner, coords)
|
||||
{
|
||||
inner.style.backgroundPosition = (-coords["x"])+"px "+(-coords["y"])+"px";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size value of an icon.
|
||||
*
|
||||
* @param {Element} node The outer node.
|
||||
* @param {Element} inner The inner node (<i> element of the icon object).
|
||||
* @param {Object} size The size.
|
||||
*/
|
||||
PkSpr.set_icon_size = function(node, inner, size)
|
||||
{
|
||||
node.style.width = (size.w)+"px";
|
||||
node.style.height = (size.h)+"px";
|
||||
inner.style.width = (size.w)+"px";
|
||||
inner.style.height = (size.h)+"px";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and other properties for the icon.
|
||||
*
|
||||
* @param {Object} attrs The icon's list of attributes.
|
||||
* @return {?Object} The icon's coordinates and properties.
|
||||
*/
|
||||
PkSpr.get_icon_data = function(attrs)
|
||||
{
|
||||
var tree = PkSpr.PKSPR_DATA;
|
||||
var branch;
|
||||
|
||||
// The following list contains fallbacks. If a certain form
|
||||
// or variation is not found in the coordinates list, it will
|
||||
// either fall back to something from this list, or return an error.
|
||||
var attr, val, fbval;
|
||||
var fallbacks = {
|
||||
"type": null,
|
||||
"slug": null,
|
||||
"form": ".",
|
||||
"dir": null,
|
||||
"gender": ".",
|
||||
"color": "{{$fallback_color}}"
|
||||
};
|
||||
var props = {
|
||||
"flipped": false
|
||||
};
|
||||
// Attributes that the user requested but couldn't be found in the data.
|
||||
var missing = {
|
||||
};
|
||||
|
||||
for (attr in fallbacks) {
|
||||
if (!fallbacks.hasOwnProperty(attr)) {
|
||||
continue;
|
||||
}
|
||||
// Check if we've reached an end node and quit iterating if so.
|
||||
if (tree.x >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
val = attrs[attr];
|
||||
fbval = fallbacks[attr];
|
||||
|
||||
// If the value exists in the tree, continue via that branch.
|
||||
if (branch = tree[val]) {
|
||||
tree = branch;
|
||||
continue;
|
||||
}
|
||||
// If not, continue via the fallback value.
|
||||
else
|
||||
if (branch = tree[fbval]) {
|
||||
missing[attr] = fbval;
|
||||
tree = branch;
|
||||
// If we're reverting from a non-existent right-facing icon,
|
||||
// keep note that this icon should be flipped later.
|
||||
if (attr === "dir" && val === "right") {
|
||||
props["flipped"] = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// If the fallback value doesn't exist, and we're in "dir",
|
||||
// continue with "gender" instead. These two share the same node.
|
||||
else if (attr === "dir") {
|
||||
continue;
|
||||
}
|
||||
// If the fallback value doesn't exist, and we're in "gender",
|
||||
// just skip to the next one. It means we are in a right-facing icon.
|
||||
else if (attr === "gender") {
|
||||
continue;
|
||||
}
|
||||
// In all other cases, error out. We don't have the icon.
|
||||
else {
|
||||
tree = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all went well, we'll have the coordinates and other properties.
|
||||
return {
|
||||
"coords": tree,
|
||||
"props": props,
|
||||
"missing": missing
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the icon type.
|
||||
*
|
||||
* @param {string} type The type to retrieve information from.
|
||||
* @return {?Object} The type's information.
|
||||
*/
|
||||
PkSpr.get_type_size = function(type)
|
||||
{
|
||||
var spr_type;
|
||||
for (spr_type in PkSpr.PKSPR_TYPES) {
|
||||
if (!PkSpr.PKSPR_TYPES.hasOwnProperty(spr_type)) {
|
||||
continue;
|
||||
}
|
||||
if (spr_type === type) {
|
||||
return PkSpr.PKSPR_TYPES[spr_type];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves icon type information from a node's class.
|
||||
*
|
||||
* @param {Element} node The node to be scanned.
|
||||
* @return {?Object} The node's information.
|
||||
*/
|
||||
PkSpr.get_node_attrs = function(node)
|
||||
{
|
||||
// The node's class.
|
||||
var node_class = node.className;
|
||||
if (node_class == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var node_attrs = {
|
||||
"type": null, // e.g. pkmn
|
||||
"slug": null, // e.g. unown
|
||||
"color": null, // regular or shiny
|
||||
"form": null, // e.g. defense, a, exclamation, orange
|
||||
"gender": null, // male, female or genderless
|
||||
"dir": null // left or right
|
||||
};
|
||||
|
||||
// Aside from these basic variables, we'll also scan for
|
||||
// every known icon type. We'll register the type and
|
||||
// redirect the values to the appropriate keys.
|
||||
var spr_type;
|
||||
for (spr_type in PkSpr.PKSPR_TYPES) {
|
||||
if (!PkSpr.PKSPR_TYPES.hasOwnProperty(spr_type)) {
|
||||
continue;
|
||||
}
|
||||
// The key goes to "type", the value to "slug".
|
||||
// e.g. pkmn-caterpie yields type: pkmn, slug: caterpie.
|
||||
node_attrs[spr_type] = {"k": "type", "v": "slug"};
|
||||
}
|
||||
|
||||
var a, z;
|
||||
var var_idx, var_mapping, var_key, var_val;
|
||||
var bit, bits = node_class.split(" ");
|
||||
for (a = 0, z = bits.length; a < z; ++a) {
|
||||
bit = bits[a];
|
||||
// Iterate over all recognized variable types.
|
||||
for (var_key in node_attrs) {
|
||||
if (!node_attrs.hasOwnProperty(var_key)) {
|
||||
continue;
|
||||
}
|
||||
var_mapping = node_attrs[var_key];
|
||||
var_idx = bit.indexOf(var_key+"-");
|
||||
if (var_idx === 0) {
|
||||
var_val = bit.substring(var_key.length + 1);
|
||||
|
||||
if (var_mapping === null) {
|
||||
// Color, form, gender and dir are saved to
|
||||
// the node_attrs variable directly.
|
||||
node_attrs[var_key] = var_val;
|
||||
}
|
||||
else {
|
||||
node_attrs[var_mapping["k"]] = var_key;
|
||||
node_attrs[var_mapping["v"]] = var_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if this is a Pokémon icon that uses the number
|
||||
// as the identifier rather than the slug.
|
||||
if (node_attrs.type === "pkmn"
|
||||
&& PkSpr.is_numeric_pkmn(node_attrs["slug"])) {
|
||||
// Replace the index number with the slug.
|
||||
node_attrs["slug"] = pkmn_idx_to_slug[node_attrs["slug"]];
|
||||
}
|
||||
|
||||
// Clean the output up a bit.
|
||||
for (spr_type in PkSpr.PKSPR_TYPES) {
|
||||
if (!PkSpr.PKSPR_TYPES.hasOwnProperty(spr_type)) {
|
||||
continue;
|
||||
}
|
||||
delete node_attrs[spr_type];
|
||||
}
|
||||
|
||||
return node_attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a regular expression for use by PkSpr.is_numeric_pkmn().
|
||||
*/
|
||||
PkSpr.prepare_numeric_check = function()
|
||||
{
|
||||
if (numeric_regexp != undefined) {
|
||||
return;
|
||||
}
|
||||
// 000 is always false.
|
||||
numeric_regexp = new RegExp(/(?!000)^[0-9]{3}$/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of Pokédex numbers linked to their respective slugs.
|
||||
*/
|
||||
PkSpr.generate_idx_list = function()
|
||||
{
|
||||
var a, z, pkmn;
|
||||
|
||||
if (pkmn_idx_to_slug != undefined) {
|
||||
return;
|
||||
}
|
||||
pkmn_idx_to_slug = {};
|
||||
|
||||
// In case we don't have any Pokémon icons in this compile.
|
||||
if (PkSpr.PKSPR_DATA == null
|
||||
|| PkSpr.PKSPR_DATA["pkmn"] == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
pkmn = Object.keys(PkSpr.PKSPR_DATA["pkmn"]);
|
||||
for (a = 1, z = pkmn.length; a <= z; ++a) {
|
||||
// Fast zero-padding hardcoded to work for 3 digits.
|
||||
pkmn_idx_to_slug[("000"+a).slice(-3)] = pkmn[a - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a Pokémon identifier is a dex number or not.
|
||||
*
|
||||
* @param {?string} pkmn The Pokémon identifier (slug or ID).
|
||||
* @return {boolean} Whether it is or isn't a numeric identifier.
|
||||
*/
|
||||
PkSpr.is_numeric_pkmn = function(pkmn)
|
||||
{
|
||||
return numeric_regexp.test(pkmn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether something is an array.
|
||||
*
|
||||
* @param {?} something The object.
|
||||
* @return {boolean} Whether the object is an array.
|
||||
*/
|
||||
PkSpr.is_array = function(something)
|
||||
{
|
||||
return toString.call(something) === "[object Array]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether something is an associative array.
|
||||
*
|
||||
* @param {?} something The object.
|
||||
* @return {boolean} Whether the object is an associative array, e.g. {}.
|
||||
*/
|
||||
PkSpr.is_object = function(something)
|
||||
{
|
||||
return Object.prototype.toString.call(something) === "[object Object]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates all icons found in the parent object.
|
||||
*
|
||||
* If decorating the entire DOM (document as parent object),
|
||||
* this function should be run as a callback from PkSpr.content_loaded().
|
||||
*
|
||||
* @param {*} caller Calling object (if callback).
|
||||
* @param {HTMLDocument|Element} parent Parent object.
|
||||
*/
|
||||
PkSpr.process_container = function(caller, parent)
|
||||
{
|
||||
if (parent == null) {
|
||||
parent = document;
|
||||
}
|
||||
|
||||
var a;
|
||||
var elements = PkSpr.get_icon_elements(parent);
|
||||
for (a = 0; a < elements.length; ++a) {
|
||||
PkSpr.decorate_node(elements[a]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all elements in the DOM that can be decorated.
|
||||
*
|
||||
* @param {HTMLDocument|Element} parent The parent element to search in.
|
||||
*/
|
||||
PkSpr.get_icon_elements = function(parent)
|
||||
{
|
||||
if (parent == null) {
|
||||
parent = document;
|
||||
}
|
||||
|
||||
// We'll attempt to use document.querySelectorAll() first.
|
||||
// If it's not available, we'll do our own check.
|
||||
try {
|
||||
return parent.querySelectorAll(
|
||||
"span."+PkSpr.PKSPR_BASE_CLASS+","+
|
||||
"div."+PkSpr.PKSPR_BASE_CLASS
|
||||
);
|
||||
}
|
||||
catch(e) {}
|
||||
|
||||
// Can't use document.querySelectorAll(), so we'll do this
|
||||
// the hard way. Grab all elements of those types and check for the
|
||||
// base identifier class.
|
||||
var a, b;
|
||||
var result, results, elements = [];
|
||||
var types = ["span", "div"];
|
||||
for (a = 0; a < types.length; ++a) {
|
||||
results = parent.getElementsByTagName(types[a]);
|
||||
for (b = 0; b < results.length; ++b) {
|
||||
result = results[b];
|
||||
if (PkSpr.has_class(result, PkSpr.PKSPR_BASE_CLASS)) {
|
||||
elements.push(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an DOM element has already been decorated before.
|
||||
*
|
||||
* @param {Element} element The element to check.
|
||||
* @return {boolean} Whether the element has been decorated.
|
||||
*/
|
||||
PkSpr.is_decorated = function(element)
|
||||
{
|
||||
return PkSpr.has_class(element, PkSpr.PKSPR_BASE_CLASS+"-decorated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a class to an item that indicates it has been decorated already.
|
||||
*
|
||||
* @param {Element} element The element to set.
|
||||
*/
|
||||
PkSpr.set_decorated = function(element)
|
||||
{
|
||||
PkSpr.add_class(element, " "+PkSpr.PKSPR_BASE_CLASS+"-decorated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a class to a DOM element.
|
||||
*
|
||||
* @param {Element} element The element to add a class to.
|
||||
* @param {string} cls The class name to add.
|
||||
*/
|
||||
PkSpr.add_class = function(element, cls)
|
||||
{
|
||||
element.className += " "+cls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an DOM element has a specific class.
|
||||
*
|
||||
* @param {Element} element The element to check.
|
||||
* @param {string} cls The class name to check for.
|
||||
* @return {boolean} Whether the element has the class.
|
||||
*/
|
||||
PkSpr.has_class = function(element, cls)
|
||||
{
|
||||
return (" "+element.className+" ").indexOf(" "+cls+" ") > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-browser DOMContentLoaded wrapper (version 1.2)
|
||||
*
|
||||
* Takes a window object and function; the function is executed after
|
||||
* DOM is loaded and ready, regardless of the browser used.
|
||||
*
|
||||
* Written by Diego Perini <diego.perini@gmail.com> and released under
|
||||
* the MIT license. Slightly modified for this project. For more
|
||||
* information, see <https://github.com/dperini/ContentLoaded>.
|
||||
*
|
||||
* @param {Window} win Window object.
|
||||
* @param {function(...)} fn Function to execute.
|
||||
*/
|
||||
PkSpr.content_loaded = function(win, fn)
|
||||
{
|
||||
var done = false, top = true,
|
||||
|
||||
doc = win.document, root = doc.documentElement,
|
||||
|
||||
add = doc.addEventListener ? "addEventListener" : "attachEvent",
|
||||
rem = doc.addEventListener ? "removeEventListener" : "detachEvent",
|
||||
pre = doc.addEventListener ? "" : "on",
|
||||
|
||||
init = function(e)
|
||||
{
|
||||
if (e.type === "readystatechange" && doc.readyState !== "complete") {
|
||||
return;
|
||||
}
|
||||
(e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
|
||||
if (!done && (done = true)) {
|
||||
fn.call(win, e.type || e);
|
||||
}
|
||||
},
|
||||
|
||||
poll = function()
|
||||
{
|
||||
try {
|
||||
root.doScroll("left");
|
||||
}
|
||||
catch(e) {
|
||||
setTimeout(poll, 50); return;
|
||||
}
|
||||
init("poll");
|
||||
};
|
||||
|
||||
if (doc.readyState == "complete") {
|
||||
fn.call(win, "lazy");
|
||||
}
|
||||
else {
|
||||
if (doc.createEventObject && root.doScroll) {
|
||||
try {
|
||||
top = !win.frameElement;
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
if (top) {
|
||||
poll();
|
||||
}
|
||||
}
|
||||
doc[add](pre+"DOMContentLoaded", init, false);
|
||||
doc[add](pre+"readystatechange", init, false);
|
||||
win[add](pre+"load", init, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a couple of initialization functions.
|
||||
*/
|
||||
PkSpr.initialize = function()
|
||||
{
|
||||
// Compile our numeric check regular expression.
|
||||
PkSpr.prepare_numeric_check();
|
||||
// Generate a list of slugs by Pokédex number.
|
||||
PkSpr.generate_idx_list();
|
||||
}();
|
||||
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define("pokesprite", [], function() {
|
||||
return PkSpr;
|
||||
});
|
||||
}
|
||||
|
||||
if (!noGlobal) {
|
||||
window["PkSpr"] = PkSpr;
|
||||
}
|
||||
|
||||
return PkSpr;
|
||||
}));
|
||||
@@ -1,189 +0,0 @@
|
||||
@charset 'UTF-8';
|
||||
/*!
|
||||
* {{$title_str}} v{{$version}} ({{$revision}}) {{$website_txt}}
|
||||
* {{$copyright_str}}
|
||||
* {{$copyright_gf}}
|
||||
* {{$copyright_contrib_notice}}
|
||||
* {{$generated_on}}
|
||||
*/
|
||||
|
||||
${{$var_base_name}}-sprite-url: '{{$img_output}}';
|
||||
{{$item_vars}}
|
||||
/**
|
||||
* Mixin that sets sprite styling.
|
||||
*
|
||||
* This mixin can be used to turn any element into an icon. When calling
|
||||
* this function, the optional second argument is a map that can be
|
||||
* used to specify which CSS values are set. It may contain any or all of
|
||||
* the following values:
|
||||
*
|
||||
* img background-image
|
||||
* w width
|
||||
* h height
|
||||
* size width and height
|
||||
* pos background-position
|
||||
* content sets a non-empty content value (for pseudoelements)
|
||||
*
|
||||
* When using this mixin to modify multiple elements, the second argument
|
||||
* can be used to minimize the amount of generated CSS code; first set
|
||||
* the common values, then add specific traits.
|
||||
*
|
||||
* For example, to set an element to show up as Bulbasaur,
|
||||
* use: @include {{$var_base_name}}-sprite('bulbasaur');
|
||||
*/
|
||||
@mixin {{$var_base_name}}-sprite($label, $set:('img', 'size', 'pos', 'content'))
|
||||
{
|
||||
@if index($set, 'img') != false {
|
||||
background-image: url(${{$var_base_name}}-sprite-url);
|
||||
}
|
||||
// Setting content:' ' causes pseudoelements to show up.
|
||||
@if index($set, 'content') != false {
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
// Look up this item's coordinates from the main variable
|
||||
// and set the appropriate background coordinates.
|
||||
@if map-has-key(${{$var_base_name}}-coords, $label) {
|
||||
$item: map-get(${{$var_base_name}}-coords, $label);
|
||||
@if index($set, 'size') != false or index($set, 'w') != false {
|
||||
width: #{map-get($item, 'w')}px;
|
||||
}
|
||||
@if index($set, 'size') != false or index($set, 'h') != false {
|
||||
height: #{map-get($item, 'h')}px;
|
||||
}
|
||||
@if index($set, 'pos') != false {
|
||||
background-position: -#{map-get($item, 'x')}px -#{map-get($item, 'y')}px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin that sets sprite size based on type.
|
||||
*
|
||||
* This sets the size of an icon based on the type size variable.
|
||||
* The optional second argument is a map that allows you to specify
|
||||
* whether to set width, height or both:
|
||||
*
|
||||
* w width
|
||||
* h height
|
||||
* size width and height
|
||||
*/
|
||||
@mixin {{$var_base_name}}-type($type, $set:('size'))
|
||||
{
|
||||
$item: map-get($pkspr-types, $type);
|
||||
@if index($set, 'size') != false or index($set, 'w') != false {
|
||||
&, > i {
|
||||
$width-val: #{map-get($item, 'w')};
|
||||
@if $width-val != '' {
|
||||
width: #{$width-val}px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@if index($set, 'size') != false or index($set, 'h') != false {
|
||||
&, > i {
|
||||
$height-val: #{map-get($item, 'h')};
|
||||
@if $height-val != '' {
|
||||
height: #{$height-val}px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If compatibility mode is enabled (and it should), browser-specific
|
||||
// CSS attributes will be used where required.
|
||||
${{$var_base_name}}-compatibility-mode: true;
|
||||
|
||||
/**
|
||||
* Mixin that ensures crisp rendering on modern browsers by setting
|
||||
* the resizing algorithm to nearest neighbor.
|
||||
*/
|
||||
@mixin crisp-rendering()
|
||||
{
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin that resets the rendering of the sprites back to standard.
|
||||
*/
|
||||
@mixin standard-rendering()
|
||||
{
|
||||
-ms-interpolation-mode: inherit;
|
||||
image-rendering: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base icon CSS.
|
||||
*
|
||||
* The display mode is determined by the element used in the HTML.
|
||||
* If a <span> is used, the icon is an inline-block element (like an image).
|
||||
* If a <div> is used, the icon is a block element.
|
||||
*
|
||||
* The <span> display mode has an alternative display style (via .display-over)
|
||||
* that sets the main element to a height of 1px, allowing the icon to be
|
||||
* displayed without affecting the line height of the running text.
|
||||
*
|
||||
* The icon itself is added to the <i> element inside of the container.
|
||||
* The element is added by the JS code.
|
||||
*/
|
||||
.{{$css_base_selector}} {
|
||||
@include crisp-rendering();
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
|
||||
// The actual icons are displayed in an embedded <i> element.
|
||||
> i {
|
||||
// Set the standard Pokémon icon attributes.
|
||||
@include {{$var_base_name}}-sprite(nth(map-keys(${{$var_base_name}}-coords), 1), ('img', 'content'));
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Two standard display modes determined by the containing element.
|
||||
&span {
|
||||
display: inline-block;
|
||||
}
|
||||
&block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// An optional display class: inline-block, but without modifying
|
||||
// the line height of the sentence.
|
||||
&span.display-over {
|
||||
height: 1px;
|
||||
vertical-align: middle;
|
||||
|
||||
> i {
|
||||
position: absolute;
|
||||
// Manually chosen positioning connate with the Pokémon icon designs.
|
||||
// This displays the Pokémon icon at a reasonable baseline.
|
||||
top: -20px;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Displays the right-facing icons for icons that do not have a customized
|
||||
// right-facing version. This class is to be added by the JS.
|
||||
&.{{$var_base_name}}-faux-right {
|
||||
// If we're using compatibility mode (and we should), generate a number
|
||||
// of vendor-specific prefixes.
|
||||
@if ${{$var_base_name}}-compatibility-mode == true {
|
||||
-moz-transform: scaleX(-1);
|
||||
-o-transform: scaleX(-1);
|
||||
-webkit-transform: scaleX(-1);
|
||||
filter: FlipH;
|
||||
-ms-filter: 'FlipH';
|
||||
}
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
// Resets the image display back to normal, in case the end user wants it.
|
||||
&.interpolated {
|
||||
@include standard-rendering();
|
||||
}
|
||||
|
||||
// The sizes of all available icon types follow.
|
||||
{{$type_sizes}}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
<frm=::bold>PokéSprite v{{$version}} ({{$revision}})</frm>
|
||||
{{$copyright}}
|
||||
{{$error}}
|
||||
Usage:
|
||||
<frm=::bold>pokesprite</frm> [<frm=::underline>options</frm>]
|
||||
|
||||
Description:
|
||||
Generates a complete image sprite of all Pokémon in the National Pokédex (along with several other types of icons), and the SCSS file to make them usable. This sprite can then be used to efficiently display these icons inside a web page. Pokémon icons are arranged sequentially, and a growing packer algorithm is used to arrange other images inside the sprite. For more information, see <{{$website}}>.
|
||||
|
||||
Options:
|
||||
<frm=::bold>--dir-icons=dir</frm>
|
||||
Icons directory. Default: <frm=::underline>./icons/</frm>.
|
||||
|
||||
<frm=::bold>--dir-pkmn=dir</frm>
|
||||
Pokémon icons directory. Relative to the icons directory. Default: <frm=::underline>pokemon/</frm>.
|
||||
|
||||
<frm=::bold>--dir-data=dir</frm>
|
||||
Data directory. Default: <frm=::underline>./data/</frm>.
|
||||
|
||||
<frm=::bold>--file-data=filename</frm>
|
||||
Data filename. Relative to the data directory. Default: <frm=::underline>pkmn-icons.json</frm>.
|
||||
|
||||
<frm=::bold>--dir-output=dir</frm>
|
||||
Output directory. Default: <frm=::underline>./output/</frm>.
|
||||
|
||||
<frm=::bold>--file-output-img-tmp=filename</frm>
|
||||
Temporary output image filename. Default: <frm=::underline>pkmn_unoptimized.png</frm>.
|
||||
|
||||
<frm=::bold>--file-output-img=filename</frm>
|
||||
Final output image filename. Default: <frm=::underline>pkmn.png</frm>.
|
||||
|
||||
<frm=::bold>--file-output-scss=filename</frm>
|
||||
SCSS output filename. Default: <frm=::underline>pkmn.scss</frm>.
|
||||
|
||||
<frm=::bold>--file-output-html=filename</frm>
|
||||
HTML icon overview output filename. Default: <frm=::underline>overview.html</frm>.
|
||||
|
||||
<frm=::bold>--file-output-md=filename</frm>
|
||||
Markdown icon overview output filename. Default: <frm=::underline>overview.md</frm>.
|
||||
|
||||
<frm=::bold>--dir-resources=dir</frm>
|
||||
Resources directory. Default: <frm=::underline>./resources/</frm>.
|
||||
|
||||
<frm=::bold>--tpl-scss=filename</frm>
|
||||
Template to use for SCSS generation. Relative to the resources directory. Default: <frm=::underline>stylesheet-tpl.scss</frm>.
|
||||
|
||||
<frm=::bold>--tpl-html</frm>
|
||||
Template to use for HTML icon overview generation. Relative to the resources directory. Default: <frm=::underline>overview-tpl.html</frm>.
|
||||
|
||||
<frm=::bold>--path-pngcrush=filename</frm>
|
||||
Path to pngcrush. Default: <frm=::underline>./tools/pngcrush</frm>.
|
||||
|
||||
<frm=::bold>--file-exts=expr</frm>
|
||||
Permitted file extensions for images to be included. Must be a comma-separated list. Default: <frm=::underline>png</frm>.
|
||||
|
||||
<frm=::bold>--icon-sets=expr</frm>
|
||||
List of icon sets to include in the image. Defaults to <frm=::underline>all known sets</frm>.
|
||||
|
||||
<frm=::bold>--include-right=[0|1|2]</frm>
|
||||
Whether to include right-facing icons. If the argument is <frm=::underline>0</frm>, none will be included. If no argument is given or the argument is <frm=::underline>1</frm>, only Pokémon that have a unique right-facing icon are included (default). If the argument is <frm=::underline>2</frm>, all Pokémon get a right-facing icon (and those that don't have one, have their regular icon flipped).
|
||||
|
||||
<frm=::bold>--generate-markdown</frm>
|
||||
Generates a Markdown overview file in addition to the HTML overview file.
|
||||
|
||||
<frm=::bold>--pkmn-lang=[eng|jpn|jpn_ro]</frm>
|
||||
Sets the language of Pokémon names to use for the output. Default: <frm=::underline>eng</frm>.
|
||||
|
||||
<frm=::bold>--lang=[en_us|ja]</frm>
|
||||
Sets the language of program feedback. Default: <frm=::underline>en_us</frm>.
|
||||
|
||||
<frm=::bold>--exclude-pkmn</frm>
|
||||
Excludes Pokémon icons.
|
||||
|
||||
<frm=::bold>--exclude-regular</frm>
|
||||
Excludes regular (non-shiny) icons.
|
||||
|
||||
<frm=::bold>--exclude-shiny</frm>
|
||||
Excludes shiny icons.
|
||||
|
||||
<frm=::bold>--exclude-forms</frm>
|
||||
Excludes alternate forms.
|
||||
|
||||
<frm=::bold>--exclude-icon-sets</frm>
|
||||
Excludes icon sets (other than the Pokémon icons).
|
||||
|
||||
<frm=::bold>--exclude-special-icons</frm>
|
||||
Excludes special icons (egg, and "unknown Pokémon").
|
||||
|
||||
<frm=::bold>--no-pngcrush</frm>
|
||||
Skips the pngcrush step.
|
||||
|
||||
<frm=::bold>--no-padding</frm>
|
||||
Don't add a 1px padding around all images (recommended for retina compatibility).
|
||||
|
||||
<frm=::bold>--verbose</frm>
|
||||
Displays debugging information for every image added to the spritesheet.
|
||||
|
||||
<frm=::bold>--monochrome</frm>
|
||||
Displays all debugging information without colors.
|
||||
|
||||
<frm=::bold>--help</frm>
|
||||
Displays this help text.
|
||||
@@ -1 +0,0 @@
|
||||
<frm=::bold>PokéSprite v{{$version}} ({{$revision}})</frm>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 250 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 257 KiB |
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
BASEDIR=$(dirname "$0")
|
||||
DIR=$BASEDIR/..
|
||||
if [ ! -f "$DIR/pokesprite.php" ]; then
|
||||
echo "Cannot find pokesprite.php"
|
||||
exit
|
||||
fi
|
||||
|
||||
rm -f "$DIR/output/"*
|
||||
"$DIR/pokesprite.php"
|
||||
java -jar "$DIR/tools/closure-compiler.jar" --compilation_level ADVANCED_OPTIMIZATIONS --js "$DIR/output/pokesprite.js" --js_output_file "$DIR/output/pokesprite.min.js" --charset UTF-8
|
||||
rm "$DIR/output/pokesprite.js"
|
||||
node-sass --sourcemap=none --output-style compressed "$DIR/output/pokesprite.scss" "$DIR/output/pokesprite.min.css"
|
||||
rm "$DIR/output/pokesprite.scss"
|
||||
rm -f "$DIR/output/pokesprite.css.map"
|
||||
node-sass --sourcemap=none --output-style compressed "$DIR/resources/overview.scss" "$DIR/output/overview.min.css"
|
||||
rm -f "$DIR/output/overview.css.map"
|
||||
cp "$DIR/resources/node-readme.md" "$DIR/output/readme.md"
|
||||
cp "$DIR/LICENSE" "$DIR/output/license"
|
||||
cp "$DIR/resources/pkg-info.json" "$DIR/output/package.json"
|
||||
|
||||
#./pokesprite.php --exclude-pkmn --file-output-img="icons.png"
|
||||
#./pokesprite.php --exclude-icon-sets --exclude-shiny --file-output-img="regular.png"
|
||||
#./pokesprite.php --exclude-icon-sets --exclude-regular --file-output-img="shiny.png"
|
||||
Reference in New Issue
Block a user