Skip to content

Commit d561ba8

Browse files
authored
Merge pull request #33 from lcdsmao/assets-style
Specify generated assets style
2 parents 324cc4d + 528130c commit d561ba8

File tree

13 files changed

+456
-90
lines changed

13 files changed

+456
-90
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,5 @@ node_modules/
108108

109109
## Test coverage
110110
coverage/
111-
test/
111+
test/.test_coverage.dart
112112

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,27 @@ final svg = SvgPicture.asset(Assets.images.icons.paint);
232232
final json = await rootBundle.loadString(Assets.json.fruits);
233233
```
234234

235+
[FlutterGen] also support generating other style of `Assets` class:
236+
237+
```yaml
238+
# pubspec.yaml
239+
flutter_gen:
240+
241+
assets:
242+
# Assets.imagesChip
243+
style: camel-case
244+
245+
# Assets.images_chip
246+
# style: snake-case
247+
248+
# Assets.images.chip (default style)
249+
# style: dot-delimiter
250+
251+
flutter:
252+
assets:
253+
- assets/images/chip.png
254+
```
255+
235256
The root directory will be omitted if it is either **`assets`** or **`asset`**.
236257

237258
```

example/lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void main() {
2727
Assets.images.icons.fuchsia.svg(),
2828
Assets.images.icons.paint.svg(
2929
width: 120,
30-
height: 120
30+
height: 120,
3131
),
3232
Assets.pictures.chip5.image(
3333
width: 120,

lib/src/generators/assets_generator.dart

Lines changed: 171 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -3,66 +3,50 @@ import 'dart:io';
33

44
import 'package:dart_style/dart_style.dart';
55
import 'package:path/path.dart';
6+
import 'package:dartx/dartx.dart';
67

78
import '../settings/asset_type.dart';
89
import '../settings/flutter.dart';
910
import '../settings/flutter_gen.dart';
10-
import '../utils/camel_case.dart';
11+
import '../utils/string.dart';
1112
import 'generator_helper.dart';
1213
import 'integrations/integration.dart';
1314
import 'integrations/svg_integration.dart';
1415

15-
String generateAssets(File pubspecFile, DartFormatter formatter,
16-
FlutterGen flutterGen, FlutterAssets assets) {
16+
String generateAssets(
17+
File pubspecFile,
18+
DartFormatter formatter,
19+
FlutterGen flutterGen,
20+
FlutterAssets assets,
21+
) {
1722
assert(assets != null && assets.hasAssets,
1823
throw 'The value of "flutter/assets:" is incorrect.');
1924

2025
final importsBuffer = StringBuffer();
2126
final classesBuffer = StringBuffer();
2227

23-
final assetRelativePathList = _getAssetRelativePathList(pubspecFile, assets);
24-
final assetTypeQueue = ListQueue<AssetType>.from(
25-
_constructAssetTree(assetRelativePathList).children);
26-
final assetsStaticStatements = <_Statement>[];
27-
2828
final integrations = <Integration>[];
2929
if (flutterGen != null &&
3030
flutterGen.hasIntegrations &&
3131
flutterGen.integrations.hasFlutterSvg) {
3232
integrations.add(SvgIntegration());
3333
}
3434

35-
while (assetTypeQueue.isNotEmpty) {
36-
final assetType = assetTypeQueue.removeFirst();
37-
final assetAbsolutePath = join(pubspecFile.parent.path, assetType.path);
38-
39-
if (FileSystemEntity.isDirectorySync(assetAbsolutePath)) {
40-
final statements = _createDirectoryClassGenStatements(
41-
pubspecFile, assetType, integrations);
42-
43-
if (assetType.isDefaultAssetsDirectory) {
44-
assetsStaticStatements.addAll(statements);
45-
} else {
46-
final className = '\$${assetType.path.camelCase().capitalize()}Gen';
47-
classesBuffer
48-
.writeln(_directoryClassGenDefinition(className, statements));
49-
// Add this directory reference to Assets class
50-
// if we are not under the default asset folder
51-
if (dirname(assetType.path) == '.') {
52-
assetsStaticStatements.add(_Statement(
53-
type: className,
54-
name: assetType.baseName.camelCase(),
55-
value: '$className\(\)',
56-
isConstConstructor: true,
57-
));
58-
}
59-
}
60-
61-
assetTypeQueue.addAll(assetType.children);
62-
}
35+
if (flutterGen == null ||
36+
!flutterGen.hasAssets ||
37+
flutterGen.assets.isDefaultStyle) {
38+
classesBuffer.writeln(
39+
_dotDelimiterStyleDefinition(pubspecFile, assets, integrations));
40+
} else if (flutterGen.assets.isSnakeCaseStyle) {
41+
classesBuffer
42+
.writeln(_snakeCaseStyleDefinition(pubspecFile, assets, integrations));
43+
} else if (flutterGen.assets.isCamelCaseStyle) {
44+
classesBuffer
45+
.writeln(_camelCaseStyleDefinition(pubspecFile, assets, integrations));
46+
} else {
47+
throw 'The value of "flutter_gen/assets/style." is incorrect.';
6348
}
6449

65-
classesBuffer.writeln(_assetsClassDefinition(assetsStaticStatements));
6650
classesBuffer.writeln(_assetGenImageClassDefinition);
6751

6852
final imports = <String>{'package:flutter/widgets.dart'};
@@ -127,55 +111,160 @@ AssetType _constructAssetTree(List<String> assetRelativePathList) {
127111
return assetTypeMap['.'];
128112
}
129113

130-
List<_Statement> _createDirectoryClassGenStatements(
131-
File pubspecFile, AssetType assetType, List<Integration> integrations) {
132-
final statements = assetType.children
133-
.map((child) {
134-
final childAssetAbsolutePath =
135-
join(pubspecFile.parent.path, child.path);
136-
_Statement statement;
137-
if (child.isSupportedImage) {
138-
statement = _Statement(
139-
type: 'AssetGenImage',
140-
name: child.baseName.camelCase(),
141-
value: 'AssetGenImage\(\'${posixStyle(child.path)}\'\)',
142-
isConstConstructor: true,
143-
);
144-
} else if (FileSystemEntity.isDirectorySync(childAssetAbsolutePath)) {
145-
final childClassName = '\$${child.path.camelCase().capitalize()}Gen';
146-
statement = _Statement(
147-
type: childClassName,
148-
name: child.baseName.camelCase(),
149-
value: '$childClassName\(\)',
114+
_Statement _createAssetTypeStatement(
115+
File pubspecFile,
116+
AssetType assetType,
117+
List<Integration> integrations,
118+
String Function(AssetType) createName,
119+
) {
120+
final childAssetAbsolutePath = join(pubspecFile.parent.path, assetType.path);
121+
_Statement statement;
122+
if (assetType.isSupportedImage) {
123+
statement = _Statement(
124+
type: 'AssetGenImage',
125+
name: createName(assetType),
126+
value: 'AssetGenImage\(\'${posixStyle(assetType.path)}\'\)',
127+
isConstConstructor: true,
128+
);
129+
} else if (FileSystemEntity.isDirectorySync(childAssetAbsolutePath)) {
130+
final childClassName = '\$${assetType.path.camelCase().capitalize()}Gen';
131+
statement = _Statement(
132+
type: childClassName,
133+
name: createName(assetType),
134+
value: '$childClassName\(\)',
135+
isConstConstructor: true,
136+
);
137+
} else if (!assetType.isUnKnownMime) {
138+
final integration = integrations.firstWhere(
139+
(element) => element.mime == assetType.mime,
140+
orElse: () => null,
141+
);
142+
if (integration == null) {
143+
statement = _Statement(
144+
type: 'String',
145+
name: createName(assetType),
146+
value: '\'${posixStyle(assetType.path)}\'',
147+
isConstConstructor: false,
148+
);
149+
} else {
150+
integration.isEnabled = true;
151+
statement = _Statement(
152+
type: integration.className,
153+
name: createName(assetType),
154+
value: integration.classInstantiate(posixStyle(assetType.path)),
155+
isConstConstructor: integration.isConstConstructor,
156+
);
157+
}
158+
}
159+
return statement;
160+
}
161+
162+
/// Generate style like Assets.foo.bar
163+
String _dotDelimiterStyleDefinition(
164+
File pubspecFile,
165+
FlutterAssets assets,
166+
List<Integration> integrations,
167+
) {
168+
final buffer = StringBuffer();
169+
final assetRelativePathList = _getAssetRelativePathList(pubspecFile, assets);
170+
final assetsStaticStatements = <_Statement>[];
171+
172+
final assetTypeQueue = ListQueue<AssetType>.from(
173+
_constructAssetTree(assetRelativePathList).children);
174+
175+
while (assetTypeQueue.isNotEmpty) {
176+
final assetType = assetTypeQueue.removeFirst();
177+
final assetAbsolutePath = join(pubspecFile.parent.path, assetType.path);
178+
179+
if (FileSystemEntity.isDirectorySync(assetAbsolutePath)) {
180+
final statements = assetType.children
181+
.map(
182+
(child) => _createAssetTypeStatement(
183+
pubspecFile,
184+
child,
185+
integrations,
186+
(element) => element.baseName.camelCase(),
187+
),
188+
)
189+
.whereType<_Statement>()
190+
.toList();
191+
192+
if (assetType.isDefaultAssetsDirectory) {
193+
assetsStaticStatements.addAll(statements);
194+
} else {
195+
final className = '\$${assetType.path.camelCase().capitalize()}Gen';
196+
buffer.writeln(_directoryClassGenDefinition(className, statements));
197+
// Add this directory reference to Assets class
198+
// if we are not under the default asset folder
199+
if (dirname(assetType.path) == '.') {
200+
assetsStaticStatements.add(_Statement(
201+
type: className,
202+
name: assetType.baseName.camelCase(),
203+
value: '$className\(\)',
150204
isConstConstructor: true,
151-
);
152-
} else if (!child.isUnKnownMime) {
153-
final integration = integrations.firstWhere(
154-
(element) => element.mime == child.mime,
155-
orElse: () => null,
156-
);
157-
if (integration == null) {
158-
statement ??= _Statement(
159-
type: 'String',
160-
name: child.baseName.camelCase(),
161-
value: '\'${posixStyle(child.path)}\'',
162-
isConstConstructor: false,
163-
);
164-
} else {
165-
integration.isEnabled = true;
166-
statement = _Statement(
167-
type: integration.className,
168-
name: child.baseName.camelCase(),
169-
value: integration.classInstantiate(posixStyle(child.path)),
170-
isConstConstructor: integration.isConstConstructor,
171-
);
172-
}
205+
));
173206
}
174-
return statement;
175-
})
207+
}
208+
209+
assetTypeQueue.addAll(assetType.children);
210+
}
211+
}
212+
buffer.writeln(_assetsClassDefinition(assetsStaticStatements));
213+
return buffer.toString();
214+
}
215+
216+
/// Generate style like Assets.fooBar
217+
String _camelCaseStyleDefinition(
218+
File pubspecFile,
219+
FlutterAssets assets,
220+
List<Integration> integrations,
221+
) {
222+
return _flatStyleDefinition(
223+
pubspecFile,
224+
assets,
225+
integrations,
226+
(assetType) => withoutExtension(assetType.path)
227+
.replaceFirst(RegExp(r'asset(s)?'), '')
228+
.camelCase(),
229+
);
230+
}
231+
232+
/// Generate style like Assets.foo_bar
233+
String _snakeCaseStyleDefinition(
234+
File pubspecFile,
235+
FlutterAssets assets,
236+
List<Integration> integrations,
237+
) {
238+
return _flatStyleDefinition(
239+
pubspecFile,
240+
assets,
241+
integrations,
242+
(assetType) => withoutExtension(assetType.path)
243+
.replaceFirst(RegExp(r'asset(s)?'), '')
244+
.snakeCase(),
245+
);
246+
}
247+
248+
String _flatStyleDefinition(
249+
File pubspecFile,
250+
FlutterAssets assets,
251+
List<Integration> integrations,
252+
String Function(AssetType) createName,
253+
) {
254+
final statements = _getAssetRelativePathList(pubspecFile, assets)
255+
.distinct()
256+
.sorted()
257+
.map(
258+
(relativePath) => _createAssetTypeStatement(
259+
pubspecFile,
260+
AssetType(relativePath),
261+
integrations,
262+
createName,
263+
),
264+
)
176265
.whereType<_Statement>()
177266
.toList();
178-
return statements;
267+
return _assetsClassDefinition(statements);
179268
}
180269

181270
String _assetsClassDefinition(List<_Statement> statements) {

lib/src/generators/colors_generator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import 'package:xml/xml.dart';
77

88
import '../settings/color_path.dart';
99
import '../settings/flutter_gen.dart';
10-
import '../utils/camel_case.dart';
1110
import '../utils/color.dart';
11+
import '../utils/string.dart';
1212
import 'generator_helper.dart';
1313

1414
String generateColors(

lib/src/generators/fonts_generator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import 'package:dartx/dartx.dart';
33
import 'package:yaml/yaml.dart';
44

55
import '../settings/flutter.dart';
6-
import '../utils/camel_case.dart';
76
import '../utils/cast.dart';
7+
import '../utils/string.dart';
88
import 'generator_helper.dart';
99

1010
String generateFonts(DartFormatter formatter, FlutterFonts fonts) {

0 commit comments

Comments
 (0)