string_get_runner.dart 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import 'package:build/build.dart';
  2. import 'package:xml/xml.dart';
  3. import 'package:glob/glob.dart';
  4. import 'package:path/path.dart' as path;
  5. // 新增配置导入
  6. import 'flutter_string_get_config.dart';
  7. Builder stringXmlWatcherBuilder(BuilderOptions options) {
  8. return StringXmlWatcherBuilder();
  9. }
  10. class StringXmlWatcherBuilder implements Builder {
  11. // 从配置读取参数
  12. late final FlutterStringGetConfig _config;
  13. late final Glob _targetXmlGlob;
  14. StringXmlWatcherBuilder() {
  15. // 初始化时加载用户配置
  16. _config = FlutterStringGetConfig.fromProject();
  17. print('string_get_runner inputDir ${_config.inputDir}');
  18. print('string_get_runner outputFile ${_config.outputFile}');
  19. print('string_get_runner language ${_config.language}');
  20. // 动态生成Glob监听模式
  21. _targetXmlGlob = Glob(_config.inputDir);
  22. }
  23. @override
  24. Future<void> build(BuildStep buildStep) async {
  25. print('string_get_runner build');
  26. final xmlFiles = await buildStep.findAssets(_targetXmlGlob).toList();
  27. final (buffer, multiBuffer) = await _processXmlFiles(buildStep, xmlFiles);
  28. // 使用配置中的输出路径
  29. final outputId = AssetId(
  30. buildStep.inputId.package,
  31. _config.outputFile,
  32. );
  33. await buildStep.writeAsString(
  34. outputId, buffer.toString() + multiBuffer.toString());
  35. }
  36. Future<(StringBuffer, StringBuffer)> _processXmlFiles(BuildStep buildStep,
  37. List<AssetId> xmlFiles,) async {
  38. final buffer = StringBuffer();
  39. final multiBuffer = StringBuffer();
  40. buffer.writeln('import \'package:get/get.dart\';');
  41. buffer.writeln();
  42. buffer.writeln('class StringName {');
  43. buffer.writeln(' StringName._();');
  44. multiBuffer.writeln('class StringMultiSource {');
  45. multiBuffer.writeln(' StringMultiSource._();');
  46. multiBuffer
  47. .writeln(' static const Map<String, Map<String, String>> values = {');
  48. multiBuffer.writeln(' \'${_config.language}\': {'); // 默认基准语言
  49. // 遍历所有 XML 文件
  50. for (final file in xmlFiles) {
  51. try {
  52. final content = await buildStep.readAsString(file);
  53. final document = XmlDocument.parse(content);
  54. // 遍历所有 <string> 元素
  55. for (final element in document.findAllElements('string')) {
  56. final name = element.getAttribute('name');
  57. final value = processXmlText(element.text);
  58. if (name != null) {
  59. final camelCaseName = _toCamelCase(name);
  60. buffer.writeln(
  61. ' static final String $camelCaseName = \'$name\'.tr; // $value');
  62. multiBuffer.writeln(' \'$name\': \'$value\',');
  63. }
  64. }
  65. } catch (e) {
  66. print('❌ (string_get_runner)Error processing file ${file.path}: $e');
  67. }
  68. }
  69. multiBuffer.writeln(' },');
  70. buffer.writeln('}');
  71. multiBuffer.writeln(' };');
  72. multiBuffer.writeln('}');
  73. print('string_get_runner file generated successfully!');
  74. return (buffer, multiBuffer);
  75. }
  76. String processXmlText(String original) {
  77. return original
  78. .replaceAll('\r\n', ' ')
  79. .replaceAll('\n', ' ')
  80. .replaceAll(RegExp(r'\s+'), ' ')
  81. .trim()
  82. .replaceAll("'", "\\'");
  83. }
  84. String _toCamelCase(String snakeCase) {
  85. return snakeCase.split('_').map((word) {
  86. if (word == snakeCase.split('_').first) return word;
  87. return word[0].toUpperCase() + word.substring(1);
  88. }).join('');
  89. }
  90. @override
  91. Map<String, List<String>> get buildExtensions => {
  92. // 动态生成扩展映射
  93. r'$package$': [path.normalize(_config.outputFile)],
  94. };
  95. }