flr 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,175 @@
1
+ require 'flr/string_extensions'
2
+
3
+ module Flr
4
+ # 条件检测器,提供检测各种条件是否合法的方法
5
+ class Checker
6
+
7
+ # check_pubspec_file_is_existed(flutter_dir) -> true
8
+ #
9
+ # 检测当前flutter工程目录是否存在pubspec.yaml文件
10
+ # 若存在,返回true
11
+ # 若不存在,则抛出异常
12
+ #
13
+ # === Examples
14
+ #
15
+ # flutter_dir = "~/path/to/flutter_project/pubspec.yaml"
16
+ # Checker.check_pubspec_file_is_existed(flutter_dir)
17
+ #
18
+ def self.check_pubspec_file_is_existed(flutter_dir)
19
+ pubspec_file_path = flutter_dir + "/pubspec.yaml"
20
+
21
+ if File.exist?(pubspec_file_path) == false
22
+ message = <<-MESSAGE
23
+ #{"[x]: #{pubspec_file_path} not found".error_style}
24
+ #{"[*]: please make sure pubspec.yaml is existed in #{flutter_dir}".tips_style}
25
+ MESSAGE
26
+
27
+ raise(message)
28
+ end
29
+
30
+ end
31
+
32
+ # check_flr_config_is_existed(pubspec_config) -> true
33
+ #
34
+ # 检测pubspec.yaml中是否存在flr的配置信息`flr_config`:
35
+ #
36
+ # ``` yaml
37
+ # flr:
38
+ # core_version: 1.0.0
39
+ # dartfmt_line_length: 80
40
+ # assets:
41
+ # fonts:
42
+ # ```
43
+ # 若存在,返回true
44
+ # 若不存在,则抛出异常
45
+ #
46
+ # === Examples
47
+ #
48
+ # pubspec_config = YAML.load(pubspec_file)
49
+ # Checker.check_flr_config_is_existed(pubspec_config)
50
+ #
51
+ def self.check_flr_config_is_existed(pubspec_config)
52
+ flr_config = pubspec_config["flr"]
53
+
54
+ if flr_config.is_a?(Hash) == false
55
+ message = <<-MESSAGE
56
+ #{"[x]: have no flr configuration in pubspec.yaml".error_style}
57
+ #{"[*]: please run \"flr init\" to fix it".tips_style}
58
+ MESSAGE
59
+
60
+ raise(message)
61
+ end
62
+
63
+ return true
64
+ end
65
+
66
+ # check_flr_assets_is_legal(flr_config) -> resource_dir_result_tuple
67
+ #
68
+ # 检测当前flr配置信息中的assets配置是否合法
69
+ # 若合法,返回资源目录结果三元组 resource_dir_result_triplet
70
+ # 若不合法,抛出异常
71
+ #
72
+ # resource_dir_result_tuple = [assets_legal_resource_dir_array, illegal_resource_dir_array, fonts_legal_resource_dir_array]
73
+ #
74
+ #
75
+ # flr的assets配置是用于配置需要flr进行扫描的资源目录,如:
76
+ #
77
+ # ``` yaml
78
+ # flr:
79
+ # core_version: 1.0.0
80
+ # dartfmt_line_length: 80
81
+ # assets:
82
+ # - lib/assets/images
83
+ # - lib/assets/texts
84
+ # fonts:
85
+ # - lib/assets/fonts
86
+ # ```
87
+ #
88
+ # 判断flr的assets配置合法的标准是:assets配置的resource_dir数组中的legal_resource_dir数量大于0。
89
+ #
90
+ # === Examples
91
+ # assets_legal_resource_dir_array = ["lib/assets/images", "lib/assets/texts"]
92
+ # fonts_legal_resource_dir_array = ["lib/assets/fonts"]
93
+ # illegal_resource_dir_array = ["wrong/path/to/non-existed_folder"]
94
+ #
95
+ def self.check_flr_assets_is_legal(flr_config)
96
+ core_version = flr_config["core_version"]
97
+ dartfmt_line_length = flr_config["dartfmt_line_length"]
98
+ assets_resource_dir_array = flr_config["assets"]
99
+ fonts_resource_dir_array = flr_config["fonts"]
100
+
101
+ if assets_resource_dir_array.is_a?(Array) == false
102
+ assets_resource_dir_array = []
103
+ end
104
+
105
+ if fonts_resource_dir_array.is_a?(Array) == false
106
+ fonts_resource_dir_array = []
107
+ end
108
+
109
+ # 移除非法的 resource_dir(nil,空字符串,空格字符串)
110
+ assets_resource_dir_array = assets_resource_dir_array - [nil, "", " "]
111
+ fonts_resource_dir_array = fonts_resource_dir_array - [nil, "", " "]
112
+ # 过滤重复的 resource_dir
113
+ assets_resource_dir_array = assets_resource_dir_array.uniq
114
+ fonts_resource_dir_array = fonts_resource_dir_array.uniq
115
+
116
+
117
+ # 筛选合法的和非法的resource_dir
118
+ assets_legal_resource_dir_array = []
119
+ fonts_legal_resource_dir_array = []
120
+ illegal_resource_dir_array = []
121
+
122
+ assets_resource_dir_array.each do |resource_dir|
123
+ if File.exist?(resource_dir) == true
124
+ assets_legal_resource_dir_array.push(resource_dir)
125
+ else
126
+ illegal_resource_dir_array.push(resource_dir)
127
+ end
128
+ end
129
+
130
+ fonts_resource_dir_array.each do |resource_dir|
131
+ if File.exist?(resource_dir) == true
132
+ fonts_legal_resource_dir_array.push(resource_dir)
133
+ else
134
+ illegal_resource_dir_array.push(resource_dir)
135
+ end
136
+ end
137
+
138
+ legal_resource_dir_array = assets_legal_resource_dir_array + fonts_legal_resource_dir_array
139
+ if legal_resource_dir_array.length <= 0
140
+
141
+ if illegal_resource_dir_array.length > 0
142
+ message = "[!]: warning, found the following resource directory which is not existed: ".warning_style
143
+ illegal_resource_dir_array.each do |resource_dir|
144
+ message = message + "\n" + " - #{resource_dir}".warning_style
145
+ end
146
+ puts(message)
147
+ puts("")
148
+ end
149
+
150
+ message = <<-MESSAGE
151
+ #{"[x]: have no valid resource directories configuration in pubspec.yaml".error_style}
152
+ #{"[*]: please manually configure the resource directories to fix it, for example: ".tips_style}
153
+
154
+ #{"flr:".tips_style}
155
+ #{"core_version: #{core_version}".tips_style}
156
+ #{"dartfmt_line_length: #{dartfmt_line_length}".tips_style}
157
+ #{"# config the image and text resource directories that need to be scanned".tips_style}
158
+ #{"assets:".tips_style}
159
+ #{"- lib/assets/images".tips_style}
160
+ #{"- lib/assets/texts".tips_style}
161
+ #{"# config the font resource directories that need to be scanned".tips_style}
162
+ #{"fonts:".tips_style}
163
+ #{"- lib/assets/fonts".tips_style}
164
+ MESSAGE
165
+
166
+ raise(message)
167
+ end
168
+
169
+ resource_dir_result_tuple = [assets_legal_resource_dir_array, fonts_legal_resource_dir_array, illegal_resource_dir_array]
170
+ return resource_dir_result_tuple
171
+ end
172
+ end
173
+ end
174
+
175
+
@@ -0,0 +1,741 @@
1
+ require 'yaml'
2
+ require 'find'
3
+ require 'listen'
4
+ require 'flr/version'
5
+ require 'flr/string_extensions'
6
+ require 'flr/checker'
7
+ require 'flr/util/file_util'
8
+ require 'flr/util/asset_util'
9
+ require 'flr/util/code_util'
10
+
11
+ # 专有名词简单解释和示例:
12
+ # (详细定义请看 flr-core 项目的文档描述)
13
+ #
14
+ # package_name:flutter工程的package产物的名称,例如“flutter_demo”
15
+ # resource_file:flutter工程的资源文件,例如“lib/assets/images/hot_foot_N.png”、“lib/assets/images/3.0x/hot_foot_N.png”
16
+ # asset:flutter工程的package产物中资源,可当作是工程中的资源文件的映射和声明,例如上述2个资源对于的asset都是“packages/flutter_demo/assets/images/hot_foot_N.png”
17
+ # file_basename:资源的文件名,其定义是“#{file_basename_no_extension}#{file_extname}”,例如“hot_foot_N.png”
18
+ # file_basename_no_extension:资源的不带扩展名的文件名,例如“hot_foot_N”
19
+ # file_extname:资源的扩展名,例如“.png”
20
+ #
21
+ # asset_name:main asset的名称,例如“assets/images/hot_foot_N.png”
22
+ # asset_id:资源ID,其值一般为 file_basename_no_extension
23
+
24
+ module Flr
25
+ class Command
26
+
27
+ # Listen Class Instance
28
+ @@listener = nil
29
+
30
+ # show the version of flr
31
+ def self.version
32
+ version_desc = "Flr version #{Flr::VERSION}\nCoreLogic version #{Flr::CORE_VERSION}"
33
+ puts(version_desc)
34
+ end
35
+
36
+ # get the right version of r_dart_library package based on flutter's version
37
+ # to get more detail, see https://github.com/YK-Unit/r_dart_library#dependency-relationship-table
38
+ def self.get_r_dart_library_version
39
+ r_dart_library_version = "0.1.1"
40
+
41
+ # $ flutter --version
42
+ # Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git
43
+ # Framework • revision 27321ebbad (5 weeks ago) • 2019-12-10 18:15:01 -0800
44
+ # Engine • revision 2994f7e1e6
45
+ # Tools • Dart 2.7.0
46
+ flutter_version_result = `flutter --version`
47
+ if (flutter_version_result.nil? == true || flutter_version_result.empty? == true)
48
+ return r_dart_library_version
49
+ end
50
+
51
+ version_with_hotfix_str = flutter_version_result.split(" ")[1]
52
+ version_without_hotfix_str = version_with_hotfix_str.split("+")[0]
53
+
54
+ if Version.new(version_with_hotfix_str) >= Version.new("1.10.15")
55
+ r_dart_library_version = "0.2.1"
56
+ end
57
+
58
+ return r_dart_library_version
59
+ end
60
+
61
+ # 对 flutter 工程进行初始化
62
+ def self.init
63
+ flutter_project_root_dir = FileUtil.get_cur_flutter_project_root_dir
64
+
65
+ # ----- Step-1 Begin -----
66
+ # 进行环境检测:
67
+ # - 检测当前 flutter 工程根目录是否存在 pubspec.yaml
68
+ #
69
+
70
+ begin
71
+ Checker.check_pubspec_file_is_existed(flutter_project_root_dir)
72
+
73
+ pubspec_file_path = FileUtil.get_pubspec_file_path
74
+
75
+ pubspec_config = FileUtil.load_pubspec_config_from_file(pubspec_file_path)
76
+
77
+ rescue Exception => e
78
+ puts(e.message)
79
+ return
80
+ end
81
+
82
+ # ----- Step-1 End -----
83
+
84
+ puts("init #{flutter_project_root_dir} now...")
85
+
86
+ # ----- Step-2 Begin -----
87
+ # 添加 flr_config 和 r_dart_library 的依赖声明到 pubspec.yaml
88
+ #
89
+
90
+ dependencies_config = pubspec_config["dependencies"]
91
+
92
+ # 添加 flr_config 到 pubspec.yaml
93
+ #
94
+ # flr_config: Flr的配置信息
95
+ # ```yaml
96
+ # flr:
97
+ # core_version: 1.0.0
98
+ # dartfmt_line_length: 80
99
+ # assets: []
100
+ # fonts: []
101
+ # ```
102
+ flr_config = Hash["core_version" => "#{Flr::CORE_VERSION}", "dartfmt_line_length" => Flr::DARTFMT_LINE_LENGTH, "assets" => [], "fonts" => []]
103
+ pubspec_config["flr"] = flr_config
104
+
105
+ # 添加 r_dart_library(https://github.com/YK-Unit/r_dart_library)的依赖声明
106
+ # - 获取正确的库版本
107
+ # - 添加依赖声明
108
+ #
109
+ # r_dart_library的依赖声明:
110
+ # ```yaml
111
+ # r_dart_library:
112
+ # git:
113
+ # url: "https://github.com/YK-Unit/r_dart_library.git"
114
+ # ref: 0.1.1
115
+ # ```
116
+ r_dart_library_version = get_r_dart_library_version
117
+ r_dart_library_config = Hash["git" => Hash["url" => "https://github.com/YK-Unit/r_dart_library.git", "ref" => r_dart_library_version]]
118
+ dependencies_config["r_dart_library"] = r_dart_library_config
119
+ pubspec_config["dependencies"] = dependencies_config
120
+
121
+ puts("add flr configuration into pubspec.yaml done!")
122
+ puts("add dependency \"r_dart_library\"(https://github.com/YK-Unit/r_dart_library) into pubspec.yaml done!")
123
+
124
+ # ----- Step-2 End -----
125
+
126
+ # ----- Step-3 Begin -----
127
+ # 对Flutter配置进行修正,以避免执行获取依赖操作时会失败:
128
+ # - 检测Flutter配置中的assets选项是否是一个非空数组;若不是,则删除assets选项;
129
+ # - 检测Flutter配置中的fonts选项是否是一个非空数组;若不是,则删除fonts选项。
130
+ #
131
+
132
+ flutter_config = pubspec_config["flutter"]
133
+
134
+ flutter_assets = flutter_config["assets"]
135
+ should_rm_flutter_assets_Key = true
136
+ if flutter_assets.is_a?(Array) == true and flutter_assets.empty? == false
137
+ should_rm_flutter_assets_Key = false
138
+ end
139
+ if should_rm_flutter_assets_Key
140
+ flutter_config.delete("assets")
141
+ end
142
+
143
+ flutter_fonts = flutter_config["fonts"]
144
+ should_rm_flutter_fonts_Key = true
145
+ if flutter_fonts.is_a?(Array) == true and flutter_fonts.empty? == false
146
+ should_rm_flutter_fonts_Key = false
147
+ end
148
+ if should_rm_flutter_fonts_Key
149
+ flutter_config.delete("fonts")
150
+ end
151
+
152
+ pubspec_config["flutter"] = flutter_config
153
+
154
+ # ----- Step-3 End -----
155
+
156
+ # 保存 pubspec.yaml
157
+ FileUtil.dump_pubspec_config_to_file(pubspec_config, pubspec_file_path)
158
+
159
+ puts("get dependency \"r_dart_library\" via execute \"flutter pub get\" now ...")
160
+
161
+ # ----- Step-4 Begin -----
162
+ # 调用 flutter 工具,为 flutter 工程获取依赖
163
+
164
+ get_flutter_pub_cmd = "flutter pub get"
165
+ system(get_flutter_pub_cmd)
166
+
167
+ puts("get dependency \"r_dart_library\" done !!!")
168
+
169
+ # ----- Step-4 End -----
170
+
171
+ puts("[√]: init done !!!")
172
+ end
173
+
174
+ # 扫描资源目录,自动为资源添加声明到 pubspec.yaml 和生成 r.g.dart
175
+ def self.generate
176
+
177
+ flutter_project_root_dir = FileUtil.get_cur_flutter_project_root_dir
178
+
179
+ # 警告日志数组
180
+ warning_messages = []
181
+
182
+ # ----- Step-1 Begin -----
183
+ # 进行环境检测;若发现不合法的环境,则抛出异常,终止当前进程:
184
+ # - 检测当前flutter工程根目录是否存在pubspec.yaml
185
+ # - 检测当前pubspec.yaml中是否存在Flr的配置
186
+ # - 检测当前flr_config中的resource_dir配置是否合法:
187
+ # 判断合法的标准是:assets配置或者fonts配置了至少1个legal_resource_dir
188
+ #
189
+
190
+ begin
191
+ Checker.check_pubspec_file_is_existed(flutter_project_root_dir)
192
+
193
+ pubspec_file_path = FileUtil.get_pubspec_file_path
194
+
195
+ pubspec_config = FileUtil.load_pubspec_config_from_file(pubspec_file_path)
196
+
197
+ Checker.check_flr_config_is_existed(pubspec_config)
198
+
199
+ flr_config = pubspec_config["flr"]
200
+
201
+ resource_dir_result_tuple = Checker.check_flr_assets_is_legal(flr_config)
202
+
203
+ rescue Exception => e
204
+ puts(e.message)
205
+ return
206
+ end
207
+
208
+ package_name = pubspec_config["name"]
209
+
210
+ # ----- Step-1 End -----
211
+
212
+ # ----- Step-2 Begin -----
213
+ # 进行核心逻辑版本检测:
214
+ # 检测Flr配置中的核心逻辑版本号和当前工具的核心逻辑版本号是否一致;若不一致,则生成“核心逻辑版本不一致”的警告日志,存放到警告日志数组
215
+
216
+ flr_core_version = flr_config["core_version"]
217
+
218
+ if flr_core_version.nil?
219
+ flr_core_version = "unknown"
220
+ end
221
+
222
+ if flr_core_version != Flr::CORE_VERSION
223
+ message = <<-MESSAGE
224
+ #{"[!]: warning, the core logic version of the configured Flr tool is #{flr_core_version}, while the core logic version of the currently used Flr tool is #{Flr::CORE_VERSION}".warning_style}
225
+ #{"[*]: to fix it, you should make sure that the core logic version of the Flr tool you are currently using is consistent with the configuration".tips_style}
226
+ MESSAGE
227
+
228
+ warning_messages.push(message)
229
+ end
230
+
231
+ # ----- Step-2 End -----
232
+
233
+ # ----- Step-3 Begin -----
234
+ # 获取assets_legal_resource_dir数组、fonts_legal_resource_dir数组和illegal_resource_dir数组:
235
+ # - 从flr_config中的assets配置获取assets_legal_resource_dir数组和assets_illegal_resource_dir数组;
236
+ # - 从flr_config中的fonts配置获取fonts_legal_resource_dir数组和fonts_illegal_resource_dir数组;
237
+ # - 合并assets_illegal_resource_dir数组和fonts_illegal_resource_dir数组为illegal_resource_dir数组‘;若illegal_resource_dir数组长度大于0,则生成“存在非法的资源目录”的警告日志,存放到警告日志数组。
238
+
239
+ # 合法的资源目录数组
240
+ assets_legal_resource_dir_array = resource_dir_result_tuple[0]
241
+ fonts_legal_resource_dir_array = resource_dir_result_tuple[1]
242
+ # 非法的资源目录数组
243
+ illegal_resource_dir_array = resource_dir_result_tuple[2]
244
+
245
+ if illegal_resource_dir_array.length > 0
246
+ message = "[!]: warning, found the following resource directory which is not existed: ".warning_style
247
+ illegal_resource_dir_array.each do |resource_dir|
248
+ message = message + "\n" + " - #{resource_dir}".warning_style
249
+ end
250
+
251
+ warning_messages.push(message)
252
+ end
253
+
254
+ # ----- Step-3 End -----
255
+
256
+ # 扫描资源
257
+ puts("scan assets now ...")
258
+
259
+ # ----- Step-4 Begin -----
260
+ # 扫描assets_legal_resource_dir数组中的legal_resource_dir,输出image_asset数组和illegal_image_file数组:
261
+ # - 创建image_asset数组、illegal_image_file数组;
262
+ # - 遍历assets_legal_resource_dir数组,按照如下处理每个资源目录:
263
+ # - 扫描当前资源目录和其第1级的子目录,查找所有image_file;
264
+ # - 根据legal_resource_file的标准,筛选查找结果生成legal_image_file子数组和illegal_image_file子数组;illegal_image_file子数组合并到illegal_image_file数组;
265
+ # - 根据image_asset的定义,遍历legal_image_file子数组,生成image_asset子数;组;image_asset子数组合并到image_asset数组。
266
+ # - 对image_asset数组做去重处理;
267
+ # - 按照字典顺序对image_asset数组做升序排列(一般使用开发语言提供的默认的sort算法即可);
268
+ # - 输出image_asset数组和illegal_image_file数组。
269
+ #
270
+
271
+ image_asset_array = []
272
+ illegal_image_file_array = []
273
+
274
+ assets_legal_resource_dir_array.each do |resource_dir|
275
+ image_file_result_tuple = FileUtil.find_image_files(resource_dir)
276
+ legal_image_file_subarray = image_file_result_tuple[0]
277
+ illegal_image_file_subarray = image_file_result_tuple[1]
278
+
279
+ illegal_image_file_array += illegal_image_file_subarray
280
+
281
+ image_asset_subarray = AssetUtil.generate_image_assets(legal_image_file_subarray, resource_dir, package_name)
282
+ image_asset_array += image_asset_subarray
283
+ end
284
+
285
+ image_asset_array.uniq!
286
+ image_asset_array.sort!
287
+
288
+ # ----- Step-4 End -----
289
+
290
+ # ----- Step-5 Begin -----
291
+ # 扫描assets_legal_resource_dir数组中的legal_resource_dir,输出text_asset数组和illegal_text_file数组:
292
+ # - 创建text_asset数组、illegal_text_file数组;
293
+ # - 遍历assets_legal_resource_dir数组,按照如下处理每个资源目录:
294
+ # - 扫描当前资源目录和其所有层级的子目录,查找所有text_file;
295
+ # - 根据legal_resource_file的标准,筛选查找结果生成legal_text_file子数组和illegal_text_file子数组;illegal_text_file子数组合并到illegal_text_file数组;
296
+ # - 根据text_asset的定义,遍历legal_text_file子数组,生成text_asset子数组;text_asset子数组合并到text_asset数组。
297
+ # - 对text_asset数组做去重处理;
298
+ # - 按照字典顺序对text_asset数组做升序排列(一般使用开发语言提供的默认的sort算法即可);
299
+ # - 输出text_asset数组和illegal_image_file数组。
300
+ #
301
+
302
+ text_asset_array = []
303
+ illegal_text_file_array = []
304
+
305
+ assets_legal_resource_dir_array.each do |resource_dir|
306
+ text_file_result_tuple = FileUtil.find_text_files(resource_dir)
307
+ legal_text_file_subarray = text_file_result_tuple[0]
308
+ illegal_text_file_subarray = text_file_result_tuple[1]
309
+
310
+ illegal_text_file_array += illegal_text_file_subarray
311
+
312
+ text_asset_subarray = AssetUtil.generate_text_assets(legal_text_file_subarray, resource_dir, package_name)
313
+ text_asset_array += text_asset_subarray
314
+ end
315
+
316
+ text_asset_array.uniq!
317
+ text_asset_array.sort!
318
+
319
+ # ----- Step-5 End -----
320
+
321
+ # ----- Step-6 Begin -----
322
+ # 扫描fonts_legal_resource_dir数组中的legal_resource_dir,输出font_family_config数组、illegal_font_file数组:
323
+ # - 创建font_family_config数组、illegal_font_file数组;
324
+ # - 遍历fonts_legal_resource_dir数组,按照如下处理每个资源目录:
325
+ # - 扫描当前资源目录,获得其第1级子目录数组,并按照字典顺序对数组做升序排列(一般使用开发语言提供的默认的sort算法即可);
326
+ # - 遍历第1级子目录数组,按照如下处理每个子目录:
327
+ # - 获取当前子目录的名称,生成font_family_name;
328
+ # - 扫描当前子目录和其所有子目录,查找所有font_file;
329
+ # - 根据legal_resource_file的标准,筛选查找结果生成legal_font_file数组和illegal_font_file子数组;illegal_font_file子数组合并到illegal_font_file数组;
330
+ # - 据font_asset的定义,遍历legal_font_file数组,生成font_asset_config数组;
331
+ # - 按照字典顺序对生成font_asset_config数组做升序排列(比较asset的值);
332
+ # - 根据font_family_config的定义,为当前子目录组织font_family_name和font_asset_config数组生成font_family_config对象,添加到font_family_config子数组;font_family_config子数组合并到font_family_config数组。
333
+ # - 输出font_family_config数组、illegal_font_file数组;
334
+ # - 按照字典顺序对font_family_config数组做升序排列(比较family的值)。
335
+ #
336
+
337
+ font_family_config_array = []
338
+ illegal_font_file_array = []
339
+
340
+ fonts_legal_resource_dir_array.each do |resource_dir|
341
+ font_family_dir_array = FileUtil.find_top_child_dirs(resource_dir)
342
+
343
+ font_family_dir_array.each do |font_family_dir|
344
+ font_family_name = File.basename(font_family_dir)
345
+
346
+ font_file_result_tuple = FileUtil.find_font_files_in_font_family_dir(font_family_dir)
347
+ legal_font_file_array = font_file_result_tuple[0]
348
+ illegal_font_file_subarray = font_file_result_tuple[1]
349
+
350
+ illegal_font_file_array += illegal_font_file_subarray
351
+
352
+ unless legal_font_file_array.length > 0
353
+ next
354
+ end
355
+
356
+ font_asset_config_array = AssetUtil.generate_font_asset_configs(legal_font_file_array, font_family_dir, package_name)
357
+ font_asset_config_array.sort!{|a, b| a["asset"] <=> b["asset"]}
358
+
359
+ font_family_config = Hash["family" => font_family_name , "fonts" => font_asset_config_array]
360
+ font_family_config_array.push(font_family_config)
361
+ end
362
+ end
363
+
364
+ font_family_config_array.sort!{|a, b| a["family"] <=> b["family"]}
365
+
366
+ # ----- Step-6 End -----
367
+
368
+ puts("scan assets done !!!")
369
+
370
+ # ----- Step-7 Begin -----
371
+ # 检测是否存在illegal_resource_file:
372
+ # - 合并illegal_image_file数组、illegal_text_file数组和illegal_font_file数组为illegal_resource_file数组;
373
+ # - 若illegal_resource_file数组长度大于0,则生成“存在非法的资源文件”的警告日志,存放到警告日志数组。
374
+
375
+ illegal_resource_file_array = illegal_image_file_array + illegal_text_file_array + illegal_font_file_array
376
+ if illegal_resource_file_array.length > 0
377
+ message = "[!]: warning, found the following illegal resource file who's file basename contains illegal characters: ".warning_style
378
+ illegal_resource_file_array.each do |resource_file|
379
+ message = message + "\n" + " - #{resource_file}".warning_style
380
+ end
381
+ message = message + "\n" + "[*]: to fix it, you should only use letters (a-z, A-Z), numbers (0-9), and the other legal characters ('_', '+', '-', '.', '·', '!', '@', '&', '$', '¥') to name the file".tips_style
382
+
383
+ warning_messages.push(message)
384
+ end
385
+
386
+ # ----- Step-7 End -----
387
+
388
+ puts("specify scanned assets in pubspec.yaml now ...")
389
+
390
+ # ----- Step-8 Begin -----
391
+ # 为扫描得到的legal_resource_file添加资源声明到pubspec.yaml:
392
+ # - 合并image_asset数组和text_asset数组为asset数组(image_asset数组元素在前);
393
+ # - 修改pubspec.yaml中flutter-assets配置的值为asset数组;
394
+ # - 修改pubspec.yaml中flutter-fonts配置的值为font_family_config数组。
395
+
396
+ asset_array = image_asset_array + text_asset_array
397
+ if asset_array.length > 0
398
+ pubspec_config["flutter"]["assets"] = asset_array
399
+ else
400
+ pubspec_config["flutter"].delete("assets")
401
+ end
402
+
403
+ if font_family_config_array.length > 0
404
+ pubspec_config["flutter"]["fonts"] = font_family_config_array
405
+ else
406
+ pubspec_config["flutter"].delete("fonts")
407
+ end
408
+
409
+ FileUtil.dump_pubspec_config_to_file(pubspec_config, pubspec_file_path)
410
+
411
+ # ----- Step-8 End -----
412
+
413
+ puts("specify scanned assets in pubspec.yaml done !!!")
414
+
415
+ # ----- Step-9 Begin -----
416
+ # 按照SVG分类,从image_asset数组筛选得到有序的non_svg_image_asset数组和svg_image_asset数组:
417
+ # - 按照SVG分类,从image_asset数组筛选得到non_svg_image_asset数组和svg_image_asset数组;
418
+ # - 按照字典顺序对non_svg_image_asset数组和svg_image_asset数组做升序排列(一般使用开发语言提供的默认的sort算法即可);
419
+ #
420
+
421
+ non_svg_image_asset_array = []
422
+ svg_image_asset_array = []
423
+
424
+ image_asset_array.each do |image_asset|
425
+ file_extname = File.extname(image_asset).downcase
426
+
427
+ if file_extname.eql?(".svg")
428
+ svg_image_asset_array.push(image_asset)
429
+ else
430
+ non_svg_image_asset_array.push(image_asset)
431
+ end
432
+ end
433
+
434
+ non_svg_image_asset_array.sort!
435
+ svg_image_asset_array.sort!
436
+
437
+ # ----- Step-9 End -----
438
+
439
+ puts("generate \"r.g.dart\" now ...")
440
+
441
+ # ----- Step-10 Begin -----
442
+ # 在当前根目录下创建新的r.g.dart文件。
443
+ #
444
+
445
+ r_dart_path = "#{flutter_project_root_dir}/lib/r.g.dart"
446
+ r_dart_file = File.open(r_dart_path, "w")
447
+
448
+ # ----- Step-10 End -----
449
+
450
+ # ----- Step-11 Begin -----
451
+ # 生成 R 类的代码,追加写入r.g.dart
452
+ #
453
+
454
+ g_R_class_code = CodeUtil.generate_R_class(package_name)
455
+ r_dart_file.puts(g_R_class_code)
456
+
457
+ # ----- Step-11 End -----
458
+
459
+ # ----- Step-12 Begin -----
460
+ # 生成 AssetResource 类的代码,追加写入r.g.dart
461
+ #
462
+
463
+ r_dart_file.puts("\n")
464
+ g_AssetResource_class_code = CodeUtil.generate_AssetResource_class(package_name)
465
+ r_dart_file.puts(g_AssetResource_class_code)
466
+
467
+ # ----- Step-12 End -----
468
+
469
+ # ----- Step-13 Begin -----
470
+ # 遍历 non_svg_image_asset 数组,生成 _R_Image_AssetResource 类,追加写入 r.g.dart
471
+ #
472
+
473
+ r_dart_file.puts("\n")
474
+ g__R_Image_AssetResource_class_code = CodeUtil.generate__R_Image_AssetResource_class(non_svg_image_asset_array, package_name)
475
+ r_dart_file.puts(g__R_Image_AssetResource_class_code)
476
+
477
+ # ----- Step-13 End -----
478
+
479
+ # ----- Step-14 Begin -----
480
+ # 遍历 svg_image_asset 数组,生成 _R_Svg_AssetResource 类,追加写入 r.g.dart。
481
+ #
482
+
483
+ r_dart_file.puts("\n")
484
+ g__R_Svg_AssetResource_class_code = CodeUtil.generate__R_Svg_AssetResource_class(svg_image_asset_array, package_name)
485
+ r_dart_file.puts(g__R_Svg_AssetResource_class_code)
486
+
487
+ # ----- Step-14 End -----
488
+
489
+ # ----- Step-15 Begin -----
490
+ # 遍历 text_asset 数组,生成 _R_Image_AssetResource 类,追加写入 r.g.dart
491
+ #
492
+
493
+ r_dart_file.puts("\n")
494
+ g__R_Text_AssetResource_class_code = CodeUtil.generate__R_Text_AssetResource_class(text_asset_array, package_name)
495
+ r_dart_file.puts(g__R_Text_AssetResource_class_code)
496
+
497
+ # ----- Step-15 End -----
498
+
499
+
500
+ # ----- Step-16 Begin -----
501
+ # 遍历non_svg_image_asset数组,生成 _R_Image 类,追加写入 r.g.dart
502
+ #
503
+
504
+ r_dart_file.puts("\n")
505
+ g__R_Image_class_code = CodeUtil.generate__R_Image_class(non_svg_image_asset_array, package_name)
506
+ r_dart_file.puts(g__R_Image_class_code)
507
+
508
+ # ----- Step-16 End -----
509
+
510
+ # ----- Step-17 Begin -----
511
+ # 遍历 svg_image_asset 数组,生成 _R_Svg 类,追加写入 r.g.dart。
512
+ #
513
+
514
+ r_dart_file.puts("\n")
515
+ g__R_Svg_class_code = CodeUtil.generate__R_Svg_class(svg_image_asset_array, package_name)
516
+ r_dart_file.puts(g__R_Svg_class_code)
517
+
518
+ # ----- Step-17 End -----
519
+
520
+ # ----- Step-18 Begin -----
521
+ # 遍历 text_asset 数组,生成 _R_Image 类,追加写入 r.g.dart。
522
+ #
523
+
524
+ r_dart_file.puts("\n")
525
+ g__R_Text_class_code = CodeUtil.generate__R_Text_class(text_asset_array, package_name)
526
+ r_dart_file.puts(g__R_Text_class_code)
527
+
528
+ # ----- Step-18 End -----
529
+
530
+ # ----- Step-19 Begin -----
531
+ # 遍历font_family_config数组,根据下面的模板生成_R_Font_Family类,追加写入r.g.dart。
532
+
533
+ r_dart_file.puts("\n")
534
+ g__R_Font_Family_class_code = CodeUtil.generate__R_FontFamily_class(font_family_config_array, package_name)
535
+ r_dart_file.puts(g__R_Font_Family_class_code)
536
+
537
+ # ----- Step-19 End -----
538
+
539
+ # ----- Step-20 Begin -----
540
+ # 结束操作,保存 r.g.dart
541
+ #
542
+
543
+ r_dart_file.close
544
+ puts("generate \"r.g.dart\" done !!!")
545
+
546
+ # ----- Step-20 End -----
547
+
548
+ # ----- Step-21 Begin -----
549
+ # 调用 flutter 工具对 r.g.dart 进行格式化操作
550
+ #
551
+
552
+ dartfmt_line_length = flr_config["dartfmt_line_length"]
553
+ if dartfmt_line_length.nil? or dartfmt_line_length.is_a?(Integer) == false
554
+ dartfmt_line_length = Flr::DARTFMT_LINE_LENGTH
555
+ end
556
+
557
+ if dartfmt_line_length < Flr::DARTFMT_LINE_LENGTH
558
+ dartfmt_line_length = Flr::DARTFMT_LINE_LENGTH
559
+ end
560
+
561
+ flutter_format_cmd = "flutter format #{r_dart_path} -l #{dartfmt_line_length}"
562
+ puts("execute \"#{flutter_format_cmd}\" now ...")
563
+ system(flutter_format_cmd)
564
+ puts("execute \"#{flutter_format_cmd}\" done !!!")
565
+
566
+ # ----- Step-21 End -----
567
+
568
+ # ----- Step-22 Begin -----
569
+ # 调用flutter工具,为flutter工程获取依赖
570
+ #
571
+
572
+ get_flutter_pub_cmd = "flutter pub get"
573
+ puts("execute \"#{get_flutter_pub_cmd}\" now ...")
574
+ system(get_flutter_pub_cmd)
575
+ puts("execute \"#{get_flutter_pub_cmd}\" done !!!")
576
+
577
+ # ----- Step-22 End -----
578
+
579
+ puts("[√]: generate done !!!")
580
+
581
+ # ----- Step-23 Begin -----
582
+ # 判断警告日志数组是否为空,若不为空,输出所有警告日志
583
+ #
584
+
585
+ if warning_messages.length > 0
586
+ warning_messages.each do |warning_message|
587
+ puts("")
588
+ puts(warning_message)
589
+ end
590
+ end
591
+
592
+ # ----- Step-23 End -----
593
+
594
+ end
595
+
596
+ # 启动一个资源变化监控服务,若检测到有资源变化,就自动执行generate操作;手动输入`Ctrl-C`,可终止当前服务
597
+ def self.start_monitor
598
+
599
+ flutter_project_root_dir = FileUtil.get_cur_flutter_project_root_dir
600
+
601
+ # ----- Step-1 Begin -----
602
+ # 进行环境检测;若发现不合法的环境,则抛出异常,终止当前进程:
603
+ # - 检测当前flutter工程根目录是否存在pubspec.yaml
604
+ # - 检测当前pubspec.yaml中是否存在Flr的配置
605
+ # - 检测当前flr_config中的resource_dir配置是否合法:
606
+ # 判断合法的标准是:assets配置或者fonts配置了至少1个legal_resource_dir
607
+ #
608
+
609
+ begin
610
+ Checker.check_pubspec_file_is_existed(flutter_project_root_dir)
611
+
612
+ pubspec_file_path = FileUtil.get_pubspec_file_path
613
+
614
+ pubspec_config = FileUtil.load_pubspec_config_from_file(pubspec_file_path)
615
+
616
+ Checker.check_flr_config_is_existed(pubspec_config)
617
+
618
+ flr_config = pubspec_config["flr"]
619
+
620
+ resource_dir_result_tuple = Checker.check_flr_assets_is_legal(flr_config)
621
+
622
+ rescue Exception => e
623
+ puts(e.message)
624
+ return
625
+ end
626
+
627
+ package_name = pubspec_config["name"]
628
+
629
+ # ----- Step-1 End -----
630
+
631
+ # ----- Step-2 Begin -----
632
+ # 执行一次 flr generate 操作
633
+ #
634
+
635
+ now_str = Time.now.to_s
636
+ puts("--------------------------- #{now_str} ---------------------------")
637
+ puts("scan assets, specify scanned assets in pubspec.yaml, generate \"r.g.dart\" now ...")
638
+ puts("\n")
639
+ generate
640
+ puts("\n")
641
+ puts("scan assets, specify scanned assets in pubspec.yaml, generate \"r.g.dart\" done !!!")
642
+ puts("---------------------------------------------------------------------------------")
643
+ puts("\n")
644
+
645
+ # ----- Step-2 End -----
646
+
647
+ # ----- Step-3 Begin -----
648
+ # 获取legal_resource_dir数组:
649
+ # - 从flr_config中的assets配置获取assets_legal_resource_dir数组;
650
+ # - 从flr_config中的fonts配置获取fonts_legal_resource_dir数组;
651
+ # - 合并assets_legal_resource_dir数组和fonts_legal_resource_dir数组为legal_resource_dir数组。
652
+ #
653
+
654
+ # 合法的资源目录数组
655
+ assets_legal_resource_dir_array = resource_dir_result_tuple[0]
656
+ fonts_legal_resource_dir_array = resource_dir_result_tuple[1]
657
+
658
+ legal_resource_dir_array = assets_legal_resource_dir_array + fonts_legal_resource_dir_array
659
+
660
+ # 非法的资源目录数组
661
+ illegal_resource_dir_array = resource_dir_result_tuple[2]
662
+
663
+ # ----- Step-3 End -----
664
+
665
+ # ----- Step-4 Begin -----
666
+ # 启动资源监控服务
667
+ # - 启动一个文件监控服务,对 legal_resource_dir 数组中的资源目录进行文件监控
668
+ # - 若服务检测到资源变化(资源目录下的发生增/删/改文件),则执行一次 flr generate 操作
669
+ #
670
+
671
+ now_str = Time.now.to_s
672
+ puts("--------------------------- #{now_str} ---------------------------")
673
+ puts("launch a monitoring service now ...")
674
+ puts("launching ...")
675
+ # stop the monitoring service if exists
676
+ stop_monitor
677
+ puts("launch a monitoring service done !!!")
678
+ puts("the monitoring service is monitoring the following resource directory:")
679
+ legal_resource_dir_array.each do |resource_dir|
680
+ puts(" - #{resource_dir}")
681
+ end
682
+ if illegal_resource_dir_array.length > 0
683
+ puts("")
684
+ puts("[!]: warning, found the following resource directory which is not existed: ".warning_style)
685
+ illegal_resource_dir_array.each do |resource_dir|
686
+ puts(" - #{resource_dir}".warning_style)
687
+ end
688
+ end
689
+ puts("---------------------------------------------------------------------------------")
690
+ puts("\n")
691
+
692
+ # Allow array of directories as input #92
693
+ # https://github.com/guard/listen/pull/92
694
+ @@listener = Listen.to(*legal_resource_dir_array, ignore: [/\.DS_Store/], latency: 0.5, wait_for_delay: 5, relative: true) do |modified, added, removed|
695
+ # for example: 2013-03-30 03:13:14 +0900
696
+ now_str = Time.now.to_s
697
+ puts("--------------------------- #{now_str} ---------------------------")
698
+ puts("modified resource files: #{modified}")
699
+ puts("added resource files: #{added}")
700
+ puts("removed resource files: #{removed}")
701
+ puts("scan assets, specify scanned assets in pubspec.yaml, generate \"r.g.dart\" now ...")
702
+ puts("\n")
703
+ generate
704
+ puts("\n")
705
+ puts("scan assets, specify scanned assets in pubspec.yaml, generate \"r.g.dart\" done !!!")
706
+ puts("---------------------------------------------------------------------------------")
707
+ puts("\n")
708
+ puts("[*]: the monitoring service is monitoring the asset changes, and then auto scan assets, specifies assets and generates \"r.g.dart\" ...".tips_style)
709
+ puts("[*]: you can press \"Ctrl-C\" to terminate it".tips_style)
710
+ puts("\n")
711
+ end
712
+ # not blocking
713
+ @@listener.start
714
+
715
+ # https://ruby-doc.org/core-2.5.0/Interrupt.html
716
+ begin
717
+ puts("[*]: the monitoring service is monitoring the asset changes, and then auto scan assets, specifies assets and generates \"r.g.dart\" ...".tips_style)
718
+ puts("[*]: you can press \"Ctrl-C\" to terminate it".tips_style)
719
+ puts("\n")
720
+ loop {}
721
+ rescue Interrupt => e
722
+ stop_monitor
723
+ puts("")
724
+ puts("[√]: terminate monitor service done !!!")
725
+ end
726
+
727
+ # ----- Step-4 End -----
728
+
729
+ end
730
+
731
+ # 停止资源变化监控服务
732
+ def self.stop_monitor
733
+ if @@listener.nil? == false
734
+ @@listener.stop
735
+ @@listener = nil
736
+ end
737
+ end
738
+
739
+ end
740
+
741
+ end