flr 1.0.0 → 3.2.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.
data/lib/flr/constant.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  module Flr
2
+ # Flr支持的非SVG类图片文件类型
3
+ NON_SVG_IMAGE_FILE_TYPES = %w(.png .jpg .jpeg .gif .webp .icon .bmp .wbmp)
4
+ # Flr支持的SVG类图片文件类型
5
+ SVG_IMAGE_FILE_TYPES = %w(.svg)
2
6
  # Flr支持的图片文件类型
3
- IMAGE_FILE_TYPES = %w(.png .jpg .jpeg .gif .webp .icon .bmp .wbmp .svg)
7
+ IMAGE_FILE_TYPES = NON_SVG_IMAGE_FILE_TYPES + SVG_IMAGE_FILE_TYPES
4
8
  # Flr支持的文本文件类型
5
9
  TEXT_FILE_TYPES = %w(.txt .json .yaml .xml)
6
10
  # Flr支持的字体文件类型
@@ -6,89 +6,382 @@ module Flr
6
6
  # 资产相关的工具类方法
7
7
  class AssetUtil
8
8
 
9
- # generate_image_assets(legal_image_file_array, resource_dir, package_name) -> image_asset_array
9
+ # is_asset_variant?(legal_resource_file) -> true or false
10
+ #
11
+ # 判断当前的资源文件是不是资产变体(asset_variant)类型
12
+ #
13
+ # 判断的核心算法是:
14
+ # - 获取资源文件的父目录;
15
+ # - 判断父目录是否符合资产变体目录的特征
16
+ # 资产变体映射的的资源文件要求存放在“与 main_asset 在同一个目录下的”、“符合指定特征的”子目录中;
17
+ # 截止目前,Flutter只支持一种变体类型:倍率变体;
18
+ # 倍率变体只适用于非SVG类图片资源;
19
+ # 倍率变体目录特征可使用此正则来判断:“^((0\.[0-9]+)|([1-9]+[0-9]*(\.[0-9]+)?))[x]$”;
20
+ # 倍率变体目录名称示例:“0.5x”、“1.5x”、“2.0x”、“3.0x”,“2x”、“3x”;
21
+ #
22
+ def self.is_asset_variant?(legal_resource_file)
23
+
24
+ if FileUtil.is_non_svg_image_resource_file?(legal_resource_file)
25
+ dirname = File.dirname(legal_resource_file)
26
+ parent_dir_name = File.basename(dirname)
27
+
28
+ ratio_regex = /^((0\.[0-9]+)|([1-9]+[0-9]*(\.[0-9]+)?))[x]$/
29
+ if parent_dir_name =~ ratio_regex
30
+ return true
31
+ end
32
+ end
33
+
34
+ return false
35
+ end
36
+
37
+ # is_image_asset?(asset) -> true or false
38
+ #
39
+ # 判断当前资产是不是图片类资产
40
+ #
41
+ # === Examples
42
+ #
43
+ # === Example-1
44
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
45
+ # @return true
46
+ #
47
+ # === Example-2
48
+ # asset = "assets/images/test.png"
49
+ # @return true
50
+ #
51
+ def self.is_image_asset?(asset)
52
+ if FileUtil.is_image_resource_file?(asset)
53
+ return true
54
+ end
55
+
56
+ return false
57
+ end
58
+
59
+ # is_package_asset?(asset) -> true or false
60
+ #
61
+ # 判断当前资产是不是package类资产
62
+ #
63
+ # === Examples
64
+ #
65
+ # === Example-1
66
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
67
+ # @return true
68
+ #
69
+ # === Example-2
70
+ # asset = "assets/images/test.png"
71
+ # @return false
72
+ #
73
+ def self.is_package_asset?(asset)
74
+ package_prefix = "packages/"
75
+ if asset =~ /\A#{package_prefix}/
76
+ return true
77
+ end
78
+
79
+ return false
80
+ end
81
+
82
+ # is_specified_package_asset?(package_name, asset) -> true or false
83
+ #
84
+ # 判断当前资产是不是指定的package的资产
85
+ #
86
+ # === Examples
87
+ # package_name = "flutter_r_demo"
88
+ #
89
+ # === Example-1
90
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
91
+ # @return true
92
+ #
93
+ # === Example-2
94
+ # asset = "packages/hello_demo/assets/images/test.png"
95
+ # @return false
96
+ #
97
+ def self.is_specified_package_asset?(package_name, asset)
98
+ specified_package_prefix = "packages/" + package_name + "/"
99
+ if asset =~ /\A#{specified_package_prefix}/
100
+ return true
101
+ end
102
+
103
+ return false
104
+ end
105
+
106
+ # get_main_resource_file(flutter_project_dir, package_name, asset) -> main_resource_file
107
+ #
108
+ # 获取指定flutter工程的asset对应的主资源文件
109
+ # 注意:主资源文件不一定存在,比如图片资产可能只存在变体资源文件
110
+ #
111
+ # === Examples
112
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
113
+ # package_name = "flutter_r_demo"
114
+ #
115
+ # === Example-1
116
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
117
+ # main_resource_file = "~/path/to/flutter_r_demo/lib/assets/images/test.png"
118
+ #
119
+ # === Example-2
120
+ # asset = "assets/images/test.png"
121
+ # main_resource_file = "~/path/to/flutter_r_demo/assets/images/test.png"
122
+ #
123
+ def self.get_main_resource_file(flutter_project_dir, package_name, asset)
124
+ if is_specified_package_asset?(package_name, asset)
125
+ specified_package_prefix = "packages/" + package_name + "/"
126
+
127
+ # asset: packages/flutter_r_demo/assets/images/test.png
128
+ # to get implied_relative_resource_file: lib/assets/images/test.png
129
+ implied_relative_resource_file = asset.dup
130
+ implied_relative_resource_file[specified_package_prefix] = ""
131
+ implied_relative_resource_file = "lib/" + implied_relative_resource_file
132
+
133
+ # main_resource_file: ~/path/to/flutter_r_demo/lib/assets/images/test.png
134
+ main_resource_file = flutter_project_dir + "/" + implied_relative_resource_file
135
+ return main_resource_file
136
+ else
137
+ # asset: assets/images/test.png
138
+ # main_resource_file: ~/path/to/flutter_r_demo/assets/images/test.png
139
+ main_resource_file = flutter_project_dir + "/" + asset
140
+ return main_resource_file
141
+ end
142
+ end
143
+
144
+ # is_asset_existed?(flutter_project_dir, package_name, asset) -> true or false
145
+ #
146
+ # 判断指定flutter工程的asset是不是存在;存在的判断标准是:asset需要存在对应的资源文件
147
+ #
148
+ # === Examples
149
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
150
+ # package_name = "flutter_r_demo"
151
+ #
152
+ # === Example-1
153
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
154
+ # @return true
155
+ #
156
+ # === Example-2
157
+ # asset = "packages/flutter_r_demo/404/not-existed.png"
158
+ # @return false
159
+ #
160
+ def self.is_asset_existed?(flutter_project_dir, package_name, asset)
161
+ # 处理指定flutter工程的asset
162
+ # 1. 获取asset对应的main_resource_file
163
+ # 2. 若main_resource_file是非SVG类图片资源文件,判断asset是否存在的标准是:主资源文件或者至少一个变体资源文件存在
164
+ # 3. 若main_resource_file是SVG类图片资源文件或者其他资源文件,判断asset是否存在的标准是:主资源文件存在
165
+ #
166
+ main_resource_file = get_main_resource_file(flutter_project_dir, package_name, asset)
167
+ if FileUtil.is_non_svg_image_resource_file?(main_resource_file)
168
+ if File.exist?(main_resource_file)
169
+ return true
170
+ end
171
+
172
+ file_name = File.basename(main_resource_file)
173
+ file_dir = File.dirname(main_resource_file)
174
+ did_find_variant_resource_file = false
175
+ Dir.glob(["#{file_dir}/*/#{file_name}"]).each do |file|
176
+ if is_asset_variant?(file)
177
+ did_find_variant_resource_file = true
178
+ end
179
+ end
180
+
181
+ if did_find_variant_resource_file
182
+ return true
183
+ end
184
+ else
185
+ if File.exist?(main_resource_file)
186
+ return true
187
+ end
188
+ end
189
+
190
+ return false
191
+ end
192
+
193
+ # generate_main_asset(flutter_project_dir, package_name, legal_resource_file) -> main_asset
194
+ #
195
+ # 为当前资源文件生成 main_asset
196
+ #
197
+ # === Examples
198
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
199
+ # package_name = "flutter_r_demo"
200
+ #
201
+ # === Example-1
202
+ # legal_resource_file = "~/path/to/flutter_r_demo/lib/assets/images/test.png"
203
+ # main_asset = "packages/flutter_r_demo/assets/images/test.png"
204
+ #
205
+ # === Example-2
206
+ # legal_resource_file = "~/path/to/flutter_r_demo/lib/assets/images/3.0x/test.png"
207
+ # main_asset = "packages/flutter_r_demo/assets/images/test.png"
208
+ #
209
+ # === Example-3
210
+ # legal_resource_file = "~/path/to/flutter_r_demo/lib/assets/texts/3.0x/test.json"
211
+ # main_asset = "packages/flutter_r_demo/assets/texts/3.0x/test.json"
212
+ #
213
+ # === Example-3
214
+ # legal_resource_file = "~/path/to/flutter_r_demo/lib/assets/fonts/Amiri/Amiri-Regular.ttf"
215
+ # main_asset = "packages/flutter_r_demo/fonts/Amiri/Amiri-Regular.ttf"
216
+ #
217
+ # === Example-4
218
+ # legal_resource_file = "~/path/to/flutter_r_demo/assets/images/test.png"
219
+ # main_asset = "assets/images/test.png"
220
+ #
221
+ # === Example-5
222
+ # legal_resource_file = "~/path/to/flutter_r_demo/assets/images/3.0x/test.png"
223
+ # main_asset = "assets/images/test.png"
224
+ #
225
+ def self.generate_main_asset(flutter_project_dir, package_name, legal_resource_file)
226
+ # legal_resource_file: ~/path/to/flutter_r_demo/lib/assets/images/3.0x/test.png
227
+ # to get main_resource_file: ~/path/to/flutter_r_demo/lib/assets/images/test.png
228
+ main_resource_file = legal_resource_file
229
+ if is_asset_variant?(legal_resource_file)
230
+ # test.png
231
+ file_basename = File.basename(legal_resource_file)
232
+ # ~/path/to/flutter_r_demo/lib/assets/images/3.0x
233
+ file_dir = File.dirname(legal_resource_file)
234
+ # ~/path/to/flutter_r_demo/lib/assets/images
235
+ main_resource_file_dir = File.dirname(file_dir)
236
+ # ~/path/to/flutter_r_demo/lib/assets/images/test.png
237
+ main_resource_file = main_resource_file_dir + "/" + file_basename
238
+ end
239
+
240
+ # main_resource_file: ~/path/to/flutter_r_demo/lib/assets/images/test.png
241
+ # to get main_relative_resource_file: lib/assets/images/test.png
242
+ flutter_project_dir_prefix = "#{flutter_project_dir}/"
243
+ main_relative_resource_file = main_resource_file
244
+ if main_relative_resource_file =~ /\A#{flutter_project_dir_prefix}/
245
+ main_relative_resource_file["#{flutter_project_dir_prefix}"] = ""
246
+ end
247
+
248
+ # 判断 main_relative_resource_file 是不是 implied_resource_file 类型
249
+ # implied_resource_file 的定义是:放置在 "lib/" 目录内 resource_file
250
+ # 具体实现是:main_relative_resource_file 的前缀若是 "lib/" ,则其是 implied_resource_file 类型;
251
+ #
252
+ # implied_relative_resource_file 生成 main_asset 的算法是: main_asset = "packages/#{package_name}/#{asset_name}"
253
+ # non-implied_relative_resource_file 生成 main_asset 的算法是: main_asset = "#{asset_name}"
254
+ #
255
+ lib_prefix = "lib/"
256
+ if main_relative_resource_file =~ /\A#{lib_prefix}/
257
+ # main_relative_resource_file: lib/assets/images/test.png
258
+ # to get asset_name: assets/images/test.png
259
+ asset_name = main_relative_resource_file
260
+ asset_name[lib_prefix] = ""
261
+
262
+ main_asset = "packages/#{package_name}/#{asset_name}"
263
+ return main_asset
264
+ else
265
+ # main_relative_resource_file: assets/images/test.png
266
+ # to get asset_name: assets/images/test.png
267
+ asset_name = main_relative_resource_file
268
+
269
+ main_asset = asset_name
270
+ return main_asset
271
+ end
272
+ end
273
+
274
+ # generate_image_assets(flutter_project_dir, package_name, legal_image_file_array) -> image_asset_array
10
275
  #
