diff --git a/.gitignore b/.gitignore index 653f383..eb0cedf 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ doc/api/ .idea/ +assets diff --git a/lib/spider.dart b/lib/spider.dart index e0f9a40..4604613 100644 --- a/lib/spider.dart +++ b/lib/spider.dart @@ -19,10 +19,12 @@ import 'dart:io'; -import 'package:intl/intl.dart'; import 'package:path/path.dart' as path; -import 'package:spider/src/Configuration.dart'; +import 'package:spider/src/configuration.dart'; import 'package:spider/src/constants.dart'; +import 'package:spider/src/dart_class_generator.dart'; + +import 'src/utils.dart'; class Spider { final String _path; @@ -54,22 +56,22 @@ class Spider { } void generate_code() { - if (!Directory(configs['path']).existsSync()) { - print('Directory "${configs['path']}" does not exist!'); - exit(2); - } - var files = Directory(configs['path']) - .listSync() - .where((file) => - File(file.path).statSync().type == FileSystemEntityType.file && - _fileRegex.hasMatch(path.basename(file.path))) - .toList(); - - if (files.isEmpty) { - print('Directory ${configs['path']} does not contain any assets!'); - exit(2); - } - generate_dart_class(files); + var properties = createFileMap(configs['path']); + var generator = DartClassGenerator( + className: configs['class_name'], + prefix: configs['prefix'] ?? '', + use_underscores: configs['use_underscores'] ?? false, + useStatic: configs['use_static'] ?? true, + useConst: configs['use_const'] ?? true, + properties: properties, + ); + var data = generator.generate(); + writeToFile( + name: formatFileName(configs['file_name'] ?? configs['class_name']), + path: configs['package'] ?? '', + content: data); + print('Processed items: ${properties.length}'); + print('Dart code generated successfully'); processing = false; } @@ -79,37 +81,30 @@ class Spider { print('Configuration file created successfully'); } - void generate_dart_class(List files) { - print('Generating dart code...'); - var values = files.map((file) { - var name = _formatName(path.basenameWithoutExtension(file.path)); - var dir = path.dirname(file.path); - var filename = path.basename(file.path); - return "\tstatic const String $name = '$dir/$filename';"; - }).toList(); - var final_values = values.join('\n'); - var final_class = '''class ${configs['class_name']} { -$final_values -}'''; - if (!Directory('lib/' + configs['package']).existsSync()) { - Directory('lib/' + configs['package']).createSync(); + /// Creates map from files list of a [dir] where key is the file name without + /// extension and value is the path of the file + Map createFileMap(String dir) { + dir = dir.endsWith('/') ? dir : dir + '/'; + if (!Directory(dir).existsSync()) { + print('Directory "$dir" does not exist!'); + exit(2); } - var classFile = File(path.join('lib', configs['package'], - '${configs['class_name'].toString().toLowerCase()}.dart')); - classFile.writeAsStringSync(final_class); - print('Processed items: ${values.length}'); - print('Dart code generated successfully'); - } - - String _formatName(String name) { - name = name.replaceAll('-', '_'); - name = name.replaceAll(' ', '_'); - var tokens = name.split('_'); - var first = tokens.removeAt(0).toLowerCase(); - tokens = tokens - .map((token) => toBeginningOfSentenceCase(token)) + var files = Directory(dir) + .listSync() + .where((file) => + File(file.path) + .statSync() + .type == FileSystemEntityType.file && + _fileRegex.hasMatch(path.basename(file.path))) .toList(); - var final_name = first + tokens.join(); - return final_name; + + if (files.isEmpty) { + print('Directory $dir does not contain any assets!'); + exit(2); + } + return { + for (var file in files) + path.basenameWithoutExtension(file.path): file.path + }; } } diff --git a/lib/src/Configuration.dart b/lib/src/configuration.dart similarity index 100% rename from lib/src/Configuration.dart rename to lib/src/configuration.dart diff --git a/lib/src/constants.dart b/lib/src/constants.dart index 64ae3cd..18a09f5 100644 --- a/lib/src/constants.dart +++ b/lib/src/constants.dart @@ -24,4 +24,5 @@ class Constants { path: assets class_name: Assets package: res'''; + static final String LIB_FOLDER = 'lib'; } diff --git a/lib/src/dart_class_generator.dart b/lib/src/dart_class_generator.dart new file mode 100644 index 0000000..65bdd3a --- /dev/null +++ b/lib/src/dart_class_generator.dart @@ -0,0 +1,86 @@ +/* + * Copyright © $YEAR Birju Vachhani + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Author: Birju Vachhani +// Created Date: February 03, 2020 + +import 'package:meta/meta.dart'; + +class DartClassGenerator { + final String className; + bool useStatic = false; + bool useConst = false; + bool use_underscores = false; + String prefix = ''; + final Map properties; + + static final String _CAPITALIZE_REGEX = r'(_)(\S)'; + static final String _SPECIAL_SYMBOLS = + "[,.\\/;'\\[\\]\\-=<>?:\\\"\\{}_+!@#\$%^&*()\\\\|\\s]+"; + static final Pattern _SPECIAL_SYMBOL_REGEX = RegExp(_SPECIAL_SYMBOLS); + + DartClassGenerator( + {@required this.className, + @required this.properties, + this.use_underscores, + this.useConst, + this.useStatic, + this.prefix}); + + String generate() { + var properties_strings = properties.keys.map((name) { + var str = useStatic ? '\tstatic ' : '\t'; + str += useConst ? 'const ' : ''; + str += + 'String ${formatName(name)} = \'${formatPath(properties[name])}\';'; + return str; + }).toList(); + var dart_class = '''// Generated by spider on ${DateTime.now()} + +class ${className} { +${properties_strings.join('\n')} +}'''; + return dart_class; + } + + // Formats variable name to be pascal case or with underscores + // if [use_underscores] is true + String formatName(String name) { + // appending prefix if provided any + name = (prefix.isEmpty ? '' : prefix + '_') + name; + name = name + // adds preceding _ for capital letters and lowers them + .replaceAllMapped( + RegExp(r'[A-Z]+'), (match) => '_' + match.group(0).toLowerCase()) + // replaces all the special characters with _ + .replaceAll(_SPECIAL_SYMBOL_REGEX, '_') + // removes _ in the beginning of the name + .replaceFirst(RegExp(r'^_+'), '') + // removes any numbers in the beginning of the name + .replaceFirst(RegExp(r'^[0-9]+'), '') + // lowers the first character of the string + .replaceFirstMapped( + RegExp(r'^[A-Za-z]'), (match) => match.group(0).toLowerCase()); + return use_underscores + ? name + : name + // removes _ and capitalize the next character of the _ + .replaceAllMapped(RegExp(_CAPITALIZE_REGEX), + (match) => match.group(2).toUpperCase()); + } + + String formatPath(String value) => value.replaceAll('\\', '/'); +} diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 28af134..9b25946 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -19,7 +19,27 @@ import 'dart:io'; +import 'package:path/path.dart' as p; + +import 'constants.dart'; + File file(String path) { var file = File(path); return file.existsSync() ? file : null; } + +String formatFileName(String name) { + name = name + .replaceAllMapped( + RegExp(r'[A-Z]+'), (match) => '_' + match.group(0).toLowerCase()) + .replaceFirst(RegExp(r'^_+'), ''); + return name.contains('.dart') ? name : name + '.dart'; +} + +void writeToFile({String name, String path, String content}) { + if (!Directory(p.join(Constants.LIB_FOLDER, path)).existsSync()) { + Directory(p.join(Constants.LIB_FOLDER, path)).createSync(recursive: true); + } + var classFile = File(p.join(Constants.LIB_FOLDER, path, name)); + classFile.writeAsStringSync(content); +} diff --git a/spider.yaml b/spider.yaml index b09c6ec..82f0530 100644 --- a/spider.yaml +++ b/spider.yaml @@ -1,4 +1,8 @@ -# Configuration file for spider -path: assets +# Sample Configuration file for spider + +# where to locate images +path: assets/images +# Name of the generated class class_name: Assets +# where to generate in the lib folder? package: res \ No newline at end of file