Sfoglia il codice sorgente

Merge branch 'refs/heads/v0.0.4'

# Conflicts:
#	README.md
zk 8 mesi fa
parent
commit
49672a25eb
5 ha cambiato i file con 151 aggiunte e 73 eliminazioni
  1. 9 1
      CHANGELOG.md
  2. 1 0
      README.md
  3. 74 0
      lib/flutter_string_get_config.dart
  4. 60 27
      lib/string_get_runner.dart
  5. 7 45
      pubspec.yaml

+ 9 - 1
CHANGELOG.md

@@ -1,3 +1,11 @@
 ## 0.0.1
 
-* TODO: Describe initial release.
+* 增加 build_runner build/watch时自动生成string.gen.dart文件的功能
+
+## 0.0.3
+
+* 增加可配置输入输出目录功能
+
+## 0.0.4
+
+* 增加配置语言类型功能

+ 1 - 0
README.md

@@ -11,6 +11,7 @@
 flutter_string_get:
   input: assets/string/base/*.xml           # 输入目录
   output: lib/resource/string.gen.dart      # 输出文件
+  language: 'zh_CN'                         # 语言类型 默认为中文
 ```
 
 ### 清理build_runner命令

+ 74 - 0
lib/flutter_string_get_config.dart

@@ -0,0 +1,74 @@
+import 'package:yaml/yaml.dart';
+import 'dart:io';
+import 'package:path/path.dart' as path;
+
+class FlutterStringGetConfig {
+  String inputDir;
+  String outputFile;
+  String language;
+
+  FlutterStringGetConfig({
+    required this.inputDir,
+    required this.outputFile,
+    this.language = 'zh_CN',
+  });
+
+  factory FlutterStringGetConfig.defaults() {
+    return FlutterStringGetConfig(
+      inputDir: 'assets/string/base/*.xml',
+      outputFile: 'lib/resource/string.gen.dart',
+      language: 'zh_CN',
+    );
+  }
+
+  factory FlutterStringGetConfig.fromProject() {
+    try {
+      final getConfig = FlutterStringGetConfig.defaults();
+      final file = File('pubspec.yaml');
+      if (!file.existsSync()) return getConfig;
+
+      final yamlContent = file.readAsStringSync();
+      final yaml = loadYaml(yamlContent);
+      final config = yaml['flutter_string_get'];
+
+      if (config == null) return getConfig;
+      String input = _normalizePath(config['input']?.toString());
+      String output = _normalizePath(config['output']?.toString());
+      String language = _normalizePath(config['language']?.toString());
+
+      if (input.isNotEmpty) {
+        getConfig.inputDir = input;
+      }
+      if (output.isNotEmpty) {
+        getConfig.outputFile = output;
+      }
+      if (language.isNotEmpty) {
+        getConfig.language = language;
+      }
+      return getConfig;
+    } catch (e) {
+      print('Error parsing flutter_string_get config: $e');
+      return FlutterStringGetConfig.defaults();
+    }
+  }
+
+  static String _normalizePath(String? rawPath, {bool isDirectory = false}) {
+    if (rawPath == null || rawPath.isEmpty) return '';
+
+    // 强制替换所有反斜杠为正斜杠(跨平台兼容)
+    final unifiedPath = rawPath.replaceAll(r'\', '/');
+
+    // 保留目录末尾的斜杠
+    bool hasTrailingSlash = unifiedPath.endsWith('/');
+    String normalized = unifiedPath;
+
+    // 仅处理路径中的 `.` 和 `..`
+    normalized = path.posix.normalize(normalized); // 使用 posix 风格的 normalize
+
+    if (isDirectory && !hasTrailingSlash) {
+      normalized += '/';
+    }
+
+    return normalized;
+  }
+}

+ 60 - 27
lib/string_get_runner.dart

@@ -1,57 +1,81 @@
 import 'package:build/build.dart';
 import 'package:xml/xml.dart';
 import 'package:glob/glob.dart';
+import 'package:path/path.dart' as path;
+
+// 新增配置导入
+import 'flutter_string_get_config.dart';
 
 Builder stringXmlWatcherBuilder(BuilderOptions options) {
   return StringXmlWatcherBuilder();
 }
 
 class StringXmlWatcherBuilder implements Builder {
-  static const _baseType = 'zh_CN';
-  static final _targetXmlGlob = Glob('assets/string/base/*.xml');
+  // 从配置读取参数
+  late final FlutterStringGetConfig _config;
+  late final Glob _targetXmlGlob;
+
+  StringXmlWatcherBuilder() {
+    // 初始化时加载用户配置
+    _config = FlutterStringGetConfig.fromProject();
+
+    print('string_get_runner inputDir ${_config.inputDir}');
+    print('string_get_runner outputFile ${_config.outputFile}');
+    print('string_get_runner language ${_config.language}');
+    // 动态生成Glob监听模式
+    _targetXmlGlob = Glob(_config.inputDir);
+  }
 
   @override
   Future<void> build(BuildStep buildStep) async {
+    print('string_get_runner build');
     final xmlFiles = await buildStep.findAssets(_targetXmlGlob).toList();
     final (buffer, multiBuffer) = await _processXmlFiles(buildStep, xmlFiles);
 
+    // 使用配置中的输出路径
     final outputId = AssetId(
       buildStep.inputId.package,
-      'lib/resource/string.gen.dart',
+      _config.outputFile,
     );
-    await buildStep.writeAsString(outputId, buffer.toString() + multiBuffer.toString());
+    await buildStep.writeAsString(
+        outputId, buffer.toString() + multiBuffer.toString());
   }
 
-  Future<(StringBuffer, StringBuffer)> _processXmlFiles(
-      BuildStep buildStep,
-      List<AssetId> xmlFiles,
-      ) async {
+  Future<(StringBuffer, StringBuffer)> _processXmlFiles(BuildStep buildStep,
+      List<AssetId> xmlFiles,) async {
     final buffer = StringBuffer();
     final multiBuffer = StringBuffer();
+
     buffer.writeln('import \'package:get/get.dart\';');
     buffer.writeln();
     buffer.writeln('class StringName {');
     buffer.writeln('  StringName._();');
+
     multiBuffer.writeln('class StringMultiSource {');
     multiBuffer.writeln('  StringMultiSource._();');
-    multiBuffer.writeln('  static const Map<String, Map<String, String>> values = {');
-
-    multiBuffer.writeln('    \'${_baseType}\': {');
+    multiBuffer
+        .writeln('  static const Map<String, Map<String, String>> values = {');
+    multiBuffer.writeln('    \'${_config.language}\': {'); // 默认基准语言
 
+    // 遍历所有 XML 文件
     for (final file in xmlFiles) {
-      final content = await buildStep.readAsString(file);
-      final document = XmlDocument.parse(content);
-
-      for (final element in document.findAllElements('string')) {
-        final name = element.getAttribute('name');
-        final value = _sanitizeValue(element.text);
-
-        if (name != null) {
-          final camelCaseName = _toCamelCase(name);
-          buffer.writeln(
-              '  static final String $camelCaseName = \'$name\'.tr;// $value');
-          multiBuffer.writeln('      \'$name\': \'$value\',');
+      try {
+        final content = await buildStep.readAsString(file);
+        final document = XmlDocument.parse(content);
+        // 遍历所有 <string> 元素
+        for (final element in document.findAllElements('string')) {
+          final name = element.getAttribute('name');
+          final value = processXmlText(element.text);
+
+          if (name != null) {
+            final camelCaseName = _toCamelCase(name);
+            buffer.writeln(
+                '  static final String $camelCaseName = \'$name\'.tr; // $value');
+            multiBuffer.writeln('      \'$name\': \'$value\',');
+          }
         }
+      } catch (e) {
+        print('❌ (string_get_runner)Error processing file ${file.path}: $e');
       }
     }
 
@@ -60,10 +84,18 @@ class StringXmlWatcherBuilder implements Builder {
     multiBuffer.writeln('  };');
     multiBuffer.writeln('}');
 
+    print('string_get_runner file generated successfully!');
     return (buffer, multiBuffer);
   }
 
-  String _sanitizeValue(String value) => value.replaceAll('\r\n', '').trim();
+  String processXmlText(String original) {
+    return original
+        .replaceAll('\r\n', ' ')
+        .replaceAll('\n', ' ')
+        .replaceAll(RegExp(r'\s+'), ' ')
+        .trim()
+        .replaceAll("'", "\\'");
+  }
 
   String _toCamelCase(String snakeCase) {
     return snakeCase.split('_').map((word) {
@@ -74,6 +106,7 @@ class StringXmlWatcherBuilder implements Builder {
 
   @override
   Map<String, List<String>> get buildExtensions => {
-    r'$package$': ['lib/resource/string.gen.dart'],
-  };
-}
+        // 动态生成扩展映射
+        r'$package$': [path.normalize(_config.outputFile)],
+      };
+}

+ 7 - 45
pubspec.yaml

@@ -1,59 +1,21 @@
 name: string_get_runner
-description: "getx插件 多语言字符串生成工具"
-version: 0.0.1
-homepage:
+description: Multilingual String Generation Plugin for GetX
+version: 0.0.4
+homepage: http://git.atmob.com/Atmob-Flutter/string_get_runner
+repository: http://git.atmob.com/Atmob-Flutter/string_get_runner
+documentation: http://git.atmob.com/Atmob-Flutter/string_get_runner
 
 environment:
-  sdk: ^3.5.0
-  flutter: ">=1.17.0"
+  sdk: ^3.0.0
 
 dependencies:
-  flutter:
-    sdk: flutter
-
   build: ^2.0.0
   yaml: ^3.0.0
   xml: ^6.0.0
 
 
 dev_dependencies:
-  flutter_test:
-    sdk: flutter
-  flutter_lints: ^4.0.0
-
-# For information on the generic Dart part of this file, see the
-# following page: https://dart.dev/tools/pub/pubspec
+  lints: any
 
-# The following section is specific to Flutter packages.
-flutter:
 
-  # To add assets to your package, add an assets section, like this:
-  # assets:
-  #   - images/a_dot_burr.jpeg
-  #   - images/a_dot_ham.jpeg
-  #
-  # For details regarding assets in packages, see
-  # https://flutter.dev/to/asset-from-package
-  #
-  # An image asset can refer to one or more resolution-specific "variants", see
-  # https://flutter.dev/to/resolution-aware-images
 
-  # To add custom fonts to your package, add a fonts section here,
-  # in this "flutter" section. Each entry in this list should have a
-  # "family" key with the font family name, and a "fonts" key with a
-  # list giving the asset and other descriptors for the font. For
-  # example:
-  # fonts:
-  #   - family: Schyler
-  #     fonts:
-  #       - asset: fonts/Schyler-Regular.ttf
-  #       - asset: fonts/Schyler-Italic.ttf
-  #         style: italic
-  #   - family: Trajan Pro
-  #     fonts:
-  #       - asset: fonts/TrajanPro.ttf
-  #       - asset: fonts/TrajanPro_Bold.ttf
-  #         weight: 700
-  #
-  # For details regarding fonts in packages, see
-  # https://flutter.dev/to/font-from-package