11
276
  # 遍历指定资源目录下扫描找到的legal_image_file数组生成image_asset数组
12
277
  #
13
278
  # === Examples
14
- # legal_image_file_array = ["lib/assets/images/test.png"]
15
- # resource_dir = "lib/assets/images"
279
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
16
280
  # package_name = "flutter_r_demo"
281
+ # legal_image_file_array = ["~/path/to/flutter_r_demo/lib/assets/images/test.png", "~/path/to/flutter_r_demo/lib/assets/images/3.0x/test.png"]
17
282
  # image_asset_array = ["packages/flutter_r_demo/assets/images/test.png"]
18
283
  #
19
- def self.generate_image_assets(legal_image_file_array, resource_dir, package_name)
284
+ def self.generate_image_assets(flutter_project_dir, package_name, legal_image_file_array)
20
285
 
21
286
  image_asset_array = []
22
287
 
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
288
  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}"
289
+ image_asset = generate_main_asset(flutter_project_dir, package_name, legal_image_file)
32
290
  image_asset_array.push(image_asset)
33
291
  end
34
292
 
293
+ image_asset_array.uniq!
35
294
  return image_asset_array
36
295
  end
37
296
 
38
- # generate_text_assets(legal_text_file_array, resource_dir, package_name) -> text_asset_array
297
+ # generate_text_assets(flutter_project_dir, package_name, legal_text_file_array) -> text_asset_array
39
298
  #
