jslint-johnson 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/jslint-johnson +24 -0
- data/test/helper.rb +18 -0
- data/test/suite.rb +5 -0
- data/test/test_cli.rb +44 -0
- data/test/test_formatter.rb +50 -0
- data/test/test_lint_error.rb +32 -0
- data/test/test_runner.rb +141 -0
- data/test/test_task.rb +124 -0
- metadata +127 -0
data/bin/jslint-johnson
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require File.expand_path("../lib/jslint-johnson", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
if ARGV.empty?
|
6
|
+
puts "usage: #{File.basename(__FILE__)} FILES"
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
formatter = JSLintJohnson::Formatter.new(STDOUT)
|
11
|
+
|
12
|
+
# get a list of all failed files, printing . or * along the way depending on the result
|
13
|
+
lint_result = JSLintJohnson::Runner.new(ARGV).run do |file, errors|
|
14
|
+
formatter.tick(errors)
|
15
|
+
end
|
16
|
+
|
17
|
+
# put a separator line in between the ticks and any summary
|
18
|
+
print "\n"
|
19
|
+
|
20
|
+
# print a summary of failed files
|
21
|
+
formatter.summary(ARGV, lint_result)
|
22
|
+
|
23
|
+
# exit with the status code of the number of errors
|
24
|
+
exit(lint_result.values.flatten.length)
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require 'test/unit'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
# require the library code
|
6
|
+
require File.expand_path("../lib/jslint-johnson", File.dirname(__FILE__))
|
7
|
+
|
8
|
+
def erb_fixture(basename)
|
9
|
+
::ERB.new(File.read(erb_filename(basename))).result
|
10
|
+
end
|
11
|
+
|
12
|
+
def erb_filename(basename)
|
13
|
+
File.expand_path("fixtures/#{basename}.txt.erb", File.dirname(__FILE__))
|
14
|
+
end
|
15
|
+
|
16
|
+
def js_filename(basename)
|
17
|
+
File.expand_path("fixtures/#{basename}.js", File.dirname(__FILE__))
|
18
|
+
end
|
data/test/suite.rb
ADDED
data/test/test_cli.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
class TestCli < Test::Unit::TestCase
|
5
|
+
Executable = File.expand_path("../bin/jslint-johnson", File.dirname(__FILE__))
|
6
|
+
|
7
|
+
def test_executable_exists
|
8
|
+
assert File.exist?(Executable)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_empty_args
|
12
|
+
result = `#{Executable}`
|
13
|
+
|
14
|
+
assert_equal "usage: jslint-johnson FILES\n", result
|
15
|
+
assert_equal false, $?.success?
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_valid
|
19
|
+
result = %x{#{Executable} "#{js_filename "valid"}"}
|
20
|
+
|
21
|
+
assert $?.success?
|
22
|
+
assert_equal erb_fixture("cli-valid-expected-output"), result
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_invalid
|
26
|
+
result = %x{#{Executable} "#{js_filename "invalid"}"}
|
27
|
+
|
28
|
+
assert_equal false, $?.success?
|
29
|
+
assert_equal erb_fixture("cli-invalid-expected-output"), result
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_suite
|
33
|
+
defined_globals = js_filename("defined-globals")
|
34
|
+
defined_options = js_filename("defined-options")
|
35
|
+
invalid = js_filename("invalid")
|
36
|
+
valid = js_filename("valid")
|
37
|
+
|
38
|
+
result = %x{#{Executable} "#{defined_globals}" "#{defined_options}" "#{invalid}" "#{valid}"}
|
39
|
+
|
40
|
+
assert_equal false, $?.success?
|
41
|
+
assert_equal erb_fixture("cli-suite-expected-output"), result
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
class TestFormatter < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@output = String.new
|
8
|
+
@output_stream = StringIO.new(@output, "w+")
|
9
|
+
|
10
|
+
@formatter = JSLintJohnson::Formatter.new(@output_stream)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_create
|
14
|
+
assert_equal @output_stream.object_id, @formatter.output_stream.object_id
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_tick
|
18
|
+
assert_equal "", @output
|
19
|
+
|
20
|
+
@formatter.tick([])
|
21
|
+
|
22
|
+
assert_equal ".", @output
|
23
|
+
|
24
|
+
@formatter.tick(["foo"])
|
25
|
+
|
26
|
+
assert_equal ".*", @output
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_summary_with_no_errors
|
30
|
+
@formatter.summary(%w(foo bar), {})
|
31
|
+
|
32
|
+
assert_equal erb_fixture("formatter-summary-noerrors"), @output
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_summary_with_errors
|
36
|
+
error_1 = JSLintJohnson::LintError.new("line" => 42, "character" => 10, "reason" => "because i can")
|
37
|
+
error_2 = JSLintJohnson::LintError.new("line" => 43, "character" => 3, "reason" => "a proof is not a proof")
|
38
|
+
error_3 = JSLintJohnson::LintError.new("line" => 139, "character" => 12, "reason" => "undefined global 'foo'")
|
39
|
+
|
40
|
+
result = {
|
41
|
+
"foo" => [error_1, error_2],
|
42
|
+
"bar" => [error_3]
|
43
|
+
}
|
44
|
+
|
45
|
+
@formatter.summary(%w(foo bar baz one two three), result)
|
46
|
+
|
47
|
+
assert_equal erb_fixture("formatter-summary-errors"), @output
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class TestLintError < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@object = {
|
7
|
+
"line" => 42,
|
8
|
+
"character" => 10,
|
9
|
+
"reason" => "because i can",
|
10
|
+
"evidence" => "I don't know, a proof is a proof. What kind of a proof? It's a proof. A proof is a proof, and when you have a good proof, it's because it's proven."
|
11
|
+
}
|
12
|
+
|
13
|
+
@error = JSLintJohnson::LintError.new(@object)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_line_number
|
17
|
+
assert_equal @error.line_number, 42
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_character
|
21
|
+
assert_equal @error.character, 10
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_reason
|
25
|
+
assert_equal @error.reason, "because i can"
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_evidence
|
29
|
+
assert_equal @error.evidence, "I don't know, a proof is a proof. What kind of a proof? It's a proof. A proof is a proof, and when you have a good proof, it's because it's proven."
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/test/test_runner.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class TestRunner < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@runner = JSLintJohnson::Runner.new(%w(foo bar))
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_lint_library_filename
|
10
|
+
assert File.exist? JSLintJohnson::Runner::JSLintLibraryFilename
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_file_list
|
14
|
+
assert_equal @runner.file_list, %w(foo bar)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_constructor_enumerable_wrapping
|
18
|
+
@runner = JSLintJohnson::Runner.new("foo")
|
19
|
+
|
20
|
+
assert_equal @runner.file_list, %w(foo)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_file_not_found
|
24
|
+
assert_raise RuntimeError do
|
25
|
+
@runner.run
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_file_found
|
30
|
+
filename = js_filename "valid"
|
31
|
+
|
32
|
+
assert_nothing_raised do
|
33
|
+
JSLintJohnson::Runner.new(filename).run
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_runtime
|
38
|
+
assert @runner.runtime.is_a?(Johnson::Runtime)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_runtime_caching
|
42
|
+
first = @runner.runtime
|
43
|
+
assert_equal @runner.runtime.object_id, first.object_id
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_jslint_function_proxy
|
47
|
+
assert_not_nil @runner.jslint_function
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_jslint_result
|
51
|
+
assert @runner.jslint_result.is_a?(Array)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_jslint_default_options
|
55
|
+
assert @runner.jslint_options.keys.any?
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_jslint_returns_array_of_errors
|
59
|
+
result = @runner.jslint("if(true) alert('foo');")
|
60
|
+
|
61
|
+
assert result.is_a?(Array)
|
62
|
+
assert result.length > 0
|
63
|
+
assert result.all? {|error| error.is_a?(JSLintJohnson::LintError) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_run
|
67
|
+
filename = js_filename("invalid")
|
68
|
+
|
69
|
+
result = JSLintJohnson::Runner.new(filename).run
|
70
|
+
|
71
|
+
assert result.is_a?(Hash)
|
72
|
+
assert result.keys.include?(filename)
|
73
|
+
assert result[filename].is_a?(Array)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_valid_run
|
77
|
+
filename = js_filename("valid")
|
78
|
+
|
79
|
+
result = JSLintJohnson::Runner.new(filename).run
|
80
|
+
|
81
|
+
errors = result[filename]
|
82
|
+
|
83
|
+
assert errors.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_invalid_run
|
87
|
+
filename = js_filename("invalid")
|
88
|
+
|
89
|
+
result = JSLintJohnson::Runner.new(filename).run
|
90
|
+
|
91
|
+
errors = result[filename]
|
92
|
+
|
93
|
+
assert errors.any?
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_defined_globals
|
97
|
+
filename = js_filename("defined-globals")
|
98
|
+
|
99
|
+
result = JSLintJohnson::Runner.new(filename).run
|
100
|
+
|
101
|
+
errors = result[filename]
|
102
|
+
|
103
|
+
assert errors.nil?
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_defined_options
|
107
|
+
filename = js_filename("defined-options")
|
108
|
+
|
109
|
+
result = JSLintJohnson::Runner.new(filename).run
|
110
|
+
|
111
|
+
errors = result[filename]
|
112
|
+
|
113
|
+
assert errors.nil?
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_block
|
117
|
+
filename = js_filename("valid")
|
118
|
+
|
119
|
+
count = 0
|
120
|
+
|
121
|
+
JSLintJohnson::Runner.new(filename).run do |file, errors|
|
122
|
+
count += 1
|
123
|
+
|
124
|
+
if count == 1
|
125
|
+
assert_equal file, filename
|
126
|
+
assert_equal errors, []
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
assert_equal count, 1
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_rejects_successful
|
134
|
+
valid_file = js_filename("valid")
|
135
|
+
invalid_file = js_filename("invalid")
|
136
|
+
|
137
|
+
result = JSLintJohnson::Runner.new([valid_file, invalid_file]).run
|
138
|
+
|
139
|
+
assert_equal result.keys.length, 1
|
140
|
+
end
|
141
|
+
end
|
data/test/test_task.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
require 'rake'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
class TestTask < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
# completely reset the rake application to ensure everything is clean
|
9
|
+
Rake.application = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_creation
|
13
|
+
initial_length = Rake.application.tasks.length
|
14
|
+
|
15
|
+
JSLintJohnson::RakeTask.new
|
16
|
+
|
17
|
+
# the number of tasks should have increased by 1
|
18
|
+
assert_equal initial_length + 1, Rake.application.tasks.length
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_default_name
|
22
|
+
JSLintJohnson::RakeTask.new
|
23
|
+
|
24
|
+
task = Rake.application.lookup("lint")
|
25
|
+
|
26
|
+
assert_equal "lint", task.name
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_default_description
|
30
|
+
JSLintJohnson::RakeTask.new
|
31
|
+
|
32
|
+
task = Rake.application.lookup("lint")
|
33
|
+
|
34
|
+
assert_equal "Runs the JSLint Test Suite", task.comment
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_default_include_pattern
|
38
|
+
task = JSLintJohnson::RakeTask.new
|
39
|
+
|
40
|
+
assert_equal "app/javascripts/**/*.js", task.include_pattern
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_default_exclude_pattern
|
44
|
+
task = JSLintJohnson::RakeTask.new
|
45
|
+
|
46
|
+
assert_equal "", task.exclude_pattern
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_default_output_stream
|
50
|
+
task = JSLintJohnson::RakeTask.new
|
51
|
+
|
52
|
+
assert_equal STDOUT, task.output_stream
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_creation_block
|
56
|
+
tempfile = Tempfile.new("foo")
|
57
|
+
|
58
|
+
task = JSLintJohnson::RakeTask.new do |task|
|
59
|
+
task.name = "foo"
|
60
|
+
task.description = "Points out the bad codezzzz"
|
61
|
+
task.include_pattern = "js/**/*.js"
|
62
|
+
task.exclude_pattern = "js/**/*.txt"
|
63
|
+
task.output_stream = tempfile
|
64
|
+
end
|
65
|
+
|
66
|
+
rake_task = Rake.application.lookup("foo")
|
67
|
+
|
68
|
+
assert_equal "foo", rake_task.name
|
69
|
+
assert_equal "Points out the bad codezzzz", rake_task.comment
|
70
|
+
assert_equal "js/**/*.js", task.include_pattern
|
71
|
+
assert_equal "js/**/*.txt", task.exclude_pattern
|
72
|
+
assert_equal tempfile.object_id, task.output_stream.object_id
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_files_to_run
|
76
|
+
task = JSLintJohnson::RakeTask.new do |task|
|
77
|
+
task.include_pattern = File.expand_path("fixtures/*", File.dirname(__FILE__))
|
78
|
+
task.exclude_pattern = File.expand_path("fixtures/*.erb", File.dirname(__FILE__))
|
79
|
+
end
|
80
|
+
|
81
|
+
expected_files = Dir.glob(File.expand_path("fixtures/*.js", File.dirname(__FILE__))).sort
|
82
|
+
|
83
|
+
assert_equal expected_files, task.files_to_run
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_valid_output
|
87
|
+
result = String.new
|
88
|
+
|
89
|
+
task = JSLintJohnson::RakeTask.new do |task|
|
90
|
+
task.include_pattern = File.expand_path("fixtures/valid.js", File.dirname(__FILE__))
|
91
|
+
task.output_stream = StringIO.new(result, "w+")
|
92
|
+
end
|
93
|
+
|
94
|
+
Rake.application.lookup("lint").invoke
|
95
|
+
|
96
|
+
assert_equal erb_fixture("cli-valid-expected-output"), result
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_invalid_output
|
100
|
+
result = String.new
|
101
|
+
|
102
|
+
task = JSLintJohnson::RakeTask.new do |task|
|
103
|
+
task.include_pattern = File.expand_path("fixtures/invalid.js", File.dirname(__FILE__))
|
104
|
+
task.output_stream = StringIO.new(result, "w+")
|
105
|
+
end
|
106
|
+
|
107
|
+
Rake.application.lookup("lint").invoke
|
108
|
+
|
109
|
+
assert_equal erb_fixture("cli-invalid-expected-output"), result
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_suite_output
|
113
|
+
result = String.new
|
114
|
+
|
115
|
+
task = JSLintJohnson::RakeTask.new do |task|
|
116
|
+
task.include_pattern = File.expand_path("fixtures/*.js", File.dirname(__FILE__))
|
117
|
+
task.output_stream = StringIO.new(result, "w+")
|
118
|
+
end
|
119
|
+
|
120
|
+
Rake.application.lookup("lint").invoke
|
121
|
+
|
122
|
+
assert_equal erb_fixture("cli-suite-expected-output"), result
|
123
|
+
end
|
124
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jslint-johnson
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- William Howard
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-28 00:00:00 +02:00
|
19
|
+
default_executable: jslint-johnson
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: johnson
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 31
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 0
|
34
|
+
version: 1.2.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 49
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 8
|
49
|
+
- 7
|
50
|
+
version: 0.8.7
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: johnson
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 31
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 2
|
65
|
+
- 0
|
66
|
+
version: 1.2.0
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
description: " - Ruby gem wrapper for a JSLint CLI.\n - Uses the Johnson library for performance.\n - Targeted for usage in CI environments.\n - Thoroughly tested.\n"
|
70
|
+
email: whoward.tke@gmail.com
|
71
|
+
executables:
|
72
|
+
- jslint-johnson
|
73
|
+
extensions: []
|
74
|
+
|
75
|
+
extra_rdoc_files: []
|
76
|
+
|
77
|
+
files:
|
78
|
+
- test/helper.rb
|
79
|
+
- test/suite.rb
|
80
|
+
- test/test_cli.rb
|
81
|
+
- test/test_formatter.rb
|
82
|
+
- test/test_lint_error.rb
|
83
|
+
- test/test_runner.rb
|
84
|
+
- test/test_task.rb
|
85
|
+
- bin/jslint-johnson
|
86
|
+
has_rdoc: true
|
87
|
+
homepage: http://github.com/whoward/jslint-johnson
|
88
|
+
licenses: []
|
89
|
+
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 3
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
version: "0"
|
113
|
+
requirements: []
|
114
|
+
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 1.6.1
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: JSLint CLI and rake tasks via johnson
|
120
|
+
test_files:
|
121
|
+
- test/helper.rb
|
122
|
+
- test/suite.rb
|
123
|
+
- test/test_cli.rb
|
124
|
+
- test/test_formatter.rb
|
125
|
+
- test/test_lint_error.rb
|
126
|
+
- test/test_runner.rb
|
127
|
+
- test/test_task.rb
|