fdlint 0.2.0.pre → 0.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/Gemfile.lock +1 -1
- data/README.md +36 -15
- data/Rakefile +1 -1
- data/bin/fdlint +30 -9
- data/lib/fdlint/cli.rb +62 -10
- data/lib/fdlint/helper/logger.rb +1 -1
- data/lib/fdlint/log_entry.rb +14 -0
- data/lib/fdlint/parser/html/html_parser.rb +10 -12
- data/lib/fdlint/parser/html/query.rb +64 -50
- data/lib/fdlint/parser/html/struct.rb +20 -3
- data/lib/fdlint/parser/parser_visitable.rb +11 -5
- data/lib/fdlint/printer/base_printer.rb +6 -0
- data/lib/fdlint/printer/console_printer.rb +15 -23
- data/lib/fdlint/rule.rb +4 -4
- data/lib/fdlint/support/core/object.rb +6 -0
- data/lib/fdlint/support/core_ext.rb +1 -0
- data/lib/fdlint/validator.rb +60 -8
- data/lib/fdlint/version.rb +1 -1
- data/lib/hook/git_pre_commit +18 -0
- data/rules.d/css.rule.rb +1 -1
- data/rules.d/filename.rule.rb +3 -1
- data/rules.d/html.rule.rb +45 -32
- data/rules.d/js.rule.rb +2 -2
- data/test/all_tests.rb +28 -42
- data/test/css/mac_line_end_support_test.rb +10 -12
- data/test/css/parser_test.rb +4 -5
- data/test/css/rule/check_encoding_test.rb +7 -8
- data/test/css/rule/check_list_rule_test.rb +85 -102
- data/test/css/rule/file_name_test.rb +18 -39
- data/test/default_test.rb +1 -14
- data/test/fixtures/css/ad.css +0 -0
- data/test/fixtures/css/adver/test.css +0 -0
- data/test/fixtures/css/camelCase.css +0 -0
- data/test/fixtures/css/min/ad.css +0 -0
- data/test/fixtures/css/min/ad.min.css +0 -0
- data/test/fixtures/html/mixed_log_levels.html +1 -0
- data/test/fixtures/html/mixed_types.html +3 -0
- data/test/helper.rb +116 -16
- data/test/html/mixed_type_test.rb +14 -20
- data/test/html/parser/parse_comment_test.rb +4 -4
- data/test/html/parser/parse_dtd_test.rb +7 -7
- data/test/html/parser/parse_script_tag_test.rb +21 -14
- data/test/html/parser/parse_with_auto_close_tag_test.rb +12 -10
- data/test/html/parser/parse_with_diff_case_test.rb +8 -9
- data/test/html/parser/parse_with_emtpy_test.rb +5 -3
- data/test/html/parser/parse_with_multi_children_test.rb +4 -4
- data/test/html/parser/parse_with_multi_line_test.rb +5 -5
- data/test/html/parser/parse_with_prop_test.rb +10 -10
- data/test/html/parser/parse_with_script_tag_test.rb +4 -4
- data/test/html/parser/parse_with_selfclosing_test.rb +11 -11
- data/test/html/parser/parse_with_simple_tag_test.rb +7 -7
- data/test/html/parser/parse_with_simple_tree_test.rb +6 -6
- data/test/html/parser/parse_with_style_tag_test.rb +4 -4
- data/test/html/parser/parse_with_text_test.rb +7 -7
- data/test/html/parser_test.rb +19 -19
- data/test/html/query_test.rb +18 -18
- data/test/html/rule/check_block_level_element_test.rb +22 -24
- data/test/html/rule/check_button_test.rb +9 -9
- data/test/html/rule/check_css_in_head_test.rb +11 -32
- data/test/html/rule/check_dtd_test.rb +15 -11
- data/test/html/rule/check_form_element_name_test.rb +10 -9
- data/test/html/rule/check_head_contain_meta_and_title_test.rb +28 -34
- data/test/html/rule/check_hyperlink_with_target_test.rb +23 -17
- data/test/html/rule/check_hyperlink_with_title_test.rb +13 -20
- data/test/html/rule/check_id_n_class_downcase_test.rb +8 -19
- data/test/html/rule/check_img_with_alt_prop_test.rb +11 -12
- data/test/html/rule/check_no_import_css_test.rb +20 -20
- data/test/html/rule/check_prop_have_value_test.rb +9 -13
- data/test/html/rule/check_prop_seperator_test.rb +9 -13
- data/test/html/rule/check_style_prop_test.rb +7 -12
- data/test/html/rule/check_tag_closed_test.rb +15 -40
- data/test/html/rule/check_tag_downcase_test.rb +31 -28
- data/test/html/rule/check_unescape_char_test.rb +17 -17
- data/test/html/rule/check_unique_import_test.rb +15 -33
- data/test/html/rule_test.rb +2 -6
- data/test/js/expr/expr.rb +1 -1
- data/test/js/expr/left_hand.rb +1 -1
- data/test/js/expr/operate.rb +1 -1
- data/test/js/expr/primary.rb +1 -1
- data/test/js/parser_test.rb +3 -6
- data/test/js/rule/alert_check_test.rb +5 -19
- data/test/js/rule/base_test.rb +5 -19
- data/test/js/rule/jq_check_test.rb +26 -58
- data/test/js/rule/nest_try_catch_test.rb +26 -43
- data/test/js/rule/new_object_and_new_array_test.rb +5 -21
- data/test/js/rule/no_eval_test.rb +3 -19
- data/test/js/rule/no_global_test.rb +34 -73
- data/test/js/rule/private_method_check_test.rb +14 -43
- data/test/js/rule/semicolon_test.rb +18 -47
- data/test/js/rule/stat_if_with_brace_test.rb +30 -53
- data/test/js/rule/stat_if_with_muti_else_test.rb +36 -53
- data/test/js/rule/use_strict_equal_test.rb +16 -29
- data/test/js/rule_test.rb +2 -4
- data/test/js/stat/if.rb +1 -1
- data/test/js/stat/iter.rb +1 -1
- data/test/js/stat/stat.rb +1 -1
- data/test/js/stat/switch.rb +1 -1
- data/test/js/stat/try.rb +1 -1
- data/test/js/stat/var.rb +1 -1
- data/test/parser_visitable_test.rb +14 -36
- data/test/position_info_test.rb +4 -5
- data/test/runner/log_level_test.rb +30 -25
- metadata +11 -14
- data/lib/fdlint/file_validator.rb +0 -38
- data/lib/fdlint/parser/html/rule/check_tag_rule.rb +0 -80
- data/test/css/rule/compression_test.rb +0 -53
- data/test/html/rule/check_class_count_test.rb +0 -36
- data/test/html/rule/check_html_template_test.rb +0 -103
- data/test/js/rule/all_test.rb +0 -23
- data/test/js/rule/file_checker_test.rb +0 -131
- data/test/rule_dsl/dsl_basic_test.rb +0 -91
- data/test/rule_dsl/importing_test.rb +0 -48
- data/test/test_helper.rb +0 -9
@@ -1,103 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require_relative '../../helper'
|
4
|
-
require 'html/rule/check_tag_rule'
|
5
|
-
|
6
|
-
module XRayTest
|
7
|
-
module HTML
|
8
|
-
module Rule
|
9
|
-
|
10
|
-
class CheckHTMLTemplateTest < Test::Unit::TestCase
|
11
|
-
|
12
|
-
include XRay::HTML
|
13
|
-
|
14
|
-
def setup
|
15
|
-
@rule = XRay::HTML::Rule::CheckTagRule.new
|
16
|
-
@head = %Q(<head>
|
17
|
-
<meta charset="gbk"/>
|
18
|
-
<title>阿里巴巴</title>
|
19
|
-
<mea name="description" content="阿里巴巴批发大市场"/>
|
20
|
-
<meta name="keywords" content="阿里巴巴,采购批发,1688,行业门户,网上贸易,b2b,电子商务"/>
|
21
|
-
<link href="产品线merge.css" rel="stylesheet"/>
|
22
|
-
<link href="页面merge.css" rel="stylesheet"/>
|
23
|
-
<script src="产品线merge.js"></script>
|
24
|
-
<base target="_blank"/>
|
25
|
-
</head>)
|
26
|
-
@doc = %Q(<div id="doc">
|
27
|
-
<div id="alibar">alibar</div>
|
28
|
-
<div id="header" class="w952">header</div>
|
29
|
-
<div id="content" class="w952">content</div>
|
30
|
-
<div id="footer">footer</div>
|
31
|
-
</div>)
|
32
|
-
@body = %Q(<body>
|
33
|
-
#{@doc}
|
34
|
-
<script src="页面merge.js"></script>
|
35
|
-
</body>)
|
36
|
-
@html = %Q(<html lang="zh-CN">
|
37
|
-
#{@head}
|
38
|
-
#{@body}
|
39
|
-
</html>)
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_check_right_tag
|
43
|
-
tag = parse(@html)
|
44
|
-
assert_equal [], @rule.check_html_tag(tag)
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_check_missing_desc
|
48
|
-
tag = parse(@head.sub(/<meta name="description".*?\/>/m, ''))
|
49
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_check_missing_keywords
|
53
|
-
tag = parse(@head.sub(/<meta name="keywords".*?\/>/m, ''))
|
54
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_check_missing_doc
|
58
|
-
tag = parse(@body.sub(/<div id="doc"/m, '<div id="_doc"'))
|
59
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_check_missing_alibar
|
63
|
-
tag = parse(@body.sub(/<div id="alibar"/m, '<div id="_alibar"'))
|
64
|
-
assert_equal [], @rule.check_html_tag(tag)
|
65
|
-
|
66
|
-
tag = parse(@doc.sub(/<div id="alibar"/m, '<div id="_alibar"'))
|
67
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_check_missing_content
|
71
|
-
tag = parse(@body.sub(/<div id="content"/m, '<div id="_content"'))
|
72
|
-
assert_equal [], @rule.check_html_tag(tag)
|
73
|
-
|
74
|
-
tag = parse(@doc.sub(/<div id="content"/m, '<div id="_content"'))
|
75
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_check_missing_footer
|
79
|
-
tag = parse(@body.sub(/<div id="footer"/m, '<div id="_footer"'))
|
80
|
-
assert_equal [], @rule.check_html_tag(tag)
|
81
|
-
|
82
|
-
tag = parse(@doc.sub(/<div id="footer"/m, '<div id="_footer"'))
|
83
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_check_missing_header
|
87
|
-
tag = parse(@body.sub(/<div id="header"/m, '<div id="_header"'))
|
88
|
-
assert_equal [], @rule.check_html_tag(tag)
|
89
|
-
|
90
|
-
tag = parse(@doc.sub(/<div id="header"/m, '<div id="_header"'))
|
91
|
-
assert_equal [["新页面按库中的HTML基本结构模板书写基本页面结构", :warn]], @rule.check_html_tag(tag)
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
def parse(src)
|
96
|
-
XRay::HTML::Parser.parse(src)
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/test/js/rule/all_test.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require_relative '../../helper'
|
2
|
-
|
3
|
-
require 'js/rule/all'
|
4
|
-
|
5
|
-
module XRayTest
|
6
|
-
module JS
|
7
|
-
module Rule
|
8
|
-
|
9
|
-
class AllTest < Test::Unit::TestCase
|
10
|
-
|
11
|
-
def test_initialize
|
12
|
-
all = XRay::JS::Rule::All.new
|
13
|
-
|
14
|
-
assert all.respond_to?(:each)
|
15
|
-
assert all.size > 0
|
16
|
-
assert all.size == all.rules.size
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,131 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require_relative 'base_test'
|
4
|
-
|
5
|
-
require 'js/rule/file_checker'
|
6
|
-
|
7
|
-
module XRayTest
|
8
|
-
module JS
|
9
|
-
module Rule
|
10
|
-
|
11
|
-
class FileCheckerTest < BaseTest
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@checker = XRay::JS::Rule::FileChecker.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_merge_file?
|
18
|
-
assert @checker.merge_file?('abc-merge.js')
|
19
|
-
assert @checker.merge_file?('abc-merge-12345.js')
|
20
|
-
assert @checker.merge_file?('abc-merge12345.js')
|
21
|
-
|
22
|
-
assert !@checker.merge_file?('abc-merge.css')
|
23
|
-
assert !@checker.merge_file?('abc-merge.jss')
|
24
|
-
assert !@checker.merge_file?('-merge.js')
|
25
|
-
assert !@checker.merge_file?('abc-mergeabc.js')
|
26
|
-
assert !@checker.merge_file?('abc-merge-.js')
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_min_file?
|
30
|
-
assert @checker.min_file?('abc-min.js')
|
31
|
-
|
32
|
-
assert !@checker.min_file?('abc-min.jss')
|
33
|
-
assert !@checker.min_file?('-min.js')
|
34
|
-
assert !@checker.min_file?('abc-min1.js')
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_grep_import_js_path
|
38
|
-
pathes = @checker.grep_import_js_path fixture_01
|
39
|
-
assert_equal 6, pathes.length
|
40
|
-
assert_equal %w(
|
41
|
-
http://style.china.alibaba.com/js/common/aliclick.js
|
42
|
-
http://style.china.alibaba.com/js/detail/xpclick.js
|
43
|
-
http://style.china.alibaba.com/js/lib/fdev-v4/widget/util/debug-min.js
|
44
|
-
http://style.china.alibaba.com/js/lib/fdev-v4/widget/web/alitalk-min.js
|
45
|
-
http://style.china.alibaba.com/js/lib/fdev-v4/widget/web/sweet-min.js
|
46
|
-
http://style.china.alibaba.com/js/lib/fdev-v4/widget/web/sweet-min.js
|
47
|
-
), pathes.collect { |path| path[:url] }
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_check_one_line_one_import
|
51
|
-
pathes = @checker.grep_import_js_path fixture_01
|
52
|
-
ret = []
|
53
|
-
pathes.each { |import|
|
54
|
-
r = @checker.check_js_merge_importing import, pathes, ""
|
55
|
-
ret.concat r
|
56
|
-
}
|
57
|
-
assert_equal [
|
58
|
-
["merge文件需要引用压缩版的js, 如a-min.js", :warn, 12, 63],
|
59
|
-
["merge文件需要引用压缩版的js, 如a-min.js", :warn, 13, 62],
|
60
|
-
["一行只能有一个import文件", :error, 18, 96],
|
61
|
-
["merge文件格式不正确", :error, 19, 1],
|
62
|
-
["merge文件格式不正确", :error, 20, 1]
|
63
|
-
], ret
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_has_doc_comment
|
67
|
-
js = '
|
68
|
-
/**
|
69
|
-
* 功能文件头必须要有文档注释
|
70
|
-
* 现在没有对doc格式进行规范
|
71
|
-
* 所以暂时不做文档注释内容检查
|
72
|
-
* 只检则有注释
|
73
|
-
*/
|
74
|
-
|
75
|
-
i++;
|
76
|
-
'
|
77
|
-
assert @checker.has_doc_comment?(js)
|
78
|
-
|
79
|
-
js = '
|
80
|
-
i++;
|
81
|
-
'
|
82
|
-
assert !@checker.has_doc_comment?(js)
|
83
|
-
|
84
|
-
js = '
|
85
|
-
/*
|
86
|
-
* 多行注释不属于文档注释
|
87
|
-
* 文档注释需要以/*开头
|
88
|
-
*/
|
89
|
-
'
|
90
|
-
assert !@checker.has_doc_comment?(js)
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_check_import_js_scope
|
94
|
-
#not implements
|
95
|
-
end
|
96
|
-
|
97
|
-
def test_check_import_js_exist_and_min
|
98
|
-
# not implements
|
99
|
-
end
|
100
|
-
|
101
|
-
def fixture_01
|
102
|
-
<<END
|
103
|
-
(function(){
|
104
|
-
ImportJavscript = {
|
105
|
-
url:function(url){
|
106
|
-
document.write('<script type="text/javascript" src="'+url+'"></scr'+'ipt>');
|
107
|
-
}
|
108
|
-
};
|
109
|
-
})();
|
110
|
-
|
111
|
-
/**
|
112
|
-
* 打点依赖库
|
113
|
-
*/
|
114
|
-
ImportJavscript.url('http://style.china.alibaba.com/js/common/aliclick.js');
|
115
|
-
ImportJavscript.url(http://style.china.alibaba.com/js/detail/xpclick.js);
|
116
|
-
|
117
|
-
/**
|
118
|
-
* 旺铺基础JS
|
119
|
-
*/
|
120
|
-
ImportJavscript.url("http://style.china.alibaba.com/js/lib/fdev-v4/widget/util/debug-min.js"); ImportJavscript.url("http://style.china.alibaba.com/js/lib/fdev-v4/widget/web/alitalk-min.js");
|
121
|
-
ImportJavscript.url( 'http://style.china.alibaba.com/js/lib/fdev-v4/widget/web/sweet-min.js' ) ;
|
122
|
-
ImportJavscript.url('http://style.china.alibaba.com/js/lib/fdev-v4/widget/web/sweet-min.js')
|
123
|
-
END
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require_relative '../helper'
|
4
|
-
|
5
|
-
module XRayTest
|
6
|
-
|
7
|
-
module Rule
|
8
|
-
|
9
|
-
class DSLBasicTest < Test::Unit::TestCase
|
10
|
-
|
11
|
-
include ::XRay::Rule
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@rule = Proc.new do |file|
|
15
|
-
@called = true
|
16
|
-
["it's just a test", :warn]
|
17
|
-
end
|
18
|
-
@called = false
|
19
|
-
clear_all_rules
|
20
|
-
common
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_add_file_checker
|
24
|
-
check_file &@rule
|
25
|
-
assert_contains file_rules, "available in common rules"
|
26
|
-
assert_contains css_rules, "common rules available in css rules too"
|
27
|
-
assert_contains css_file_rules, "common rules available in css file rules too"
|
28
|
-
assert_not_contains only_css_file_rules, "not available in css rules only"
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_add_css_file_checker
|
32
|
-
css {
|
33
|
-
check_file &@rule
|
34
|
-
}
|
35
|
-
assert_not_contains file_rules, "not available in common rules"
|
36
|
-
assert_contains css_file_rules, "available in css rules"
|
37
|
-
assert_contains only_css_file_rules, "available in css only rules"
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_check
|
41
|
-
check_file &@rule
|
42
|
-
assert_equal check_file("test"), [["it's just a test", :warn]]
|
43
|
-
assert @called
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_named_checker
|
47
|
-
msg = ['we suggest use "-" instead', :info]
|
48
|
-
html {
|
49
|
-
check_file_with_underline do |file|
|
50
|
-
msg if file =~ /_/
|
51
|
-
end
|
52
|
-
}
|
53
|
-
|
54
|
-
results = check_file_with_underline 'a_b.html'
|
55
|
-
assert_equal msg, results
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_normal_plus_named_checker
|
59
|
-
case_warn = ['must use downcase filename', :error]
|
60
|
-
check_file { |file|
|
61
|
-
case_warn if file =~ /[A-Z]/
|
62
|
-
}
|
63
|
-
|
64
|
-
msg = ['we suggest use "-" instead', :info]
|
65
|
-
html {
|
66
|
-
check_file_with_underline do |file|
|
67
|
-
msg if file =~ /_/
|
68
|
-
end
|
69
|
-
}
|
70
|
-
|
71
|
-
results = check_html_file 'a_B.html'
|
72
|
-
assert_equal [case_warn, msg], results
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
def assert_contains( rules, *msg )
|
77
|
-
assert has_rule?(rules), *msg
|
78
|
-
end
|
79
|
-
|
80
|
-
def assert_not_contains( rules, *msg)
|
81
|
-
assert !has_rule?(rules), *msg
|
82
|
-
end
|
83
|
-
|
84
|
-
def has_rule?( rules )
|
85
|
-
rules.any? {|r| r[:block] == @rule }
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require_relative '../helper'
|
4
|
-
|
5
|
-
module XRayTest
|
6
|
-
|
7
|
-
module Rule
|
8
|
-
|
9
|
-
class ImportingTest < Test::Unit::TestCase
|
10
|
-
|
11
|
-
include ::XRay::Rule
|
12
|
-
|
13
|
-
def setup
|
14
|
-
clear_all_rules
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_import_with_symbol
|
18
|
-
import :css
|
19
|
-
assert css_rules.size > 0
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_import_with_symbol_twice
|
23
|
-
assert_equal 0, css_rules.size
|
24
|
-
|
25
|
-
import :css
|
26
|
-
size = css_rules.size
|
27
|
-
assert size > 0
|
28
|
-
|
29
|
-
import :css
|
30
|
-
assert_equal size, css_rules.size
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_import_all_twice
|
34
|
-
assert_equal 0, css_rules.size
|
35
|
-
|
36
|
-
import_all
|
37
|
-
size = css_rules.size
|
38
|
-
assert size > 0
|
39
|
-
|
40
|
-
import_all
|
41
|
-
assert_equal size, css_rules.size
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|