40
299
  # 遍历指定资源目录下扫描找到的legal_text_file数组生成text_asset数组
41
300
  #
42
301
  # === Examples
43
- # legal_text_file_array = ["lib/assets/jsons/test.json"]
44
- # resource_dir = "lib/assets/jsons"
302
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
45
303
  # package_name = "flutter_r_demo"
304
+ # legal_text_file_array = ["~path/to/flutter_r_demo/lib/assets/jsons/test.json"]
46
305
  # text_asset_array = ["packages/flutter_r_demo/assets/jsons/test.json"]
47
306
  #
48
- def self.generate_text_assets(legal_text_file_array, resource_dir, package_name)
307
+ def self.generate_text_assets(flutter_project_dir, package_name, legal_text_file_array)
49
308
 
50
309
  text_asset_array = []
51
310
 
52
311
  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}"
312
+ text_asset = generate_main_asset(flutter_project_dir, package_name, legal_text_file)
59
313
  text_asset_array.push(text_asset)
60
314
  end
61
315
 
316
+ text_asset_array.uniq!
62
317
  return text_asset_array
63
318
  end
64
319
 
65
- # generate_font_asset_configs(legal_font_file_array, resource_dir, package_name) -> font_asset_config_array
320
+ # generate_font_asset_configs(flutter_project_dir, package_name, legal_font_file_array) -> font_asset_config_array
66
321
  #
