flr 1.0.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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