flr 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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