67
322
  # 遍历指定资源目录下扫描找到的legal_font_file数组生成font_asset_config数组
68
323
  #
69
324
  # === Examples
70
- # legal_font_file_array = ["lib/assets/fonts/Amiri/Amiri-Regular.ttf"]
71
- # resource_dir = "lib/assets/fonts/Amiri"
325
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
72
326
  # package_name = "flutter_r_demo"
327
+ # legal_font_file_array = ["~path/to/flutter_r_demo/lib/assets/fonts/Amiri/Amiri-Regular.ttf"]
73
328
  # font_asset_config_array -> [{"asset": "packages/flutter_r_demo/assets/fonts/Amiri/Amiri-Regular.ttf"}]
74
329
  #
75
- def self.generate_font_asset_configs(legal_font_file_array, resource_dir, package_name)
330
+ def self.generate_font_asset_configs(flutter_project_dir, package_name, legal_font_file_array)
76
331
 
77
332
  font_asset_config_array = []
78
333
 
79
334
  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}"
335
+ font_asset = generate_main_asset(flutter_project_dir, package_name, legal_font_file)
86
336
  font_asset_config = Hash["asset" => font_asset]
87
337
  font_asset_config_array.push(font_asset_config)
88
338
  end
89
339
 
340
+ font_asset_config_array.uniq!{|config| config["asset"]}
90
341
  return font_asset_config_array
91
342
  end
92
343
 
344
+ # mergeFlutterAssets(new_asset_array, old_asset_array) -> merged_asset_array
345
+ #
346
+ # 合并新旧2个asset数组:
347
+ # - old_asset_array - new_asset_array = diff_asset_array,获取old_asset_array与new_asset_array的差异集合
348
+ # - 遍历diff_asset_array,筛选合法的asset得到legal_old_asset_array;合法的asset标准是:非图片资源 + 存在对应的资源文件
349
+ # - 按照字典序对legal_old_asset_array进行排序,并追加到new_asset_array
350
+ # - 返回合并结果merged_asset_array
351
+ #
352
+ # === Examples
353
+ # flutter_project_dir = "~/path/to/flutter_r_demo"
354
+ # package_name = "flutter_r_demo"
355
+ # new_asset_array = ["packages/flutter_r_demo/assets/images/test.png", "packages/flutter_r_demo/assets/jsons/test.json"]
356
+ # old_asset_array = ["packages/flutter_r_demo/assets/htmls/test.html"]
357
+ # merged_asset_array = ["packages/flutter_r_demo/assets/images/test.png", "packages/flutter_r_demo/assets/jsons/test.json", "packages/flutter_r_demo/assets/htmls/test.html"]
358
+ def self.mergeFlutterAssets(flutter_project_dir, package_name, new_asset_array, old_asset_array)
359
+ legal_old_asset_array = []
360
+
361
+ diff_asset_array = old_asset_array - new_asset_array;
362
+ diff_asset_array.each do |asset|
363
+ # 若是第三方package的资源,则合并到new_asset_array
364
+ # 引用第三方package的资源的推荐做法是:通过引用第三方package的R类来访问
365
+ if is_package_asset?(asset)
366
+ if is_specified_package_asset?(package_name, asset) == false
367
+ legal_old_asset_array.push(asset)
368
+ next
369
+ end
370
+ end
371
+
372
+ # 处理指定flutter工程的asset
373
+ # 1. 判断asset是否存在
374
+ # 2. 若asset存在,则合并到new_asset_array
375
+ #
376
+ if is_asset_existed?(flutter_project_dir, package_name, asset)
377
+ legal_old_asset_array.push(asset)
378
+ end
379
+ end
380
+
381
+ legal_old_asset_array.sort!
382
+ merged_asset_array = new_asset_array + legal_old_asset_array
383
+ return merged_asset_array
384
+ end
385
+
93
386
  end
94
387
  end
@@ -5,6 +5,36 @@ module Flr
5
5
  # 代码生成相关的工具类方法
6
6
  class CodeUtil
7
7
 
