diff --git a/README.md b/README.md index 11953f4..1e9f33f 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ $ pub global activate icon_font_generator - `--out-font` * - Output icon font path (to file, for example: lib/font.ttf) - `--out-flutter` * - Output flutter icon class (to file, for example: lib/icons.dart) - `--class-name` * - The class name is also the font name used in pubspec.yaml (as font name) +- `--symlinks-map` - Source map of symlinked icons, have to be a json map with this pattern: symlink -> target - `--height` - Fixed font height value, defaults: 512 - `--descent` - Offset applied to the baseline, defaults: 240 - `--package` - Name of package for generated icon data ([See more](https://api.flutter.dev/flutter/widgets/IconData/fontPackage.html)) diff --git a/bin/icon_font_generator.dart b/bin/icon_font_generator.dart index 1a09dea..de698da 100644 --- a/bin/icon_font_generator.dart +++ b/bin/icon_font_generator.dart @@ -37,6 +37,10 @@ class GenerateCommand extends Command { 'class-name', help: 'Flutter class name / family for generating file', ) + ..addOption( + 'symlinks-map', + help: 'Symlinks json map, with this pattern: symlink -> target', + ) ..addOption( 'height', help: 'Fixed font height value', @@ -97,6 +101,12 @@ class GenerateCommand extends Command { exit(1); } + if (argResults!['symlinks-map'] != null && + !argResults!['symlinks-map'].toString().endsWith('.json')) { + print('--symlinks-map have to be a .json file'); + exit(1); + } + final genRootDir = Directory.fromUri(Platform.script.resolve('..')); final npmPackage = File(path.join(genRootDir.path, 'package.json')); @@ -139,6 +149,10 @@ class GenerateCommand extends Command { final sourceIconsDirectory = Directory.fromUri(Directory.current.uri .resolve(argResults!['from'].replaceAll('\\', '/'))); + final symlinksMap = argResults!['symlinks-map'] == null + ? null + : File.fromUri(Directory.current.uri + .resolve(argResults!['symlinks-map'].replaceAll('\\', '/'))); final outIconsFile = File.fromUri(Directory.current.uri .resolve(argResults!['out-font'].replaceAll('\\', '/'))); final outFlutterClassFile = File.fromUri(Directory.current.uri @@ -201,6 +215,7 @@ class GenerateCommand extends Command { final generateClassResult = await generateFlutterClass( iconMap: iconsMap, + symlinksMap: symlinksMap, className: argResults!['class-name'], packageName: argResults!['package'], namingStrategy: argResults!['naming-strategy'], diff --git a/lib/generate_flutter_class.dart b/lib/generate_flutter_class.dart index 43bef36..d951806 100644 --- a/lib/generate_flutter_class.dart +++ b/lib/generate_flutter_class.dart @@ -13,20 +13,55 @@ class GenerateResult { Future generateFlutterClass({ required File iconMap, + required File? symlinksMap, required String className, required String? packageName, required String namingStrategy, String indent = ' ', }) async { + String reCase(String data) { + return namingStrategy == 'snake' + ? ReCase(data).snakeCase + : ReCase(data).camelCase; + } + final Map icons = jsonDecode(await iconMap.readAsString()); + final Map symlinks = + symlinksMap == null ? {} : jsonDecode(await symlinksMap.readAsString()); + + for (var symlinkEntry in symlinks.entries) { + // Symlinks values are already correctly cased + final symlink = symlinkEntry.key; + final target = symlinkEntry.value.toString(); + final Iterable reCasedIconKeys = + icons.keys.map((key) => reCase(key)); + + if (reCasedIconKeys.contains(symlink)) { + print( + '\x1B[33mWarning: symlink "$symlink" icon already exists - symlink creation skipped\x1B[0m'); + continue; + } else if (symlinks.keys.contains(target)) { + print( + '\x1B[33mWarning: target "$target" icon is already a symlink - symlink creation skipped\x1B[0m'); + continue; + } else if (!reCasedIconKeys.contains(target)) { + print( + '\x1B[33mWarning: target "$target" icon does not exist - symlink creation skipped\x1B[0m'); + continue; + } + + final targetEntry = + icons.entries.singleWhere((entry) => reCase(entry.key) == target); + icons.addAll({ + symlink: targetEntry.value, + }); + } final dartIconsEntries = {}; final dartIconsValues = {}; for (final entry in icons.entries) { - final name = namingStrategy == 'snake' - ? ReCase(entry.key).snakeCase - : ReCase(entry.key).camelCase; + final name = reCase(entry.key); dartIconsEntries.add(someReplace( template.icon