flr 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ module Flr
2
+ # Flr支持的图片文件类型
3
+ IMAGE_FILE_TYPES = %w(.png .jpg .jpeg .gif .webp .icon .bmp .wbmp .svg)
4
+ # Flr支持的文本文件类型
5
+ TEXT_FILE_TYPES = %w(.txt .json .yaml .xml)
6
+ # Flr支持的字体文件类型
7
+ FONT_FILE_TYPES = %w(.ttf .otf .ttc)
8
+
9
+ # Flr优先考虑的非SVG类图片文件类型
10
+ PRIOR_NON_SVG_IMAGE_FILE_TYPE = ".png"
11
+ # Flr优先考虑的SVG类图片文件类型
12
+ PRIOR_SVG_IMAGE_FILE_TYPE = ".svg"
13
+ # Flr优先考虑的文本文件类型
14
+ # 当前值为 ".*", 意味所有文本文件类型的优先级都一样
15
+ PRIOR_TEXT_FILE_TYPE = ".*"
16
+ # Flr优先考虑的字体文件类型
17
+ # 当前值为 ".*", 意味所有文本文件类型的优先级都一样
18
+ PRIOR_FONT_FILE_TYPE = ".*"
19
+
20
+ # dartfmt工具的默认行长
21
+ DARTFMT_LINE_LENGTH = 80
22
+ end
@@ -0,0 +1,102 @@
1
+ # 参考:https://gist.github.com/lnznt/2663516
2
+ class String
3
+ def black
4
+ "\e[30m#{self}\e[m"
5
+ end
6
+
7
+ def red
8
+ "\e[31m#{self}\e[m"
9
+ end
10
+
11
+ def green
12
+ "\e[32m#{self}\e[m"
13
+ end
14
+
15
+ def yellow
16
+ "\e[33m#{self}\e[m"
17
+ end
18
+
19
+ def blue
20
+ "\e[34m#{self}\e[m"
21
+ end
22
+
23
+ def magenta
24
+ "\e[35m#{self}\e[m"
25
+ end
26
+
27
+ def cyan
28
+ "\e[36m#{self}\e[m"
29
+ end
30
+
31
+ def white
32
+ "\e[37m#{self}\e[m"
33
+ end
34
+
35
+ def bg_black
36
+ "\e[40m#{self}\e[m"
37
+ end
38
+
39
+ def bg_red
40
+ "\e[41m#{self}\e[m"
41
+ end
42
+
43
+ def bg_green
44
+ "\e[42m#{self}\e[m"
45
+ end
46
+
47
+ def bg_yellow
48
+ "\e[43m#{self}\e[m"
49
+ end
50
+
51
+ def bg_blue
52
+ "\e[44m#{self}\e[m"
53
+ end
54
+
55
+ def bg_magenta
56
+ "\e[45m#{self}\e[m"
57
+ end
58
+
59
+ def bg_cyan
60
+ "\e[46m#{self}\e[m"
61
+ end
62
+
63
+ def bg_white
64
+ "\e[47m#{self}\e[m"
65
+ end
66
+
67
+ def bold
68
+ "\e[1m#{self}\e[m"
69
+ end
70
+
71
+ def bright
72
+ "\e[2m#{self}\e[m"
73
+ end
74
+
75
+ def italic
76
+ "\e[3m#{self}\e[m"
77
+ end
78
+
79
+ def underline
80
+ "\e[4m#{self}\e[m"
81
+ end
82
+
83
+ def blink
84
+ "\e[5m#{self}\e[m"
85
+ end
86
+
87
+ def reverse_color
88
+ "\e[7m#{self}\e[m"
89
+ end
90
+
91
+ def error_style
92
+ self.red
93
+ end
94
+
95
+ def warning_style
96
+ self.yellow
97
+ end
98
+
99
+ def tips_style
100
+ self.green
101
+ end
102
+ end
@@ -0,0 +1,94 @@
1
+ require 'yaml'
2
+ require 'flr/constant'
3
+
4
+ module Flr
5
+
6
+ # 资产相关的工具类方法
7
+ class AssetUtil
8
+
9
+ # generate_image_assets(legal_image_file_array, resource_dir, package_name) -> image_asset_array
10
+ #
11
+ # 遍历指定资源目录下扫描找到的legal_image_file数组生成image_asset数组
12
+ #
13
+ # === Examples
14
+ # legal_image_file_array = ["lib/assets/images/test.png"]
15
+ # resource_dir = "lib/assets/images"
16
+ # package_name = "flutter_r_demo"
17
+ # image_asset_array = ["packages/flutter_r_demo/assets/images/test.png"]
18
+ #
19
+ def self.generate_image_assets(legal_image_file_array, resource_dir, package_name)
20
+
21
+ image_asset_array = []
22
+
23
+ # implied_resource_dir = "assets/images"
24
+ implied_resource_dir = resource_dir
25
+ if resource_dir.include?("lib/")
26
+ implied_resource_dir = resource_dir.split("lib/")[1]
27
+ end
28
+
29
+ legal_image_file_array.each do |legal_image_file|
30
+ file_basename = File.basename(legal_image_file)
31
+ image_asset = "packages/#{package_name}/#{implied_resource_dir}/#{file_basename}"
32
+ image_asset_array.push(image_asset)
33
+ end
34
+
35
+ return image_asset_array
36
+ end
37
+
38
+ # generate_text_assets(legal_text_file_array, resource_dir, package_name) -> text_asset_array
39
+ #
40
+ # 遍历指定资源目录下扫描找到的legal_text_file数组生成text_asset数组
41
+ #
42
+ # === Examples
43
+ # legal_text_file_array = ["lib/assets/jsons/test.json"]
44
+ # resource_dir = "lib/assets/jsons"
45
+ # package_name = "flutter_r_demo"
46
+ # text_asset_array = ["packages/flutter_r_demo/assets/jsons/test.json"]
47
+ #
48
+ def self.generate_text_assets(legal_text_file_array, resource_dir, package_name)
49
+
50
+ text_asset_array = []
51
+
52
+ legal_text_file_array.each do |legal_text_file|
53
+ # implied_resource_file = "assets/jsons/test.json"
54
+ implied_resource_file = legal_text_file
55
+ if legal_text_file.include?("lib/")
56
+ implied_resource_file = legal_text_file.split("lib/")[1]
57
+ end
58
+ text_asset = "packages/#{package_name}/#{implied_resource_file}"
59
+ text_asset_array.push(text_asset)
60
+ end
61
+
62
+ return text_asset_array
63
+ end
64
+
65
+ # generate_font_asset_configs(legal_font_file_array, resource_dir, package_name) -> font_asset_config_array
66
+ #
67
+ # 遍历指定资源目录下扫描找到的legal_font_file数组生成font_asset_config数组
68
+ #
69
+ # === Examples
70
+ # legal_font_file_array = ["lib/assets/fonts/Amiri/Amiri-Regular.ttf"]
71
+ # resource_dir = "lib/assets/fonts/Amiri"
72
+ # package_name = "flutter_r_demo"
73
+ # font_asset_config_array -> [{"asset": "packages/flutter_r_demo/assets/fonts/Amiri/Amiri-Regular.ttf"}]
74
+ #
75
+ def self.generate_font_asset_configs(legal_font_file_array, resource_dir, package_name)
76
+
77
+ font_asset_config_array = []
78
+
79
+ legal_font_file_array.each do |legal_font_file|
80
+ # implied_resource_file = "assets/fonts/Amiri/Amiri-Regular.ttf"
81
+ implied_resource_file = legal_font_file
82
+ if legal_font_file.include?("lib/")
83
+ implied_resource_file = legal_font_file.split("lib/")[1]
84
+ end
85
+ font_asset = "packages/#{package_name}/#{implied_resource_file}"
86
+ font_asset_config = Hash["asset" => font_asset]
87
+ font_asset_config_array.push(font_asset_config)
88
+ end
89
+
90
+ return font_asset_config_array
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,482 @@
1
+ require 'flr/constant'
2
+
3
+ module Flr
4
+
5
+ # 代码生成相关的工具类方法
6
+ class CodeUtil
7
+
8
+ # generate_R_class(package_name) -> string
9
+ #
10
+ # 根据模板生成 R class 的代码
11
+ #
12
+ def self.generate_R_class(package_name)
13
+ code = <<-CODE
14
+ // IT IS GENERATED BY FLR - DO NOT MODIFY BY HAND
15
+ // YOU CAN GET MORE DETAILS ABOUT FLR FROM:
16
+ // - https://github.com/Fly-Mix/flr-cli
17
+ // - https://github.com/Fly-Mix/flr-vscode-extension
18
+ // - https://github.com/Fly-Mix/flr-as-plugin
19
+ //
20
+
21
+ // ignore: unused_import
22
+ import 'package:flutter/widgets.dart';
23
+ // ignore: unused_import
24
+ import 'package:flutter/services.dart' show rootBundle;
25
+ // ignore: unused_import
26
+ import 'package:path/path.dart' as path;
27
+ // ignore: unused_import
28
+ import 'package:flutter_svg/flutter_svg.dart';
29
+ // ignore: unused_import
30
+ import 'package:r_dart_library/asset_svg.dart';
31
+
32
+ /// This `R` class is generated and contains references to static asset resources.
33
+ class R {
34
+ /// package name: #{package_name}
35
+ static const package = "#{package_name}";
36
+
37
+ /// This `R.image` struct is generated, and contains static references to static non-svg type image asset resources.
38
+ static const image = _R_Image();
39
+
40
+ /// This `R.svg` struct is generated, and contains static references to static svg type image asset resources.
41
+ static const svg = _R_Svg();
42
+
43
+ /// This `R.text` struct is generated, and contains static references to static text asset resources.
44
+ static const text = _R_Text();
45
+
46
+ /// This `R.fontFamily` struct is generated, and contains static references to static font asset resources.
47
+ static const fontFamily = _R_FontFamily();
48
+ }
49
+ CODE
50
+
51
+ return code
52
+ end
53
+
54
+
55
+ # generate_AssetResource_class(package_name) -> string
56
+ #
57
+ # 根据模板生成 AssetResource class 的代码
58
+ #
59
+ def self.generate_AssetResource_class(package_name)
60
+ code = <<-CODE
61
+ /// Asset resource’s metadata class.
62
+ /// For example, here is the metadata of `packages/flutter_demo/assets/images/example.png` asset:
63
+ /// - packageName:flutter_demo
64
+ /// - assetName:assets/images/example.png
65
+ /// - fileDirname:assets/images
66
+ /// - fileBasename:example.png
67
+ /// - fileBasenameNoExtension:example
68
+ /// - fileExtname:.png
69
+ class AssetResource {
70
+ /// Creates an object to hold the asset resource’s metadata.
71
+ const AssetResource(this.assetName, {this.packageName}) : assert(assetName != null);
72
+
73
+ /// The name of the main asset from the set of asset resources to choose from.
74
+ final String assetName;
75
+
76
+ /// The name of the package from which the asset resource is included.
77
+ final String packageName;
78
+
79
+ /// The name used to generate the key to obtain the asset resource. For local assets
80
+ /// this is [assetName], and for assets from packages the [assetName] is
81
+ /// prefixed 'packages/<package_name>/'.
82
+ String get keyName => packageName == null ? assetName : "packages/$packageName/$assetName";
83
+
84
+ /// The file basename of the asset resource.
85
+ String get fileBasename {
86
+ final basename = path.basename(assetName);
87
+ return basename;
88
+ }
89
+
90
+ /// The no extension file basename of the asset resource.
91
+ String get fileBasenameNoExtension {
92
+ final basenameWithoutExtension = path.basenameWithoutExtension(assetName);
93
+ return basenameWithoutExtension;
94
+ }
95
+
96
+ /// The file extension name of the asset resource.
97
+ String get fileExtname {
98
+ final extension = path.extension(assetName);
99
+ return extension;
100
+ }
101
+
102
+ /// The directory path name of the asset resource.
103
+ String get fileDirname {
104
+ var dirname = assetName;
105
+ if (packageName != null) {
106
+ final packageStr = "packages/$packageName/";
107
+ dirname = dirname.replaceAll(packageStr, "");
108
+ }
109
+ final filenameStr = "$fileBasename/";
110
+ dirname = dirname.replaceAll(filenameStr, "");
111
+ return dirname;
112
+ }
113
+ }
114
+ CODE
115
+
116
+ return code
117
+ end
118
+
119
+ # generate_asset_id (asset, prior_asset_type) -> string
120
+ #
121
+ # - prior_asset_type: 优先的资源类型;默认值为 ".*",意味当前不存在任何优先的资源类型
122
+ # 对于优先的资源类型,其 asset_id 不会携带类型信息,详细见例子
123
+ #
124
+ # 为当前 asset 生成 asset_id(资产ID);asset_id 一般为 asset 的 file_basename_no_extension;
125
+ # 但是为了保证 asset_id 的健壮性,需要对 file_basename_no_extension 做以下加工处理:
126
+ # - 处理非法字符:把除了字母(a-z, A-Z)、数字(0-9)、'_' 字符、'$' 字符之外的字符转换为 '_' 字符
127
+ # - 首字母转化为小写
128
+ # - 处理首字符异常情况:检测首字符是不是数字、'_'、'$',若是则添加前缀字符"a"
129
+ #
130
+ # === Examples
131
+ #
132
+ # ===== Example-1
133
+ # a_asset = "packages/flutter_r_demo/assets/images/test.png"
134
+ # b_asset = "packages/flutter_r_demo/assets/images/test.jpg"
135
+ # prior_asset_type = ".png"
136
+ # a_asset_id = "test"
137
+ # b_asset_id = "test_jpg"
138
+ #
139
+ # ===== Example-2
140
+ # a_asset = "packages/flutter_r_demo/assets/texts/test.json"
141
+ # b_asset = "packages/flutter_r_demo/assets/texts/test.yaml"
142
+ # prior_asset_type = ".*"
143
+ # a_asset_id = "test_json"
144
+ # b_asset_id = "test_yaml"
145
+ #
146
+ def self.generate_asset_id(asset, prior_asset_type = ".*")
147
+ file_extname = File.extname(asset).downcase
148
+
149
+ file_basename = File.basename(asset)
150
+
151
+ file_basename_no_extension = File.basename(asset, ".*")
152
+ asset_id = file_basename_no_extension.dup
153
+ if prior_asset_type.eql?(".*") or file_extname.eql?(prior_asset_type) == false
154
+ ext_info = file_extname
155
+ ext_info[0] = "_"
156
+ asset_id = asset_id + ext_info
157
+ end
158
+
159
+ # 处理非法字符
160
+ asset_id = asset_id.gsub(/[^a-zA-Z0-9_$]/, "_")
161
+
162
+ # 首字母转化为小写
163
+ capital = asset_id[0].downcase
164
+ asset_id[0] = capital
165
+
166
+ # 处理首字符异常情况
167
+ if capital =~ /[0-9_$]/
168
+ asset_id = "a" + asset_id
169
+ end
170
+
171
+ return asset_id
172
+ end
173
+
174
+ # generate_asset_comment (asset, package_name) -> string
175
+ #
176
+ # 为当前asset生成注释
177
+ #
178
+ # === Examples
179
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
180
+ # package_name = "flutter_r_demo"
181
+ # asset_comment = "asset: assets/images/test.png"
182
+ #
183
+ def self.generate_asset_comment (asset, package_name)
184
+
185
+ asset_name = asset.dup
186
+ asset_name["packages/#{package_name}/"] = ""
187
+
188
+ asset_comment = "asset: #{asset_name}"
189
+
190
+ return asset_comment
191
+ end
192
+
193
+ # generate_AssetResource_property(asset, package_name, prior_asset_type) -> string
194
+ #
195
+ # 为当前 asset 生成 AssetResource property 的代码
196
+ #
197
+ def self.generate_AssetResource_property(asset, package_name, prior_asset_type = ".*")
198
+
199
+ asset_id = generate_asset_id(asset, prior_asset_type)
200
+ asset_comment = generate_asset_comment(asset, package_name)
201
+
202
+ asset_name = asset.dup
203
+ asset_name["packages/#{package_name}/"] = ""
204
+ # 对字符串中的 '$' 进行转义处理:'$' -> '\$'
205
+ escaped_asset_name = asset_name.gsub(/[$]/, "\\$")
206
+
207
+ code = <<-CODE
208
+ /// #{asset_comment}
209
+ // ignore: non_constant_identifier_names
210
+ final #{asset_id} = const AssetResource("#{escaped_asset_name}", packageName: R.package);
211
+ CODE
212
+
213
+ return code
214
+ end
215
+
216
+ # generate__R_Image_AssetResource_class(non_svg_image_asset_array, package_name) -> string
217
+ #
218
+ # 根据模板,为 non_svg_image_asset_array(非svg类的图片资产数组)生成 _R_Image_AssetResource class 的代码
219
+ #
220
+ def self.generate__R_Image_AssetResource_class(non_svg_image_asset_array, package_name)
221
+
222
+ all_g_AssetResource_property_code = ""
223
+
224
+ non_svg_image_asset_array.each do |image_asset|
225
+ all_g_AssetResource_property_code += "\n"
226
+ g_AssetResource_property_code = generate_AssetResource_property(image_asset, package_name, Flr::PRIOR_NON_SVG_IMAGE_FILE_TYPE)
227
+ all_g_AssetResource_property_code += g_AssetResource_property_code
228
+ end
229
+
230
+ code = <<-CODE
231
+ // ignore: camel_case_types
232
+ class _R_Image_AssetResource {
233
+ const _R_Image_AssetResource();
234
+ #{all_g_AssetResource_property_code}
235
+ }
236
+ CODE
237
+
238
+ return code
239
+ end
240
+
241
+ # generate__R_Svg_AssetResource_class(image_asset_array, package_name) -> string
242
+ #
243
+ # 根据模板,为 svg_image_asset_array(svg类的图片资产数组)生成 _R_Svg_AssetResource class 的代码
244
+ #
245
+ def self.generate__R_Svg_AssetResource_class(svg_image_asset_array, package_name)
246
+
247
+ all_g_AssetResource_property_code = ""
248
+
249
+ svg_image_asset_array.each do |image_asset|
250
+ all_g_AssetResource_property_code += "\n"
251
+ g_AssetResource_property_code = generate_AssetResource_property(image_asset, package_name, Flr::PRIOR_SVG_IMAGE_FILE_TYPE)
252
+ all_g_AssetResource_property_code += g_AssetResource_property_code
253
+ end
254
+
255
+ code = <<-CODE
256
+ // ignore: camel_case_types
257
+ class _R_Svg_AssetResource {
258
+ const _R_Svg_AssetResource();
259
+ #{all_g_AssetResource_property_code}
260
+ }
261
+ CODE
262
+
263
+ return code
264
+ end
265
+
266
+ # generate__R_Text_AssetResource_class(text_asset_array, package_name) -> string
267
+ #
268
+ # 根据模板,为 text_asset_array(文本资产数组)生成 _R_Text_AssetResource class 的代码
269
+ #
270
+ def self.generate__R_Text_AssetResource_class(text_asset_array, package_name)
271
+
272
+ all_g_AssetResource_property_code = ""
273
+
274
+ text_asset_array.each do |text_asset|
275
+ all_g_AssetResource_property_code += "\n"
276
+ g_AssetResource_property_code = generate_AssetResource_property(text_asset, package_name, Flr::PRIOR_TEXT_FILE_TYPE)
277
+ all_g_AssetResource_property_code += g_AssetResource_property_code
278
+ end
279
+
280
+ code = <<-CODE
281
+ // ignore: camel_case_types
282
+ class _R_Text_AssetResource {
283
+ const _R_Text_AssetResource();
284
+ #{all_g_AssetResource_property_code}
285
+ }
286
+ CODE
287
+
288
+ return code
289
+ end
290
+
291
+ # generate__R_Image_class(non_svg_image_asset_array, package_name) -> string
292
+ #
293
+ # 根据模板,为 non_svg_image_asset_array(非svg类的图片资产数组)生成 _R_Image class 的代码
294
+ #
295
+ def self.generate__R_Image_class(non_svg_image_asset_array, package_name)
296
+
297
+ all_g_Asset_method_code = ""
298
+
299
+ non_svg_image_asset_array.each do |image_asset|
300
+ all_g_Asset_method_code += "\n"
301
+
302
+ asset_id = generate_asset_id(image_asset, Flr::PRIOR_NON_SVG_IMAGE_FILE_TYPE)
303
+ asset_comment = generate_asset_comment(image_asset, package_name)
304
+
305
+ g_Asset_method_code = <<-CODE
306
+ /// #{asset_comment}
307
+ // ignore: non_constant_identifier_names
308
+ AssetImage #{asset_id}() {
309
+ return AssetImage(asset.#{asset_id}.keyName);
310
+ }
311
+ CODE
312
+
313
+ all_g_Asset_method_code += g_Asset_method_code
314
+ end
315
+
316
+ code = <<-CODE
317
+ /// This `_R_Image` class is generated and contains references to static non-svg type image asset resources.
318
+ // ignore: camel_case_types
319
+ class _R_Image {
320
+ const _R_Image();
321
+
322
+ final asset = const _R_Image_AssetResource();
323
+ #{all_g_Asset_method_code}
324
+ }
325
+ CODE
326
+
327
+ return code
328
+ end
329
+
330
+ # generate__R_Svg_class(image_asset_array, package_name) -> string
331
+ #
332
+ # 根据模板,为 svg_image_asset_array(svg类的图片资产数组)生成 _R_Svg class 的代码
333
+ #
334
+ def self.generate__R_Svg_class(svg_image_asset_array, package_name)
335
+
336
+ all_g_Asset_method_code = ""
337
+
338
+ svg_image_asset_array.each do |image_asset|
339
+ all_g_Asset_method_code += "\n"
340
+
341
+ asset_id = generate_asset_id(image_asset, Flr::PRIOR_SVG_IMAGE_FILE_TYPE)
342
+ asset_comment = generate_asset_comment(image_asset, package_name)
343
+
344
+ g_Asset_method_code = <<-CODE
345
+ /// #{asset_comment}
346
+ // ignore: non_constant_identifier_names
347
+ AssetSvg #{asset_id}({@required double width, @required double height}) {
348
+ final imageProvider = AssetSvg(asset.#{asset_id}.keyName, width: width, height: height);
349
+ return imageProvider;
350
+ }
351
+ CODE
352
+
353
+ all_g_Asset_method_code += g_Asset_method_code
354
+ end
355
+
356
+ code = <<-CODE
357
+ /// This `_R_Svg` class is generated and contains references to static svg type image asset resources.
358
+ // ignore: camel_case_types
359
+ class _R_Svg {
360
+ const _R_Svg();
361
+
362
+ final asset = const _R_Svg_AssetResource();
363
+ #{all_g_Asset_method_code}
364
+ }
365
+ CODE
366
+
367
+ return code
368
+ end
369
+
370
+ # generate__R_Text_class(text_asset_array, package_name) -> string
371
+ #
372
+ # 根据模板,为 text_asset_array(文本资产数组)生成 _R_Text class 的代码
373
+ #
374
+ def self.generate__R_Text_class(text_asset_array, package_name)
375
+
376
+ all_g_Asset_method_code = ""
377
+
378
+ text_asset_array.each do |text_asset|
379
+ all_g_Asset_method_code += "\n"
380
+
381
+ asset_id = generate_asset_id(text_asset, Flr::PRIOR_TEXT_FILE_TYPE)
382
+ asset_comment = generate_asset_comment(text_asset, package_name)
383
+
384
+ g_Asset_method_code = <<-CODE
385
+ /// #{asset_comment}
386
+ // ignore: non_constant_identifier_names
387
+ Future<String> #{asset_id}() {
388
+ final str = rootBundle.loadString(asset.#{asset_id}.keyName);
389
+ return str;
390
+ }
391
+ CODE
392
+
393
+ all_g_Asset_method_code += g_Asset_method_code
394
+ end
395
+
396
+ code = <<-CODE
397
+ /// This `_R_Text` class is generated and contains references to static text asset resources.
398
+ // ignore: camel_case_types
399
+ class _R_Text {
400
+ const _R_Text();
401
+
402
+ final asset = const _R_Text_AssetResource();
403
+ #{all_g_Asset_method_code}
404
+ }
405
+ CODE
406
+
407
+ return code
408
+ end
409
+
410
+ # generate_font_family_id(font_family_name) -> string
411
+ #
412
+ # 为当前 font_family_name 生成 font_family_id;font_family_id 一般为 asset 的 font_family_name;
413
+ # 但是为了保证 font_family_id 的健壮性,需要对 font_family_name 做以下加工处理:
414
+ # - 处理非法字符:把除了字母(a-z, A-Z)、数字(0-9)、'_' 字符、'$' 字符之外的字符转换为 '_' 字符
415
+ # - 首字母转化为小写
416
+ # - 处理首字符异常情况:检测首字符是不是数字、'_'、'$',若是则添加前缀字符"a"
417
+ #
418
+ # === Examples
419
+ # a_font_family_name = "Amiri"
420
+ # b_font_family_name = "Baloo-Thambi-2"
421
+ # a_font_family_id = "amiri"
422
+ # b_font_family_id = "baloo_Thambi_2"
423
+ #
424
+ #
425
+ def self.generate_font_family_id(font_family_name)
426
+
427
+ font_family_id = font_family_name.dup
428
+
429
+ # 处理非法字符
430
+ font_family_id = font_family_id.gsub(/[^a-zA-Z0-9_$]/, "_")
431
+
432
+ # 首字母转化为小写
433
+ capital = font_family_id[0].downcase
434
+ font_family_id[0] = capital
435
+
436
+ # 处理首字符异常情况
437
+ if capital =~ /[0-9_$]/
438
+ font_family_id = "a" + font_family_id
439
+ end
440
+
441
+ return font_family_id
442
+ end
443
+
444
+ # generate__R_FontFamily_class(font_family_config_array, package_name) -> string
445
+ #
446
+ # 根据模板,为 font_family_config_array(字体家族配置数组)生成 _R_FontFamily class 的代码
447
+ #
448
+ def self.generate__R_FontFamily_class(font_family_config_array, package_name)
449
+
450
+ all_g_AssetResource_property_code = ""
451
+
452
+ font_family_config_array.each do |font_family_config|
453
+ all_g_AssetResource_property_code += "\n"
454
+
455
+ font_family_name = font_family_config["family"]
456
+
457
+ font_family_id = generate_font_family_id(font_family_name)
458
+ font_family_comment = "font family: #{font_family_name}"
459
+
460
+ g_AssetResource_property_code = <<-CODE
461
+ /// #{font_family_comment}
462
+ // ignore: non_constant_identifier_names
463
+ final #{font_family_id} = "#{font_family_name}";
464
+ CODE
465
+
466
+ all_g_AssetResource_property_code += g_AssetResource_property_code
467
+ end
468
+
469
+ code = <<-CODE
470
+ /// This `_R_FontFamily` class is generated and contains references to static font asset resources.
471
+ // ignore: camel_case_types
472
+ class _R_FontFamily {
473
+ const _R_FontFamily();
474
+ #{all_g_AssetResource_property_code}
475
+ }
476
+ CODE
477
+
478
+ return code
479
+ end
480
+ end
481
+
482
+ end