1- import { CommandLineParser } from '@rushstack/ts-command-line' ;
1+ /* eslint-disable no-console */
2+ import { command , multioption , flag , number , restPositionals , array , string } from 'cmd-ts' ;
23import { writeFile } from 'fs/promises' ;
34import path from 'path' ;
4- import { listSprites } from './fs.js' ;
5+ import { listSprites , ValidExtensions } from './fs.js' ;
56import { Sprites } from './sprites.js' ;
67import { promises as fs } from 'fs' ;
78
8- export class SpriteCli extends CommandLineParser {
9- ratio = this . defineIntegerListParameter ( {
10- argumentName : 'RATIO' ,
11- parameterLongName : '--ratio' ,
12- description : 'Pixel ratio, default: "--ratio 1 --ratio 2"' ,
13- } ) ;
9+ export const SpriteCli = command ( {
10+ name : 'basemaps-sprites' ,
11+ description : 'Create a sprite sheet from a folder of sprites' ,
12+ args : {
13+ ratio : multioption ( { long : 'ratio' , type : array ( number ) , description : 'Pixel ratios to use, default: 1, 2' } ) ,
14+ retina : flag ( { long : 'retina' , defaultValue : ( ) => false , description : 'Double the pixel ratio' } ) ,
15+ paths : restPositionals ( { description : 'Path to sprites' } ) ,
16+ extensions : multioption ( {
17+ long : 'extension' ,
18+ type : array ( string ) ,
19+ description : 'File extensions to use, default: .svg' ,
20+ } ) ,
21+ } ,
22+ handler : async ( args ) => {
23+ if ( args . paths . length === 0 ) throw new Error ( 'No sprite paths supplied' ) ;
24+ if ( args . ratio . length === 0 ) args . ratio . push ( 1 , 2 ) ;
1425
15- retina = this . defineFlagParameter ( {
16- parameterLongName : '--retina' ,
17- description : 'Double the pixel ratios, 1x becomes 2x' ,
18- } ) ;
19- r = this . defineCommandLineRemainder ( { description : 'Path to sprites' } ) ;
26+ if ( args . extensions . length > 0 ) ValidExtensions . clear ( ) ;
27+ for ( const ext of args . extensions ) {
28+ const extName = ext . toLowerCase ( ) ;
29+ if ( extName . startsWith ( '.' ) ) ValidExtensions . add ( extName ) ;
30+ else ValidExtensions . add ( `.${ extName } ` ) ;
31+ }
2032
21- constructor ( ) {
22- super ( {
23- toolFilename : 'basemaps-sprites' ,
24- toolDescription : 'Create a sprite sheet from a folder of sprites' ,
25- } ) ;
26- }
33+ const result = await buildSprites ( args . ratio , args . retina , args . paths ) ;
2734
28- protected onDefineParameters ( ) : void {
29- // Noop
30- }
31-
32- protected async onExecute ( ) : Promise < void > {
33- if ( this . remainder ?. values == null || this . remainder . values . length === 0 ) {
34- throw new Error ( 'No sprite paths supplied' ) ;
35+ for ( const r of result ) {
36+ console . log ( 'Write' , r . sprites , 'sprites to' , r . path , { ratio : r . ratio } ) ;
3537 }
36- const ratio = [ ...this . ratio . values ] ;
37- const paths = [ ...this . remainder . values ] ;
38- await buildSprites ( ratio , this . retina . value , paths ) ;
39- }
40- }
38+ console . log ( 'Done' ) ;
39+ } ,
40+ } ) ;
4141
42- export async function buildSprites ( ratio : number [ ] , retina : boolean , paths : string [ ] , output ?: string ) : Promise < void > {
42+ export interface SpriteStats {
43+ /** Sprite sheet name */
44+ sheet : string ;
45+ /** Number of sprites found */
46+ sprites : number ;
47+ /** Pixel ratio */
48+ ratio : number ;
49+ /** Output location */
50+ path : string ;
51+ /**
52+ * Pixel ratio scale, will be empty if ratio is 1
53+ * @example "@2x" or "@3x"
54+ */
55+ scale : string ;
56+ }
57+ export async function buildSprites (
58+ ratio : number [ ] ,
59+ retina : boolean ,
60+ paths : string [ ] ,
61+ output ?: string ,
62+ ) : Promise < SpriteStats [ ] > {
4363 if ( ratio . length === 0 ) ratio . push ( 1 , 2 ) ;
4464
4565 let baseRatio = 1 ;
@@ -48,6 +68,8 @@ export async function buildSprites(ratio: number[], retina: boolean, paths: stri
4868 for ( let i = 0 ; i < ratio . length ; i ++ ) ratio [ i ] = ratio [ i ] * 2 ;
4969 }
5070
71+ const stats : SpriteStats [ ] = [ ] ;
72+
5173 for ( const spritePath of paths ) {
5274 const sheetName = path . basename ( spritePath ) ;
5375 const sprites = await listSprites ( spritePath ) ;
@@ -63,6 +85,15 @@ export async function buildSprites(ratio: number[], retina: boolean, paths: stri
6385
6486 await writeFile ( `${ outputPath } .json` , JSON . stringify ( res . layout , null , 2 ) ) ;
6587 await writeFile ( `${ outputPath } .png` , res . buffer ) ;
88+ stats . push ( {
89+ sheet : sheetName ,
90+ path : outputPath ,
91+ sprites : sprites . length ,
92+ ratio : res . pixelRatio ,
93+ scale : scaleText ,
94+ } ) ;
6695 }
6796 }
97+
98+ return stats ;
6899}
0 commit comments