Skip to content

Commit

Permalink
✨ add class generator code with more robust properties name
Browse files Browse the repository at this point in the history
♻️ refactor code

Signed-off-by: birjuvachhani <[email protected]>
  • Loading branch information
BirjuVachhani committed Feb 3, 2020
1 parent 930fe74 commit ada871e
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 50 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ doc/api/

.idea/

assets
91 changes: 43 additions & 48 deletions lib/spider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -79,37 +81,30 @@ class Spider {
print('Configuration file created successfully');
}

void generate_dart_class(List<FileSystemEntity> files) {
print('Generating dart code...');
var values = files.map<String>((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<String, String> 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<String>((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
};
}
}
File renamed without changes.
1 change: 1 addition & 0 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ class Constants {
path: assets
class_name: Assets
package: res''';
static final String LIB_FOLDER = 'lib';
}
86 changes: 86 additions & 0 deletions lib/src/dart_class_generator.dart
Original file line number Diff line number Diff line change
@@ -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<String, Object> 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<String>((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('\\', '/');
}
20 changes: 20 additions & 0 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
8 changes: 6 additions & 2 deletions spider.yaml
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit ada871e

Please sign in to comment.