Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions lib/src/commands/get_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import 'package:yaml/yaml.dart';
/// Configuration for a single file to download and export
class FileConfig {
/// Creates a file config
FileConfig({required this.fileId, required this.output});
FileConfig({required this.fileId, required this.output, this.scale});

/// The file ID to download
final String fileId;

/// The output path for the exported image
final String output;

/// Optional scale dimensions in WIDTH,HEIGHT format (e.g. "512,512")
final String? scale;
}

/// {@template get_command}
Expand Down Expand Up @@ -116,9 +119,10 @@ class GetCommand extends Command<int> {

final fileId = fileMap['fileId'] as String?;
final output = fileMap['output'] as String?;
final scale = fileMap['scale'] as String?;

if (fileId != null && output != null) {
configs.add(FileConfig(fileId: fileId, output: output));
configs.add(FileConfig(fileId: fileId, output: output, scale: scale));
}
}

Expand All @@ -130,6 +134,28 @@ class GetCommand extends Command<int> {
Future<bool> _processFile(FileConfig config, String apiKey) async {
_logger.info('Processing ${config.fileId}...');

// Validate and parse scale if provided
int? scaleWidth;
int? scaleHeight;
if (config.scale != null) {
const scaleFormatError =
' scale must be in the format WIDTH,HEIGHT with positive '
'integers, e.g. 512,512';
final parts = config.scale!.split(',').map((e) => e.trim()).toList();
if (parts.length != 2) {
_logger.err(scaleFormatError);
return false;
}
final w = int.tryParse(parts[0]);
final h = int.tryParse(parts[1]);
if (w == null || h == null || w <= 0 || h <= 0) {
_logger.err(scaleFormatError);
return false;
}
scaleWidth = w;
scaleHeight = h;
}

// Create temp file
final tempDir = Directory.systemTemp.createTempSync('pepper_sprite_');
final tempFile = File(path.join(tempDir.path, '${config.fileId}.psp'));
Expand All @@ -146,7 +172,12 @@ class GetCommand extends Command<int> {
}

// Export file
await _exportFile(tempFile, config.output);
await _exportFile(
tempFile,
config.output,
scaleWidth: scaleWidth,
scaleHeight: scaleHeight,
);

_logger.success(' Exported to ${config.output}');
return true;
Expand Down Expand Up @@ -187,7 +218,12 @@ class GetCommand extends Command<int> {
}

/// Exports a PSP file to PNG
Future<void> _exportFile(File sourceFile, String outputPath) async {
Future<void> _exportFile(
File sourceFile,
String outputPath, {
int? scaleWidth,
int? scaleHeight,
}) async {
final bytes = await sourceFile.readAsBytes();

// Deserialize
Expand All @@ -205,6 +241,11 @@ class GetCommand extends Command<int> {
}

// Export
ImageExporter.exportToPngFile(file, outputPath);
ImageExporter.exportToPngFile(
file,
outputPath,
scaleWidth: scaleWidth,
scaleHeight: scaleHeight,
);
}
}
116 changes: 116 additions & 0 deletions test/src/commands/get_command_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:mason_logger/mason_logger.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pepper_sprite_cli/src/command_runner.dart';
Expand Down Expand Up @@ -35,5 +37,119 @@ void main() {
// and the get command is registered
expect(commandRunner, isNotNull);
});

group('scale', () {
late Directory tempDir;
late File configFile;

setUp(() {
tempDir = Directory.systemTemp.createTempSync('pepper_sprite_test_');
configFile = File('${tempDir.path}/pepper-sprite.yaml');
});

tearDown(() {
tempDir.deleteSync(recursive: true);
});

test('invalid format — non-numeric', () async {
configFile.writeAsStringSync('''
files:
- fileId: "test-id"
output: "/tmp/output.png"
scale: "abc,def"
''');

final exitCode = await commandRunner.run([
'get',
'-k',
'test-api-key',
'-c',
configFile.path,
]);

expect(exitCode, ExitCode.software.code);
verify(
() => logger.err(
' scale must be in the format WIDTH,HEIGHT with positive '
'integers, e.g. 512,512',
),
).called(1);
});

test('invalid format — single value', () async {
configFile.writeAsStringSync('''
files:
- fileId: "test-id"
output: "/tmp/output.png"
scale: "512"
''');

final exitCode = await commandRunner.run([
'get',
'-k',
'test-api-key',
'-c',
configFile.path,
]);

expect(exitCode, ExitCode.software.code);
verify(
() => logger.err(
' scale must be in the format WIDTH,HEIGHT with positive '
'integers, e.g. 512,512',
),
).called(1);
});

test('invalid format — zero width', () async {
configFile.writeAsStringSync('''
files:
- fileId: "test-id"
output: "/tmp/output.png"
scale: "0,512"
''');

final exitCode = await commandRunner.run([
'get',
'-k',
'test-api-key',
'-c',
configFile.path,
]);

expect(exitCode, ExitCode.software.code);
verify(
() => logger.err(
' scale must be in the format WIDTH,HEIGHT with positive '
'integers, e.g. 512,512',
),
).called(1);
});

test('invalid format — negative height', () async {
configFile.writeAsStringSync('''
files:
- fileId: "test-id"
output: "/tmp/output.png"
scale: "512,-1"
''');

final exitCode = await commandRunner.run([
'get',
'-k',
'test-api-key',
'-c',
configFile.path,
]);

expect(exitCode, ExitCode.software.code);
verify(
() => logger.err(
' scale must be in the format WIDTH,HEIGHT with positive '
'integers, e.g. 512,512',
),
).called(1);
});
});
});
}
Loading