8
+ @@should_support_nullsafety = nil
9
+
10
+ def self.should_support_nullsafety
11
+ if @@should_support_nullsafety != nil
12
+ return @@should_support_nullsafety
13
+ end
14
+
15
+ # $ flutter --version
16
+ # Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git
17
+ # Framework • revision 27321ebbad (5 weeks ago) • 2019-12-10 18:15:01 -0800
18
+ # Engine • revision 2994f7e1e6
19
+ # Tools • Dart 2.7.0
20
+ flutter_version_result = `flutter --version`
21
+ if (flutter_version_result.nil? == true || flutter_version_result.empty? == true)
22
+ @@should_support_nullsafety = false
23
+ return @@should_support_nullsafety
24
+ end
25
+
26
+ dart_version_str = flutter_version_result.split("Dart")[1]
27
+ dart_version_str.strip!
28
+
29
+ if Version.new(dart_version_str) >= Version.new("2.12.0")
30
+ @@should_support_nullsafety = true
31
+ return @@should_support_nullsafety
32
+ end
33
+
34
+ @@should_support_nullsafety = false
35
+ return @@should_support_nullsafety
36
+ end
37
+
8
38
  # generate_R_class(package_name) -> string
9
39
  #
10
40
  # 根据模板生成 R class 的代码
