From aca4be74b43b201d8209f7856d437bab17dcd328 Mon Sep 17 00:00:00 2001 From: Furkan KURT Date: Wed, 14 Feb 2024 11:59:22 +0100 Subject: [PATCH 1/2] Added sort by name and generate icon list option --- README.md | 7 ++++++ bin/generator.dart | 2 ++ example/flutter_usage/fonts/icons.otf | Bin 2284 -> 2284 bytes example/flutter_usage/lib/ui/icons.dart | 10 +++++++- example/flutter_usage/pubspec.lock | 30 +++++++++++----------- example/flutter_usage/pubspec.yaml | 2 ++ lib/src/cli/arguments.dart | 16 ++++++++++++ lib/src/cli/options.dart | 12 +++++++++ lib/src/common/api.dart | 10 ++++++++ lib/src/utils/flutter_class_gen.dart | 19 +++++++++++++- pubspec.lock | 6 ++--- test/assets/test_config.yaml | 2 ++ test/cli_test.dart | 32 ++++++++++++++++++++++++ 13 files changed, 128 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 84d2960..597c84b 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,11 @@ Name for a generated class. Name of a package that provides a font. Used to provide a font through package dependency. - `--[no-]format` Format dart generated code. +- `-s` or `--sort` +Sort by icon names for the generated code. + +- `-l` or `--list` +Generate a list of icons. Font options: - `-f` or `--font-name=` @@ -102,6 +107,8 @@ icon_font: class_name: "MyIcons" package: my_font_package format: true + sort: true + list: true font_name: "My Icons" normalize: true diff --git a/bin/generator.dart b/bin/generator.dart index 7ab4ad0..ad73c65 100644 --- a/bin/generator.dart +++ b/bin/generator.dart @@ -87,6 +87,7 @@ void _run(CliArguments parsedArgs) { ignoreShapes: parsedArgs.ignoreShapes, normalize: parsedArgs.normalize, fontName: parsedArgs.fontName, + sort: parsedArgs.sort, ); writeToFile(parsedArgs.fontFile.path, otfResult.font); @@ -103,6 +104,7 @@ void _run(CliArguments parsedArgs) { fontFileName: fontFileName, familyName: otfResult.font.familyName, package: parsedArgs.fontPackage, + iconList: parsedArgs.iconList, ); if (parsedArgs.format ?? kDefaultFormat) { diff --git a/example/flutter_usage/fonts/icons.otf b/example/flutter_usage/fonts/icons.otf index b007d12890a9f4f46909b1db0b1b9b0bae22b5ba..83310303510b0432e6005e9e2260aa5953c4c6c7 100644 GIT binary patch delta 92 zcmaDO_(o9BKP1GTfs3Jmftf+U+09L%exjf~i`uLE_7g+wm?pMNoT4BjVy>|}p5Nvx o12^*v1|WF&$=4D_Z@h4sk static const IconData collection = IconData(0xe003, fontFamily: iconFontFamily); + + /// List of all icons in this font. + static const List values = [ + account, + arrowLeft, + arrowRight, + collection, + ]; } diff --git a/example/flutter_usage/pubspec.lock b/example/flutter_usage/pubspec.lock index 8a3b7ba..5fbb99e 100644 --- a/example/flutter_usage/pubspec.lock +++ b/example/flutter_usage/pubspec.lock @@ -61,10 +61,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -174,10 +174,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" package_config: dependency: transitive description: @@ -243,18 +243,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -275,10 +275,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -299,18 +299,18 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" xml: dependency: transitive description: @@ -328,5 +328,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.7.5" diff --git a/example/flutter_usage/pubspec.yaml b/example/flutter_usage/pubspec.yaml index a71a34a..6c18bc9 100644 --- a/example/flutter_usage/pubspec.yaml +++ b/example/flutter_usage/pubspec.yaml @@ -31,6 +31,8 @@ icon_font: output_class_file: lib/ui/icons.dart class_name: UiIcons format: true + sort: true + list: true font_name: Ui Icons normalize: false diff --git a/lib/src/cli/arguments.dart b/lib/src/cli/arguments.dart index 80ccab5..b145c5d 100644 --- a/lib/src/cli/arguments.dart +++ b/lib/src/cli/arguments.dart @@ -23,6 +23,8 @@ const _kArgAllowedTypes = >{ CliArgument.ignoreShapes: [bool], CliArgument.recursive: [bool], CliArgument.format: [bool], + CliArgument.sort: [bool], + CliArgument.iconList: [bool], CliArgument.verbose: [bool], CliArgument.help: [bool], CliArgument.configFile: [String], @@ -30,6 +32,8 @@ const _kArgAllowedTypes = >{ const kDefaultVerbose = false; const kDefaultFormat = false; +const kDefaultSort = false; +const kDefaultIconList = false; const kDefaultRecursive = false; const kOptionNames = EnumClass({ @@ -39,6 +43,8 @@ const kOptionNames = EnumClass({ CliArgument.className: 'class-name', CliArgument.fontPackage: 'package', CliArgument.format: 'format', + CliArgument.sort: 'sort', + CliArgument.iconList: 'list', CliArgument.fontName: 'font-name', CliArgument.normalize: 'normalize', @@ -59,6 +65,8 @@ const kConfigKeys = EnumClass({ CliArgument.className: 'class_name', CliArgument.fontPackage: 'package', CliArgument.format: 'format', + CliArgument.sort: 'sort', + CliArgument.iconList: 'list', CliArgument.fontName: 'font_name', CliArgument.normalize: 'normalize', @@ -85,6 +93,8 @@ enum CliArgument { className, fontPackage, format, + sort, + iconList, // Font-related fontName, @@ -109,6 +119,8 @@ class CliArguments { this.className, this.fontPackage, this.format, + this.sort, + this.iconList, this.fontName, this.recursive, this.ignoreShapes, @@ -131,6 +143,8 @@ class CliArguments { map[CliArgument.className] as String?, map[CliArgument.fontPackage] as String?, map[CliArgument.format] as bool?, + map[CliArgument.sort] as bool?, + map[CliArgument.iconList] as bool?, map[CliArgument.fontName] as String?, map[CliArgument.recursive] as bool?, map[CliArgument.ignoreShapes] as bool?, @@ -146,6 +160,8 @@ class CliArguments { final String? className; final String? fontPackage; final bool? format; + final bool? sort; + final bool? iconList; final String? fontName; final bool? recursive; final bool? ignoreShapes; diff --git a/lib/src/cli/options.dart b/lib/src/cli/options.dart index ea2e9cd..4222e43 100644 --- a/lib/src/cli/options.dart +++ b/lib/src/cli/options.dart @@ -30,6 +30,18 @@ void defineOptions(ArgParser argParser) { help: 'Formate dart generated code.', defaultsTo: kDefaultFormat, ) + ..addFlag( + kOptionNames[CliArgument.sort]!, + abbr: 's', + help: 'Sort by generated icon names.', + defaultsTo: kDefaultSort, + ) + ..addFlag( + kOptionNames[CliArgument.iconList]!, + abbr: 'l', + help: 'Generate a list of icons.', + defaultsTo: kDefaultIconList, + ) ..addSeparator('Font options:') ..addOption( kOptionNames[CliArgument.fontName]!, diff --git a/lib/src/common/api.dart b/lib/src/common/api.dart index 47f568b..e46a84c 100644 --- a/lib/src/common/api.dart +++ b/lib/src/common/api.dart @@ -24,6 +24,9 @@ class SvgToOtfResult { /// * If [normalize] is set to true, /// glyphs are resized and centered to fit in coordinates grid (unitsPerEm). /// Defaults to true. +/// * If [sort] is set to true, +/// glyphs are sorted by name. +/// Defaults to false. /// * [fontName] is a name for a generated font. /// /// Returns an instance of [SvgToOtfResult] class containing glyphs and a font. @@ -32,8 +35,10 @@ SvgToOtfResult svgToOtf({ bool? ignoreShapes, bool? normalize, String? fontName, + bool? sort, }) { normalize ??= true; + sort ??= false; final svgList = [ for (final e in svgMap.entries) @@ -52,6 +57,9 @@ SvgToOtfResult svgToOtf({ } } } + if (sort) { + svgList.sort((a, b) => a.name.compareTo(b.name)); + } final glyphList = svgList.map(GenericGlyph.fromSvg).toList(); @@ -83,6 +91,7 @@ String generateFlutterClass({ String? fontFileName, String? package, int? indent, + bool? iconList, }) { final generator = FlutterClassGenerator( glyphList, @@ -91,6 +100,7 @@ String generateFlutterClass({ fontFileName: fontFileName, familyName: familyName, package: package, + iconList: iconList, ); return generator.generate(); diff --git a/lib/src/utils/flutter_class_gen.dart b/lib/src/utils/flutter_class_gen.dart index 7287bc6..0ebcd6d 100644 --- a/lib/src/utils/flutter_class_gen.dart +++ b/lib/src/utils/flutter_class_gen.dart @@ -33,12 +33,14 @@ class FlutterClassGenerator { String? fontFileName, String? package, int? indent, + bool? iconList = false, }) : _indent = ' ' * (indent ?? _kDefaultIndent), _className = _getVarName(className ?? _kDefaultClassName), _familyName = familyName ?? kDefaultFontFamily, _fontFileName = fontFileName ?? _kDefaultFontFileName, _iconVarNames = _generateVariableNames(glyphList), - _package = package?.isEmpty ?? true ? null : package; + _package = package?.isEmpty ?? true ? null : package, + _iconList = iconList ?? false; final List glyphList; final String _fontFileName; @@ -47,6 +49,7 @@ class FlutterClassGenerator { final String _indent; final String? _package; final List _iconVarNames; + final bool _iconList; static List _generateVariableNames(List glyphList) { final iconNameSet = {}; @@ -121,6 +124,19 @@ class FlutterClassGenerator { ]; } + String _generateIconList() { + + return [ + '', + '/// List of all icons in this font.', + 'static const List values = [', + for (var i = 0; i < _iconVarNames.length; i++) ...[ + '${_iconVarNames[i]},', + ], + '];' + ].join('\n'); + } + /// Generates content for a class' file. String generate() { final classContent = [ @@ -129,6 +145,7 @@ class FlutterClassGenerator { _fontFamilyConst, if (_hasPackage) _fontPackageConst, for (var i = 0; i < glyphList.length; i++) ..._generateIconConst(i), + if (_iconList) _generateIconList(), ]; final classContentString = diff --git a/pubspec.lock b/pubspec.lock index 87e1d13..875b10c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -389,10 +389,10 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web_socket_channel: dependency: transitive description: @@ -426,4 +426,4 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.2 <4.0.0" + dart: ">=3.0.0 <4.0.0" diff --git a/test/assets/test_config.yaml b/test/assets/test_config.yaml index 28f9569..d7d1b3e 100644 --- a/test/assets/test_config.yaml +++ b/test/assets/test_config.yaml @@ -9,6 +9,8 @@ icon_font: class_name: MyIcons package: test_package format: true + sort: true + list: true font_name: My Icons normalize: false diff --git a/test/cli_test.dart b/test/cli_test.dart index b14db9c..0650978 100644 --- a/test/cli_test.dart +++ b/test/cli_test.dart @@ -42,6 +42,8 @@ void main() { '--verbose', '--config-file=test/config.yaml', '--package=test_package', + '--sort', + '--list', ]; final parsedArgs = parseArgsAndConfig(argParser, args); @@ -57,6 +59,8 @@ void main() { expect(parsedArgs.verbose, isTrue); expect(parsedArgs.configFile?.path, 'test/config.yaml'); expect(parsedArgs.fontPackage, 'test_package'); + expect(parsedArgs.sort, isTrue); + expect(parsedArgs.iconList, isTrue); }); test('All arguments with defaults', () { @@ -80,6 +84,8 @@ void main() { expect(parsedArgs.verbose, isFalse); expect(parsedArgs.configFile, isNull); expect(parsedArgs.fontPackage, isNull); + expect(parsedArgs.sort, isFalse); + expect(parsedArgs.iconList, isFalse); }); test('Help', () { @@ -100,6 +106,8 @@ void main() { '--recursive', '--verbose', '--help', + '--sort', + '--list', ]); expectCliHelpException([ './asdasd/sad/sad/asd', @@ -120,6 +128,8 @@ void main() { '--recursive', '--verbose', '--package=no', + '--sort', + '--list', '--config-file=test/assets/test_config.yaml', ]; @@ -137,6 +147,8 @@ void main() { expect(parsedArgs.verbose, isFalse); expect(parsedArgs.configFile, isNull); expect(parsedArgs.fontPackage, 'test_package'); + expect(parsedArgs.sort, isTrue); + expect(parsedArgs.iconList, isTrue); }); test('No arguments and config', () { @@ -158,6 +170,8 @@ void main() { expect(parsedArgs.verbose, isFalse); expect(parsedArgs.configFile, isNull); expect(parsedArgs.fontPackage, 'test_package'); + expect(parsedArgs.sort, isTrue); + expect(parsedArgs.iconList, isTrue); }); }); @@ -205,6 +219,8 @@ icon_font: output_class_file: lib/test_font.dart class_name: MyIcons package: test_package + sort: true + list: true font_name: My Icons normalize: false @@ -225,6 +241,8 @@ icon_font: expect(parsedArgs.recursive, isTrue); expect(parsedArgs.verbose, isTrue); expect(parsedArgs.fontPackage, 'test_package'); + expect(parsedArgs.sort, isTrue); + expect(parsedArgs.iconList, isTrue); }); test('All arguments with defaults', () { @@ -245,6 +263,8 @@ icon_font: expect(parsedArgs.recursive, isNull); expect(parsedArgs.verbose, isNull); expect(parsedArgs.fontPackage, isNull); + expect(parsedArgs.sort, isNull); + expect(parsedArgs.iconList, isNull); }); test('Type validation', () { @@ -273,6 +293,18 @@ icon_font: normalize: 1 '''); expectCliArgumentException(''' +icon_font: + input_svg_dir: ./ + output_font_file: generated_font.otf + sort: 1 + '''); + expectCliArgumentException(''' +icon_font: + input_svg_dir: ./ + output_font_file: generated_font.otf + list: 1 + '''); + expectCliArgumentException(''' icon_font: input_svg_dir: ./ output_font_file: generated_font.otf From 90e755f145e5deee6d50b5dee135cfb3c68541df Mon Sep 17 00:00:00 2001 From: Furkan KURT Date: Wed, 14 Feb 2024 13:41:26 +0100 Subject: [PATCH 2/2] Fixed 80 character limit for generated file --- lib/src/utils/flutter_class_gen.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/utils/flutter_class_gen.dart b/lib/src/utils/flutter_class_gen.dart index 0ebcd6d..97da448 100644 --- a/lib/src/utils/flutter_class_gen.dart +++ b/lib/src/utils/flutter_class_gen.dart @@ -166,8 +166,8 @@ import 'package:flutter/widgets.dart'; /// /// To use this class, make sure you declare the font in your /// project's `pubspec.yaml` file in the `fonts` section. This ensures that -/// the "$_familyName" font is included in your application. This font is used to -/// display the icons. For example: +/// the "$_familyName" font is included in your application. +/// This font is used to display the icons. For example: /// /// ```yaml /// flutter: