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.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/CHANGELOG.md +37 -0
- data/Gemfile.lock +1 -1
- data/lib/flr.rb +11 -3
- data/lib/flr/checker.rb +16 -13
- data/lib/flr/command.rb +447 -137
- data/lib/flr/constant.rb +5 -1
- data/lib/flr/util/asset_util.rb +325 -32
- data/lib/flr/util/code_util.rb +226 -47
- data/lib/flr/util/file_util.rb +154 -22
- data/lib/flr/version.rb +2 -2
- metadata +3 -3
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 =
|
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支持的字体文件类型
|
data/lib/flr/util/asset_util.rb
CHANGED
@@ -6,89 +6,382 @@ module Flr
|
|
6
6
|
# 资产相关的工具类方法
|
7
7
|
class AssetUtil
|
8
8
|
|
9
|
-
#
|
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
|
-
#
|
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(
|
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
|
-
|
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(
|
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
|
-
#
|
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(
|
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
|
-
|
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(
|
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
|
-
#
|
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(
|
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
|
-
|
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
|
data/lib/flr/util/code_util.rb
CHANGED
@@ -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
|
-
|
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
|
-
#
|
134
|
-
#
|
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
|
-
#
|
137
|
-
# b_asset_id = "test_jpg"
|
221
|
+
# asset_id = "test"
|
138
222
|
#
|
139
223
|
# ===== Example-2
|
140
|
-
#
|
141
|
-
#
|
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
|
-
#
|
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 =
|
203
|
-
|
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
|
-
|
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
|
-
|
370
|
+
CODE
|
212
371
|
|
213
|
-
|
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(
|
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 =
|
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(
|
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 =
|
509
|
+
asset_id = svg_image_asset_id_dict[image_asset]
|
342
510
|
asset_comment = generate_asset_comment(image_asset, package_name)
|
343
511
|
|
344
|
-
|
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
|
-
|
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 =
|
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
|