Skip to content

Specify generated assets style #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Sep 10, 2020
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,5 @@ node_modules/

## Test coverage
coverage/
test/
test/.test_coverage.dart

21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,27 @@ final svg = SvgPicture.asset(Assets.images.icons.paint);
final json = await rootBundle.loadString(Assets.json.fruits);
```

[FlutterGen] also support generating other style of `Assets` class:

```yaml
# pubspec.yaml
flutter_gen:

assets:
# Assets.imagesChip
style: camel-case

# Assets.images_chip
# style: snake-case

# Assets.images.chip (default style)
# style: dot-delimiter

flutter:
assets:
- assets/images/chip.png
```

The root directory will be omitted if it is either **`assets`** or **`asset`**.

```
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void main() {
Assets.images.icons.fuchsia.svg(),
Assets.images.icons.paint.svg(
width: 120,
height: 120
height: 120,
),
Assets.pictures.chip5.image(
width: 120,
Expand Down
253 changes: 171 additions & 82 deletions lib/src/generators/assets_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,50 @@ import 'dart:io';

import 'package:dart_style/dart_style.dart';
import 'package:path/path.dart';
import 'package:dartx/dartx.dart';

import '../settings/asset_type.dart';
import '../settings/flutter.dart';
import '../settings/flutter_gen.dart';
import '../utils/camel_case.dart';
import '../utils/string.dart';
import 'generator_helper.dart';
import 'integrations/integration.dart';
import 'integrations/svg_integration.dart';

String generateAssets(File pubspecFile, DartFormatter formatter,
FlutterGen flutterGen, FlutterAssets assets) {
String generateAssets(
File pubspecFile,
DartFormatter formatter,
FlutterGen flutterGen,
FlutterAssets assets,
) {
assert(assets != null && assets.hasAssets,
throw 'The value of "flutter/assets:" is incorrect.');

final importsBuffer = StringBuffer();
final classesBuffer = StringBuffer();

final assetRelativePathList = _getAssetRelativePathList(pubspecFile, assets);
final assetTypeQueue = ListQueue<AssetType>.from(
_constructAssetTree(assetRelativePathList).children);
final assetsStaticStatements = <_Statement>[];

final integrations = <Integration>[];
if (flutterGen != null &&
flutterGen.hasIntegrations &&
flutterGen.integrations.hasFlutterSvg) {
integrations.add(SvgIntegration());
}

while (assetTypeQueue.isNotEmpty) {
final assetType = assetTypeQueue.removeFirst();
final assetAbsolutePath = join(pubspecFile.parent.path, assetType.path);

if (FileSystemEntity.isDirectorySync(assetAbsolutePath)) {
final statements = _createDirectoryClassGenStatements(
pubspecFile, assetType, integrations);

if (assetType.isDefaultAssetsDirectory) {
assetsStaticStatements.addAll(statements);
} else {
final className = '\$${assetType.path.camelCase().capitalize()}Gen';
classesBuffer
.writeln(_directoryClassGenDefinition(className, statements));
// Add this directory reference to Assets class
// if we are not under the default asset folder
if (dirname(assetType.path) == '.') {
assetsStaticStatements.add(_Statement(
type: className,
name: assetType.baseName.camelCase(),
value: '$className\(\)',
isConstConstructor: true,
));
}
}

assetTypeQueue.addAll(assetType.children);
}
if (flutterGen == null ||
!flutterGen.hasAssets ||
flutterGen.assets.isDefaultStyle) {
classesBuffer.writeln(
_dotDelimiterStyleDefinition(pubspecFile, assets, integrations));
} else if (flutterGen.assets.isSnakeCaseStyle) {
classesBuffer
.writeln(_snakeCaseStyleDefinition(pubspecFile, assets, integrations));
} else if (flutterGen.assets.isCamelCaseStyle) {
classesBuffer
.writeln(_camelCaseStyleDefinition(pubspecFile, assets, integrations));
} else {
throw 'The value of "flutter_gen/assets/style." is incorrect.';
}

classesBuffer.writeln(_assetsClassDefinition(assetsStaticStatements));
classesBuffer.writeln(_assetGenImageClassDefinition);

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

List<_Statement> _createDirectoryClassGenStatements(
File pubspecFile, AssetType assetType, List<Integration> integrations) {
final statements = assetType.children
.map((child) {
final childAssetAbsolutePath =
join(pubspecFile.parent.path, child.path);
_Statement statement;
if (child.isSupportedImage) {
statement = _Statement(
type: 'AssetGenImage',
name: child.baseName.camelCase(),
value: 'AssetGenImage\(\'${posixStyle(child.path)}\'\)',
isConstConstructor: true,
);
} else if (FileSystemEntity.isDirectorySync(childAssetAbsolutePath)) {
final childClassName = '\$${child.path.camelCase().capitalize()}Gen';
statement = _Statement(
type: childClassName,
name: child.baseName.camelCase(),
value: '$childClassName\(\)',
_Statement _createAssetTypeStatement(
File pubspecFile,
AssetType assetType,
List<Integration> integrations,
String Function(AssetType) createName,
) {
final childAssetAbsolutePath = join(pubspecFile.parent.path, assetType.path);
_Statement statement;
if (assetType.isSupportedImage) {
statement = _Statement(
type: 'AssetGenImage',
name: createName(assetType),
value: 'AssetGenImage\(\'${posixStyle(assetType.path)}\'\)',
isConstConstructor: true,
);
} else if (FileSystemEntity.isDirectorySync(childAssetAbsolutePath)) {
final childClassName = '\$${assetType.path.camelCase().capitalize()}Gen';
statement = _Statement(
type: childClassName,
name: createName(assetType),
value: '$childClassName\(\)',
isConstConstructor: true,
);
} else if (!assetType.isUnKnownMime) {
final integration = integrations.firstWhere(
(element) => element.mime == assetType.mime,
orElse: () => null,
);
if (integration == null) {
statement = _Statement(
type: 'String',
name: createName(assetType),
value: '\'${posixStyle(assetType.path)}\'',
isConstConstructor: false,
);
} else {
integration.isEnabled = true;
statement = _Statement(
type: integration.className,
name: createName(assetType),
value: integration.classInstantiate(posixStyle(assetType.path)),
isConstConstructor: integration.isConstConstructor,
);
}
}
return statement;
}

/// Generate style like Assets.foo.bar
String _dotDelimiterStyleDefinition(
File pubspecFile,
FlutterAssets assets,
List<Integration> integrations,
) {
final buffer = StringBuffer();
final assetRelativePathList = _getAssetRelativePathList(pubspecFile, assets);
final assetsStaticStatements = <_Statement>[];

final assetTypeQueue = ListQueue<AssetType>.from(
_constructAssetTree(assetRelativePathList).children);

while (assetTypeQueue.isNotEmpty) {
final assetType = assetTypeQueue.removeFirst();
final assetAbsolutePath = join(pubspecFile.parent.path, assetType.path);

if (FileSystemEntity.isDirectorySync(assetAbsolutePath)) {
final statements = assetType.children
.map(
(child) => _createAssetTypeStatement(
pubspecFile,
child,
integrations,
(element) => element.baseName.camelCase(),
),
)
.whereType<_Statement>()
.toList();

if (assetType.isDefaultAssetsDirectory) {
assetsStaticStatements.addAll(statements);
} else {
final className = '\$${assetType.path.camelCase().capitalize()}Gen';
buffer.writeln(_directoryClassGenDefinition(className, statements));
// Add this directory reference to Assets class
// if we are not under the default asset folder
if (dirname(assetType.path) == '.') {
assetsStaticStatements.add(_Statement(
type: className,
name: assetType.baseName.camelCase(),
value: '$className\(\)',
isConstConstructor: true,
);
} else if (!child.isUnKnownMime) {
final integration = integrations.firstWhere(
(element) => element.mime == child.mime,
orElse: () => null,
);
if (integration == null) {
statement ??= _Statement(
type: 'String',
name: child.baseName.camelCase(),
value: '\'${posixStyle(child.path)}\'',
isConstConstructor: false,
);
} else {
integration.isEnabled = true;
statement = _Statement(
type: integration.className,
name: child.baseName.camelCase(),
value: integration.classInstantiate(posixStyle(child.path)),
isConstConstructor: integration.isConstConstructor,
);
}
));
}
return statement;
})
}

assetTypeQueue.addAll(assetType.children);
}
}
buffer.writeln(_assetsClassDefinition(assetsStaticStatements));
return buffer.toString();
}

/// Generate style like Assets.fooBar
String _camelCaseStyleDefinition(
File pubspecFile,
FlutterAssets assets,
List<Integration> integrations,
) {
return _flatStyleDefinition(
pubspecFile,
assets,
integrations,
(assetType) => withoutExtension(assetType.path)
.replaceFirst(RegExp(r'asset(s)?'), '')
.camelCase(),
);
}

/// Generate style like Assets.foo_bar
String _snakeCaseStyleDefinition(
File pubspecFile,
FlutterAssets assets,
List<Integration> integrations,
) {
return _flatStyleDefinition(
pubspecFile,
assets,
integrations,
(assetType) => withoutExtension(assetType.path)
.replaceFirst(RegExp(r'asset(s)?'), '')
.snakeCase(),
);
}

String _flatStyleDefinition(
File pubspecFile,
FlutterAssets assets,
List<Integration> integrations,
String Function(AssetType) createName,
) {
final statements = _getAssetRelativePathList(pubspecFile, assets)
.distinct()
.sorted()
.map(
(relativePath) => _createAssetTypeStatement(
pubspecFile,
AssetType(relativePath),
integrations,
createName,
),
)
.whereType<_Statement>()
.toList();
return statements;
return _assetsClassDefinition(statements);
}

String _assetsClassDefinition(List<_Statement> statements) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/generators/colors_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import 'package:xml/xml.dart';

import '../settings/color_path.dart';
import '../settings/flutter_gen.dart';
import '../utils/camel_case.dart';
import '../utils/color.dart';
import '../utils/string.dart';
import 'generator_helper.dart';

String generateColors(
Expand Down
2 changes: 1 addition & 1 deletion lib/src/generators/fonts_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import 'package:dartx/dartx.dart';
import 'package:yaml/yaml.dart';

import '../settings/flutter.dart';
import '../utils/camel_case.dart';
import '../utils/cast.dart';
import '../utils/string.dart';
import 'generator_helper.dart';

String generateFonts(DartFormatter formatter, FlutterFonts fonts) {
Expand Down
Loading