@@ -66,6 +96,58 @@ class R {
66
96
  /// - fileBasename:example.png
67
97
  /// - fileBasenameNoExtension:example
68
98
  /// - fileExtname:.png
99
+ CODE
100
+
101
+ if should_support_nullsafety
102
+ code += <<-CODE
103
+ class AssetResource {
104
+ /// Creates an object to hold the asset resource’s metadata.
105
+ const AssetResource(this.assetName, {this.packageName});
106
+
107
+ /// The name of the main asset from the set of asset resources to choose from.
108
+ final String assetName;
109
+
110
+ /// The name of the package from which the asset resource is included.
111
+ final String? packageName;
112
+
113
+ /// The name used to generate the key to obtain the asset resource. For local assets
114
+ /// this is [assetName], and for assets from packages the [assetName] is
115
+ /// prefixed 'packages/<package_name>/'.
116
+ String get keyName => packageName == null ? assetName : "packages/$packageName/$assetName";
117
+
118
+ /// The file basename of the asset resource.
119
+ String get fileBasename {
120
+ final basename = path.basename(assetName);
121
+ return basename;
122
+ }
123
+
124
+ /// The no extension file basename of the asset resource.
125
+ String get fileBasenameNoExtension {
126
+ final basenameWithoutExtension = path.basenameWithoutExtension(assetName);
127
+ return basenameWithoutExtension;
128
+ }
129
+
130
+ /// The file extension name of the asset resource.
131
+ String get fileExtname {
132
+ final extension = path.extension(assetName);
133
+ return extension;
134
+ }
135
+
136
+ /// The directory path name of the asset resource.
137
+ String get fileDirname {
138
+ var dirname = assetName;
139
+ if (packageName != null) {
140
+ final packageStr = "packages/$packageName/";
141
+ dirname = dirname.replaceAll(packageStr, "");
142
+ }
143
+ final filenameStr = "$fileBasename/";
144
+ dirname = dirname.replaceAll(filenameStr, "");
145
+ return dirname;
146
+ }
147
+ }
148
+ CODE
149
+ else
150
+ code += <<-CODE
69
151
  class AssetResource {
70
152
  /// Creates an object to hold the asset resource’s metadata.
71
153
  const AssetResource(this.assetName, {this.packageName}) : assert(assetName != null);
@@ -111,12 +193,13 @@ class AssetResource {
111
193
  return dirname;
112
194
  }
113
195
  }
114
- CODE
196
+ CODE
197
+ end
115
198
 
116
199
  return code
117
200
  end
118
201
 
119
- # generate_asset_id (asset, prior_asset_type) -> string
202
+ # generate_asset_id (asset, used_asset_id_array, prior_asset_type) -> string
120
203
  #
121
204
  # - prior_asset_type: 优先的资源类型;默认值为 ".*",意味当前不存在任何优先的资源类型
122
205
  # 对于优先的资源类型,其 asset_id 不会携带类型信息,详细见例子
@@ -126,26 +209,40 @@ class AssetResource {
126
209
  # - 处理非法字符:把除了字母(a-z, A-Z)、数字(0-9)、'_' 字符、'$' 字符之外的字符转换为 '_' 字符
127
210
  # - 首字母转化为小写
128
211
  # - 处理首字符异常情况:检测首字符是不是数字、'_'、'$',若是则添加前缀字符"a"
212
+ # - 处理 asset_id 重名的情况
129
213
  #
130
214
  # === Examples
131
215
  #
132
216
  # ===== Example-1
133
- # a_asset = "packages/flutter_r_demo/assets/images/test.png"
134
- # b_asset = "packages/flutter_r_demo/assets/images/test.jpg"
217
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
218
+ # asset = "packages/flutter_r_demo/assets/images/test.jpg"
219
+ # used_asset_id_array = []
135
220
  # prior_asset_type = ".png"
136
- # a_asset_id = "test"
137
- # b_asset_id = "test_jpg"
221
+ # asset_id = "test"
138
222
  #
139
223
  # ===== Example-2
140
- # a_asset = "packages/flutter_r_demo/assets/texts/test.json"
141
- # b_asset = "packages/flutter_r_demo/assets/texts/test.yaml"
224
+ # asset = "packages/flutter_r_demo/assets/images/test.jpg"
225
+ # used_asset_id_array = [test]
226
+ # prior_asset_type = ".png"
227
+ # asset_id = "test_jpg"
228
+ #
229
+ # ===== Example-3
230
+ # asset = "packages/flutter_r_demo/assets/home-images/test.jpg"
231
+ # used_asset_id_array = [test, test_jpg]
232
+ # prior_asset_type = ".png"
233
+ # asset_id = "test_jpg_1"
234
+ #
235
+ # ===== Example-4
236
+ # asset = "packages/flutter_r_demo/assets/texts/test.json"
237
+ # used_asset_id_array = []
142
238
  # prior_asset_type = ".*"
143
- # a_asset_id = "test_json"
144
- # b_asset_id = "test_yaml"
239
+ # asset_id = "test_json"
145
240
  #
146
- def self.generate_asset_id(asset, prior_asset_type = ".*")
241
+ def self.generate_asset_id(asset, used_asset_id_array, prior_asset_type = ".*")
147
242
  file_extname = File.extname(asset).downcase
148
243
 
244
+ dirname = File.dirname(asset)
245
+ parent_dir_name = File.basename(dirname)
149
246
  file_basename = File.basename(asset)
150
247
 
151
248
  file_basename_no_extension = File.basename(asset, ".*")
@@ -168,6 +265,26 @@ class AssetResource {
168
265
  asset_id = "a" + asset_id
169
266
  end
170
267
 
268
+ # 处理 asset_id 重名的情况
269
+ if used_asset_id_array.include?(asset_id)
270
+ # 当前asset_id重名次数,初始值为1
271
+ repeat_count = 1
272
+
273
+ # 查找当前asset_id衍生出来的asset_id_brother(id兄弟)
274
+ # asset_id_brother = #{asset_id}$#{repeat_count}
275
+ # 其中,repeat_count >= 1
276
+ #
277
+ # Example:
278
+ # asset_id = test
279
+ # asset_id_brother = test$1
280
+ #
281
+ id_brother_regx = /^#{asset_id}\$[1-9][0-9]*$/
282
+ cur_asset_id_brothers = used_asset_id_array.select{ |id| id =~ id_brother_regx }
283
+
284
+ repeat_count += cur_asset_id_brothers.size
285
+ asset_id = "#{asset_id}$#{repeat_count}"
286
+ end
287
+
171
288
  return asset_id
172
289
  end
173
290
 
@@ -176,54 +293,105 @@ class AssetResource {
176
293
  # 为当前asset生成注释
177
294
  #
178
295
  # === Examples
179
- # asset = "packages/flutter_r_demo/assets/images/test.png"
180
296
  # package_name = "flutter_r_demo"
297
+ #
298
+ # === Example-1
299
+ # asset = "packages/flutter_r_demo/assets/images/test.png"
300
+ # asset_comment = "asset: lib/assets/images/test.png"
301
+ #
302
+ # === Example-2
303
+ # asset = "assets/images/test.png"
181
304
  # asset_comment = "asset: assets/images/test.png"
182
305
  #
183
306
  def self.generate_asset_comment (asset, package_name)
307
+ packages_prefix = "packages/#{package_name}/"
308
+
309
+ if asset =~ /\A#{packages_prefix}/
310
+ # asset: packages/flutter_r_demo/assets/images/test.png
311
+ # to get assetName: assets/images/test.png
312
+ asset_name = asset.dup
313
+ asset_name[packages_prefix] = ""
314
+
315
+ asset_comment = "asset: lib/#{asset_name}"
316
+ return asset_comment
317
+ else
318
+ # asset: assets/images/test.png
319
+ # to get assetName: assets/images/test.png
320
+ asset_name = asset.dup
321
+
322
+ asset_comment = "asset: #{asset_name}"
323
+ return asset_comment
324
+ end
184
325
 
185
- asset_name = asset.dup
186
- asset_name["packages/#{package_name}/"] = ""
187
-
188
- asset_comment = "asset: #{asset_name}"
189
-
190
- return asset_comment
191
326
  end
192
327
 
193
- # generate_AssetResource_property(asset, package_name, prior_asset_type) -> string
328
+ # generate_AssetResource_property(asset, asset_id_dict, package_name, is_package_project_type, prior_asset_type) -> string
194
329
  #
195
330
  # 为当前 asset 生成 AssetResource property 的代码
196
331
  #
197
- def self.generate_AssetResource_property(asset, package_name, prior_asset_type = ".*")
198
-
199
- asset_id = generate_asset_id(asset, prior_asset_type)
332
+ def self.generate_AssetResource_property(asset, asset_id_dict, package_name, is_package_project_type, prior_asset_type = ".*")
333
+ asset_id = asset_id_dict[asset]
200
334
  asset_comment = generate_asset_comment(asset, package_name)
201
335
 
202
- asset_name = asset.dup
203
- asset_name["packages/#{package_name}/"] = ""
336
+ asset_name = ""
337
+ needPackage = false
338
+
339
+ packages_prefix = "packages/#{package_name}/"
340
+ if asset =~ /\A#{packages_prefix}/
341
+ # asset: packages/flutter_r_demo/assets/images/test.png
342
+ # to get asset_name: assets/images/test.png
343
+ asset_name = asset.dup
344
+ asset_name[packages_prefix] = ""
345
+
346
+ needPackage = true
347
+ else
348
+ # asset: assets/images/test.png
349
+ # to get asset_name: assets/images/test.png
350
+ asset_name = asset.dup
351
+
352
+ if is_package_project_type
353
+ needPackage = true
354
+ else
355
+ needPackage = false
356
+ end
357
+
358
+ end
359
+
204
360
  # 对字符串中的 '$' 进行转义处理:'$' -> '\$'
361
+ # asset_name: assets/images/test$.png
362
+ # to get escaped_asset_name: assets/images/test\$.png
205
363
  escaped_asset_name = asset_name.gsub(/[$]/, "\\$")
206
364
 
207
- code = <<-CODE
365
+ if needPackage
366
+ code = <<-CODE
208
367
  /// #{asset_comment}
209
368
  // ignore: non_constant_identifier_names
210
369
  final #{asset_id} = const AssetResource("#{escaped_asset_name}", packageName: R.package);
211
- CODE
370
+ CODE
212
371
 
213
- return code
372
+ return code
373
+ else
374
+ code = <<-CODE
375
+ /// #{asset_comment}
376
+ // ignore: non_constant_identifier_names
377
+ final #{asset_id} = const AssetResource("#{escaped_asset_name}", packageName: null);
378
+ CODE
379
+
380
+ return code
381
+ end
214
382
  end
215
383
 
216
- # generate__R_Image_AssetResource_class(non_svg_image_asset_array, package_name) -> string
384
+ # generate__R_Image_AssetResource_class(non_svg_image_asset_array, non_svg_image_asset_id_dict, package_name, is_package_project_type) -> string
217
385
  #
218
386
  # 根据模板,为 non_svg_image_asset_array(非svg类的图片资产数组)生成 _R_Image_AssetResource class 的代码
219
387
  #
220
- def self.generate__R_Image_AssetResource_class(non_svg_image_asset_array, package_name)
388
+ def self.generate__R_Image_AssetResource_class(non_svg_image_asset_array, non_svg_image_asset_id_dict, package_name, is_package_project_type)
221
389
 
222
390
  all_g_AssetResource_property_code = ""
223
391
 
224
392
  non_svg_image_asset_array.each do |image_asset|
225
393
  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)
394
+ g_AssetResource_property_code = generate_AssetResource_property(image_asset, non_svg_image_asset_id_dict, package_name, is_package_project_type, Flr::PRIOR_NON_SVG_IMAGE_FILE_TYPE)
227
395
  all_g_AssetResource_property_code += g_AssetResource_property_code
228
396
  end
229
397
 
@@ -238,17 +406,17 @@ class _R_Image_AssetResource {
238
406
  return code
239
407
  end
240
408
 
241
- # generate__R_Svg_AssetResource_class(image_asset_array, package_name) -> string
409
+ # generate__R_Svg_AssetResource_class(svg_image_asset_array, svg_image_asset_id_dict, package_name, is_package_project_type) -> string
242
410
  #
243
411
  # 根据模板,为 svg_image_asset_array(svg类的图片资产数组)生成 _R_Svg_AssetResource class 的代码
244
412
  #
245
- def self.generate__R_Svg_AssetResource_class(svg_image_asset_array, package_name)
413
+ def self.generate__R_Svg_AssetResource_class(svg_image_asset_array, svg_image_asset_id_dict, package_name, is_package_project_type)
246
414
 
247
415
  all_g_AssetResource_property_code = ""
248
416
 
249
417
  svg_image_asset_array.each do |image_asset|
250
418
  all_g_AssetResource_property_code += "\n"
251
- g_AssetResource_property_code = generate_AssetResource_property(image_asset, package_name, Flr::PRIOR_SVG_IMAGE_FILE_TYPE)
419
+ g_AssetResource_property_code = generate_AssetResource_property(image_asset, svg_image_asset_id_dict, package_name, is_package_project_type, Flr::PRIOR_SVG_IMAGE_FILE_TYPE)
252
420
  all_g_AssetResource_property_code += g_AssetResource_property_code
253
421
  end
254
422
 
@@ -263,17 +431,17 @@ class _R_Svg_AssetResource {
263
431
  return code
264
432
  end
265
433
 
266
- # generate__R_Text_AssetResource_class(text_asset_array, package_name) -> string
434
+ # generate__R_Text_AssetResource_class(text_asset_array, text_asset_id_dict, package_name, is_package_project_typ) -> string
267
435
  #
268
436
  # 根据模板,为 text_asset_array(文本资产数组)生成 _R_Text_AssetResource class 的代码
269
437
  #
270
- def self.generate__R_Text_AssetResource_class(text_asset_array, package_name)
438
+ def self.generate__R_Text_AssetResource_class(text_asset_array, text_asset_id_dict, package_name, is_package_project_type)
271
439
 
272
440
  all_g_AssetResource_property_code = ""
273
441
 
274
442
  text_asset_array.each do |text_asset|
275
443
  all_g_AssetResource_property_code += "\n"
276
- g_AssetResource_property_code = generate_AssetResource_property(text_asset, package_name, Flr::PRIOR_TEXT_FILE_TYPE)
444
+ g_AssetResource_property_code = generate_AssetResource_property(text_asset, text_asset_id_dict, package_name, is_package_project_type, Flr::PRIOR_TEXT_FILE_TYPE)
277
445
  all_g_AssetResource_property_code += g_AssetResource_property_code
278
446
  end
279
447
 
@@ -288,18 +456,18 @@ class _R_Text_AssetResource {
288
456
  return code
289
457
  end
290
458
 
291
- # generate__R_Image_class(non_svg_image_asset_array, package_name) -> string
459
+ # generate__R_Image_class(non_svg_image_asset_array, non_svg_image_asset_id_dict, package_name) -> string
292
460
  #
293
461
  # 根据模板,为 non_svg_image_asset_array(非svg类的图片资产数组)生成 _R_Image class 的代码
294
462
  #
295
- def self.generate__R_Image_class(non_svg_image_asset_array, package_name)
463
+ def self.generate__R_Image_class(non_svg_image_asset_array, non_svg_image_asset_id_dict, package_name)
296
464
 
297
465
  all_g_Asset_method_code = ""
298
466
 
299
467
  non_svg_image_asset_array.each do |image_asset|
300
468
  all_g_Asset_method_code += "\n"
301
469
 
302
- asset_id = generate_asset_id(image_asset, Flr::PRIOR_NON_SVG_IMAGE_FILE_TYPE)
470
+ asset_id = non_svg_image_asset_id_dict[image_asset]
303
471
  asset_comment = generate_asset_comment(image_asset, package_name)
304
472
 
305
473
  g_Asset_method_code = <<-CODE
@@ -327,28 +495,39 @@ class _R_Image {
327
495
  return code
328
496
  end
329
497
 
330
- # generate__R_Svg_class(image_asset_array, package_name) -> string
498
+ # generate__R_Svg_class(svg_image_asset_array, svg_image_asset_id_dict, package_name) -> string
331
499
  #
332
500
  # 根据模板,为 svg_image_asset_array(svg类的图片资产数组)生成 _R_Svg class 的代码
333
501
  #
334
- def self.generate__R_Svg_class(svg_image_asset_array, package_name)
502
+ def self.generate__R_Svg_class(svg_image_asset_array, svg_image_asset_id_dict, package_name)
335
503
 
336
504
  all_g_Asset_method_code = ""
337
505
 
338
506
  svg_image_asset_array.each do |image_asset|
339
507
  all_g_Asset_method_code += "\n"
340
508
 
341
- asset_id = generate_asset_id(image_asset, Flr::PRIOR_SVG_IMAGE_FILE_TYPE)
509
+ asset_id = svg_image_asset_id_dict[image_asset]
342
510
  asset_comment = generate_asset_comment(image_asset, package_name)
343
511
 
344
- g_Asset_method_code = <<-CODE
512
+ if should_support_nullsafety
513
+ g_Asset_method_code = <<-CODE
514
+ /// #{asset_comment}
515
+ // ignore: non_constant_identifier_names
516
+ AssetSvg #{asset_id}({required double width, required double height}) {
517
+ final imageProvider = AssetSvg(asset.#{asset_id}.keyName, width: width, height: height);
518
+ return imageProvider;
519
+ }
520
+ CODE
521
+ else
522
+ g_Asset_method_code = <<-CODE
345
523
  /// #{asset_comment}
346
524
  // ignore: non_constant_identifier_names
347
525
  AssetSvg #{asset_id}({@required double width, @required double height}) {
348
526
  final imageProvider = AssetSvg(asset.#{asset_id}.keyName, width: width, height: height);
349
527
  return imageProvider;
350
528
  }
351
- CODE
529
+ CODE
530
+ end
352
531
 
353
532
  all_g_Asset_method_code += g_Asset_method_code
354
533
  end
@@ -367,18 +546,18 @@ class _R_Svg {
367
546
  return code
368
547
  end
369
548
 
370
- # generate__R_Text_class(text_asset_array, package_name) -> string
549
+ # generate__R_Text_class(text_asset_array, text_asset_id_dict, package_name) -> string
371
550
  #
372
551
  # 根据模板,为 text_asset_array(文本资产数组)生成 _R_Text class 的代码
373
552
  #
374
- def self.generate__R_Text_class(text_asset_array, package_name)
553
+ def self.generate__R_Text_class(text_asset_array, text_asset_id_dict, package_name)
375
554
 
376
555
  all_g_Asset_method_code = ""
377
556
 
378
557
  text_asset_array.each do |text_asset|
379
558
  all_g_Asset_method_code += "\n"
380
559
 
381
- asset_id = generate_asset_id(text_asset, Flr::PRIOR_TEXT_FILE_TYPE)
560
+ asset_id = text_asset_id_dict[text_asset]
382
561
  asset_comment = generate_asset_comment(text_asset, package_name)
383
562
 
384
563
  g_Asset_method_code = <<-CODE