moco 0.1.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 +7 -0
- data/LICENSE +20 -0
- data/README.txt +67 -0
- data/Rakefile +15 -0
- data/bin/moco +6 -0
- data/lib/moco/ansi_escape.rb +37 -0
- data/lib/moco/application.rb +109 -0
- data/lib/moco/browser.rb +64 -0
- data/lib/moco/browser_error.rb +105 -0
- data/lib/moco/compile_error.rb +66 -0
- data/lib/moco/compiler.rb +151 -0
- data/lib/moco/compiler_option.rb +60 -0
- data/lib/moco/compiler_register.rb +29 -0
- data/lib/moco/compilers/coffee_compiler.rb +70 -0
- data/lib/moco/compilers/haml_compiler.rb +21 -0
- data/lib/moco/compilers/less_compiler.rb +15 -0
- data/lib/moco/compilers/markdown_compiler.rb +139 -0
- data/lib/moco/compilers/sass_compiler.rb +25 -0
- data/lib/moco/file_util.rb +54 -0
- data/lib/moco/log.rb +108 -0
- data/lib/moco/monitor.rb +83 -0
- data/lib/moco/options.rb +336 -0
- data/lib/moco/source_map.rb +22 -0
- data/lib/moco/support/error/error.css +22 -0
- data/lib/moco/support/error/error.html +7 -0
- data/lib/moco/support/error/error.js +58 -0
- data/lib/moco/support/reload.scpt +0 -0
- data/lib/moco.rb +44 -0
- data/moco.gemspec +35 -0
- data/moco.rb +35 -0
- data/src/error/error.coffee +49 -0
- data/src/reload.applescript +135 -0
- data/test/ansi_escape_test.rb +52 -0
- data/test/application_test.rb +40 -0
- data/test/browser_error_test.rb +101 -0
- data/test/browser_test.rb +29 -0
- data/test/compile_error_test.rb +82 -0
- data/test/compiler_option_test.rb +121 -0
- data/test/compiler_register_test.rb +41 -0
- data/test/compiler_test.rb +243 -0
- data/test/compilers/coffee_compiler_test.rb +117 -0
- data/test/compilers/haml_compiler_test.rb +86 -0
- data/test/compilers/less_compiler_test.rb +72 -0
- data/test/compilers/markdown_compiler_test.rb +211 -0
- data/test/compilers/sass_compiler_test.rb +84 -0
- data/test/file_util_test.rb +37 -0
- data/test/fixtures/_color.scss +1 -0
- data/test/fixtures/color.less +1 -0
- data/test/fixtures/css_lib.rb +2 -0
- data/test/fixtures/html_lib.rb +2 -0
- data/test/fixtures/js_lib.rb +2 -0
- data/test/fixtures/layout.html +13 -0
- data/test/fixtures/moco.rb +8 -0
- data/test/fixtures/options_lib.rb +2 -0
- data/test/fixtures/source.txt +1 -0
- data/test/monitor_test.rb +68 -0
- data/test/options_test.rb +177 -0
- data/test/test_helper.rb +57 -0
- metadata +270 -0
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe MarkdownCompiler do
|
6
|
+
|
7
|
+
after { reset_options(MarkdownCompiler) }
|
8
|
+
|
9
|
+
let(:markdown) { '#Title' }
|
10
|
+
let(:compiler) { mock_compiler(MarkdownCompiler, markdown) }
|
11
|
+
let(:compiled_text) { compiler.compiled_text.strip }
|
12
|
+
|
13
|
+
it 'is registered for md and markdown files' do
|
14
|
+
assert_equal MarkdownCompiler, MoCo.compiler_for('md')
|
15
|
+
assert_equal MarkdownCompiler, MoCo.compiler_for('markdown')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'is a Html compiler' do
|
19
|
+
assert MarkdownCompiler < HtmlCompiler
|
20
|
+
assert_equal 'html', MarkdownCompiler.compiled_extension
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'compiles markdown into html' do
|
24
|
+
assert_equal '<h1>Title</h1>', compiled_text
|
25
|
+
end
|
26
|
+
|
27
|
+
specify 'the options are used to specify markdown extensions' do
|
28
|
+
MarkdownCompiler.set_option(:space_after_headers)
|
29
|
+
assert_equal '<p>#Title</p>', compiled_text
|
30
|
+
end
|
31
|
+
|
32
|
+
specify 'the options are passed on to the html renderer' do
|
33
|
+
MarkdownCompiler.set_option(:with_toc_data)
|
34
|
+
assert_equal '<h1 id="toc_0">Title</h1>', compiled_text
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'the :smarty option' do
|
38
|
+
|
39
|
+
before { MarkdownCompiler.set_option(:smarty) }
|
40
|
+
|
41
|
+
let(:markdown) { '# ...' }
|
42
|
+
|
43
|
+
it 'performs SmartyPants substitutions' do
|
44
|
+
assert_equal '<h1>…</h1>', compiled_text
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'works with the Pygments renderer' do
|
48
|
+
MarkdownCompiler.set_option(:pygments)
|
49
|
+
assert_equal '<h1>…</h1>', compiled_text
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'works with the table of contents renderer' do
|
53
|
+
MarkdownCompiler.set_option(:toc)
|
54
|
+
assert_match '<a href="#toc_0">…</a>', compiled_text
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'the :toc option' do
|
60
|
+
|
61
|
+
before { MarkdownCompiler.set_option(:toc) }
|
62
|
+
|
63
|
+
it 'produces a table of contents' do
|
64
|
+
assert_match '<a href="#toc_0">Title</a>', compiled_text
|
65
|
+
assert_match '<h1 id="toc_0">Title</h1>', compiled_text
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'the :layout option' do
|
71
|
+
|
72
|
+
before { MarkdownCompiler.set_option(:layout, layout_file) }
|
73
|
+
|
74
|
+
let(:layout_file) { fixtures_path('layout.html') }
|
75
|
+
let(:layout) { File.read(layout_file) }
|
76
|
+
|
77
|
+
it 'replaces {{BODY}} with the rendered markdown' do
|
78
|
+
assert_match '<article>{{BODY}}</article>', layout
|
79
|
+
assert_match "<article><h1>Title</h1>\n</article>", compiled_text
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '{{TOC}}' do
|
83
|
+
|
84
|
+
before { MarkdownCompiler.set_option(:toc) }
|
85
|
+
|
86
|
+
it 'replaces {{TOC}} with the table of contents' do
|
87
|
+
assert_match '<nav>{{TOC}}</nav>', layout
|
88
|
+
assert_match "<nav><ul>\n<li>\n<a href", compiled_text
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'removes {{TOC}} if there is no table of contents' do
|
92
|
+
MarkdownCompiler.set_option(:toc, false)
|
93
|
+
assert_match '<nav></nav>', compiled_text
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'adds the toc to the {{BODY}} if there is no {{TOC}} tag' do
|
97
|
+
layout_file = tmp_dir + '/layout.html'
|
98
|
+
FileUtil.write(layout_file, layout.sub('{{TOC}}', ''))
|
99
|
+
|
100
|
+
MarkdownCompiler.set_option(:layout, layout_file)
|
101
|
+
assert_match "<article><ul>\n<li>\n<a href=", compiled_text
|
102
|
+
assert_match "Title</h1>\n</article>", compiled_text
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '{{TITLE}}' do
|
108
|
+
|
109
|
+
it 'replaces {{TITLE}} with the first h1 element' do
|
110
|
+
assert_match '<title>{{TITLE}}</title>', layout
|
111
|
+
assert_match '<title>Title</title>', compiled_text
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'accepts an h1 element with attributes' do
|
115
|
+
MarkdownCompiler.set_option(:toc)
|
116
|
+
assert_match '<title>Title</title>', compiled_text
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'removes nested tags from the title' do
|
120
|
+
markdown = '# The [](/index.html) Title'
|
121
|
+
compiler = mock_compiler(MarkdownCompiler, markdown)
|
122
|
+
assert_match '<title>The Title</title>', compiler.compiled_text
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'replaces {{TITLE}} with the filename if there are no h1 elements' do
|
126
|
+
compiler = mock_compiler(MarkdownCompiler, '## h2')
|
127
|
+
assert_match '<title>mock.md</title>', compiler.compiled_text
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'replaces {{FILE}} with the filename' do
|
133
|
+
assert_match '<span>{{FILE}}</span>', layout
|
134
|
+
assert_match '<span>mock.md</span>', compiled_text
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'the :pygments option' do
|
140
|
+
|
141
|
+
before { MarkdownCompiler.set_option(:pygments) }
|
142
|
+
|
143
|
+
def code_block(statement, language)
|
144
|
+
code_block = "```#{language}\n#{statement}\n```"
|
145
|
+
mock_compiler(MarkdownCompiler, code_block).compiled_text.strip
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'adds syntax highlighting hooks to fenced code blocks' do
|
149
|
+
expected = '<div class="highlight"><pre><span class="nb">puts</span>'
|
150
|
+
assert_match expected, code_block('puts', 'RUBY')
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'ignores code blocks with no language specified' do
|
154
|
+
expected = "<pre><code>puts\n</code></pre>"
|
155
|
+
assert_equal expected, code_block('puts', nil)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'adds a class for unknown languages' do
|
159
|
+
expected = "<pre><code class=\"dummy\">puts\n</code></pre>"
|
160
|
+
assert_equal expected, code_block('puts', 'dummy')
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'escapes the html' do
|
164
|
+
expected = '"'<&>'
|
165
|
+
assert_match expected, code_block(%("'<&>'"), 'ruby')
|
166
|
+
assert_match expected, code_block(%("'<&>'"), nil)
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'the :pygments options are passed on to Pygments' do
|
170
|
+
|
171
|
+
let(:markdown) { "```ruby\nputs\nputs\nputs\nputs\n\n```" }
|
172
|
+
|
173
|
+
it 'accepts a Hash' do
|
174
|
+
MarkdownCompiler.set_option(:pygments, :linenos => 'inline')
|
175
|
+
assert_equal 'inline', MarkdownCompiler.options[:pygments][:linenos]
|
176
|
+
assert_match '<span class="lineno">1</span>', compiled_text
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'accepts an Array' do
|
180
|
+
MarkdownCompiler.set_option(:pygments, [:hl_lines, 2, 3])
|
181
|
+
assert_equal [2, 3], MarkdownCompiler.options[:pygments][:hl_lines]
|
182
|
+
compiled_text.split(/\n/).each_with_index do |line, index|
|
183
|
+
if [2, 3].include?(index + 1)
|
184
|
+
assert_match '<span class="hll">', line
|
185
|
+
else
|
186
|
+
refute_match '<span class="hll">', line
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'can set an option to false' do
|
192
|
+
MarkdownCompiler.set_option(:pygments, ['stripnl', false])
|
193
|
+
assert_equal false, MarkdownCompiler.options[:pygments]['stripnl']
|
194
|
+
assert_match "\n\n</pre></div>", compiled_text
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'can be repeated' do
|
198
|
+
MarkdownCompiler.set_option(:pygments, 'noclasses')
|
199
|
+
MarkdownCompiler.set_option(:pygments, ['style', 'vim'])
|
200
|
+
assert_equal true, MarkdownCompiler.options[:pygments]['noclasses']
|
201
|
+
assert_equal 'vim', MarkdownCompiler.options[:pygments]['style']
|
202
|
+
assert_match '<span style="color: #cd00cd">puts', compiled_text
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
end if run_compiler_tests?(MarkdownCompiler)
|
210
|
+
|
211
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe SassCompiler do
|
6
|
+
|
7
|
+
it 'is registered for sass and scss files' do
|
8
|
+
assert_equal SassCompiler, MoCo.compiler_for('sass')
|
9
|
+
assert_equal SassCompiler, MoCo.compiler_for('scss')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'is a CSS compiler' do
|
13
|
+
assert SassCompiler < CssCompiler
|
14
|
+
assert_equal 'css', SassCompiler.compiled_extension
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'selects the correct syntax' do
|
18
|
+
assert_equal :sass, SassCompiler.new('style.sass').options[:syntax]
|
19
|
+
assert_equal :scss, SassCompiler.new('style.scss').options[:syntax]
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'compile' do
|
23
|
+
|
24
|
+
css = <<-EOF
|
25
|
+
.sass {
|
26
|
+
color: #ce4dd6; }
|
27
|
+
EOF
|
28
|
+
|
29
|
+
sass = <<-EOF
|
30
|
+
$pink: #CE4DD6
|
31
|
+
.sass
|
32
|
+
color: $pink
|
33
|
+
EOF
|
34
|
+
|
35
|
+
scss = <<-EOF
|
36
|
+
$pink: #CE4DD6;
|
37
|
+
.sass { color: $pink; }
|
38
|
+
EOF
|
39
|
+
|
40
|
+
import = <<-EOF
|
41
|
+
@import 'color';
|
42
|
+
.sass { color: $pink; }
|
43
|
+
EOF
|
44
|
+
|
45
|
+
[css, sass, scss, import].each { |style| style.gsub!(/^ {8}/, '') }
|
46
|
+
|
47
|
+
it 'compiles sass into css' do
|
48
|
+
compiler = mock_compiler(SassCompiler, sass, 'style.sass')
|
49
|
+
assert_equal css, compiler.compiled_text
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'compiles scss into css' do
|
53
|
+
compiler = mock_compiler(SassCompiler, scss, 'style.scss')
|
54
|
+
assert_equal css, compiler.compiled_text
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'handles the @import directive' do
|
58
|
+
SassCompiler.set_option(:load_paths, [fixtures_path])
|
59
|
+
compiler = mock_compiler(SassCompiler, import, 'style.scss')
|
60
|
+
assert_equal css, compiler.compiled_text
|
61
|
+
reset_options(SassCompiler)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'compile error' do
|
67
|
+
|
68
|
+
let(:compiler) do
|
69
|
+
mock_compiler(SassCompiler, '.sass { color: $blue; }', 'style.scss')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'raises a CompileError' do
|
73
|
+
assert_raises(CompileError) { compiler.compile }
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'has a line number' do
|
77
|
+
assert_equal 1, (compiler.compile rescue $!).line
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end if run_compiler_tests?(SassCompiler)
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe FileUtil do
|
6
|
+
|
7
|
+
describe 'normalized extension' do
|
8
|
+
|
9
|
+
specify do
|
10
|
+
assert_equal 'less', FileUtil.normalized_extension('less')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'removes the period' do
|
14
|
+
assert_equal 'less', FileUtil.normalized_extension('.less')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'accepts a symbol' do
|
18
|
+
assert_equal 'less', FileUtil.normalized_extension(:less)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'accepts a filename' do
|
22
|
+
assert_equal 'sass', FileUtil.normalized_extension('/dir/file.sass')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'works with spaces' do
|
26
|
+
assert_equal 'sass', FileUtil.normalized_extension(' file with spaces .sass ')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'works with nested extensions' do
|
30
|
+
assert_equal 'sass', FileUtil.normalized_extension('file.css.sass')
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
$pink: #CE4DD6;
|
@@ -0,0 +1 @@
|
|
1
|
+
@blue: #D9EEF2;
|
@@ -0,0 +1 @@
|
|
1
|
+
The source text
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe Monitor do
|
6
|
+
|
7
|
+
before { skip unless __FILE__ == $0 }
|
8
|
+
|
9
|
+
def tmp
|
10
|
+
Pathname.new(tmp_dir).realpath().to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def updated(&block)
|
14
|
+
updated = []
|
15
|
+
thread = Thread.new do
|
16
|
+
monitor.monitor { |file| updated << file }
|
17
|
+
end
|
18
|
+
sleep 0.05
|
19
|
+
yield
|
20
|
+
sleep 0.5
|
21
|
+
thread.kill
|
22
|
+
updated.sort
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:dirs) { [tmp, tmp].sort }
|
26
|
+
let(:files) { %W[#{dirs[0]}/file.haml #{dirs[1]}/nested/dir/file.sass] }
|
27
|
+
let(:txt_file) { "#{dirs[1]}/file.txt" }
|
28
|
+
|
29
|
+
describe 'monitor directories' do
|
30
|
+
|
31
|
+
let(:monitor) { Monitor.new([], dirs, [:sass, :haml]) }
|
32
|
+
|
33
|
+
it 'captures new files' do
|
34
|
+
assert_equal files, updated { touch(files) }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'captures file updates' do
|
38
|
+
touch(files, :mtime => 0)
|
39
|
+
assert_equal files, updated { touch(files) }
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'ignores files with other extensions' do
|
43
|
+
assert_empty updated { touch(txt_file) }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'lists all the files currently being monitored' do
|
47
|
+
Dir.mkdir("#{dirs[0]}/dir.sass")
|
48
|
+
assert_empty monitor.files
|
49
|
+
touch(files + [txt_file])
|
50
|
+
assert_equal files, monitor.files.sort
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'monitor files' do
|
56
|
+
|
57
|
+
let(:monitor) { Monitor.new(files, [], []) }
|
58
|
+
|
59
|
+
it 'captures file updates' do
|
60
|
+
touch(files, :mtime => 0)
|
61
|
+
assert_equal files, updated { touch(files + [txt_file]) }
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe Options do
|
6
|
+
|
7
|
+
class MockOptions < Options
|
8
|
+
define_method(:load_moco_files) {}
|
9
|
+
define_method(:validate_files) {}
|
10
|
+
define_method(:display_help) {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse(args = '')
|
14
|
+
MockOptions.parse(args.shellsplit)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'parse command line options' do
|
18
|
+
|
19
|
+
it 'sets the default options' do
|
20
|
+
assert_equal Options.new.default_options, parse
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'sets boolean options' do
|
24
|
+
assert_equal true, parse('--force')[:force]
|
25
|
+
assert_equal false, parse('--no-force')[:force]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'sets array options' do
|
29
|
+
assert_equal %w[Chrome], parse('-b Chrome')[:browsers]
|
30
|
+
assert_equal %w[Chrome], parse('-b Chrome,Chrome')[:browsers]
|
31
|
+
assert_equal %w[Chrome Opera], parse('-b Chrome,Opera')[:browsers]
|
32
|
+
assert_equal %w[Chrome Opera], parse('-b Chrome -b Opera')[:browsers]
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'the compile option' do
|
36
|
+
|
37
|
+
it 'sets the compile flag' do
|
38
|
+
assert_equal true, parse('-c sass')[:compile]
|
39
|
+
assert_equal true, parse('--compile')[:compile]
|
40
|
+
assert_equal false, parse('--no-compile')[:compile]
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'sets the compile extensions' do
|
44
|
+
assert_equal ['sass'], parse('--compile .sass')[:compile_exts]
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raises an OptionError if an extension is unregistered' do
|
48
|
+
assert_raises(OptionError) { parse('-c cofe') }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'setting compiler options' do
|
54
|
+
|
55
|
+
it 'sets the options' do
|
56
|
+
parse('--option haml:ugly -o haml:preserve:pre:code')
|
57
|
+
assert_equal true, HamlCompiler.options[:ugly]
|
58
|
+
assert_equal %w[pre code], HamlCompiler.options[:preserve]
|
59
|
+
reset_options(HamlCompiler)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'raises an OptionError if the option key is missing' do
|
63
|
+
assert_raises(OptionError) { parse('-o haml') }
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises an OptionError if the extension is unregistered' do
|
67
|
+
assert_raises(OptionError) { parse('-o aml:ugly') }
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'sets the source map flag' do
|
73
|
+
parse('--source-map')
|
74
|
+
assert_equal true, CoffeeCompiler.options[:sourceMap]
|
75
|
+
reset_options(CoffeeCompiler)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'requires the library' do
|
79
|
+
refute defined? OptionsLib
|
80
|
+
parse('--require ' + fixtures_path('options_lib'))
|
81
|
+
assert defined? OptionsLib
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'parse command line path arguments' do
|
87
|
+
|
88
|
+
before { MockOptions.send(:define_method, :validate_files) { super() } }
|
89
|
+
after { MockOptions.send(:define_method, :validate_files) {} }
|
90
|
+
|
91
|
+
let(:dir) { fixtures_path }
|
92
|
+
let(:file) { fixtures_path('moco.rb') }
|
93
|
+
|
94
|
+
it 'sets the source files and directories' do
|
95
|
+
assert_equal [file], parse("#{dir} #{file}")[:source_files]
|
96
|
+
assert_equal [dir], parse("#{dir} #{file}")[:source_dirs]
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'sets the compiled files and directories' do
|
100
|
+
assert_equal '/file', parse("#{file}:/file")[:compiled_files][file]
|
101
|
+
assert_equal '/dir', parse("#{dir}:/dir")[:compiled_dirs][dir]
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'raises an OptionError if no path is provided' do
|
105
|
+
assert_raises(OptionError) { parse }
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'raises an OptionError if the path does not exists' do
|
109
|
+
assert_raises(OptionError) { parse('no_such_file') }
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'raises an OptionError if the compiled file is a directory' do
|
113
|
+
assert_raises(OptionError) { parse("#{file}:#{dir}") }
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'raises an OptionError if the compiled directory is a file' do
|
117
|
+
assert_raises(OptionError) { parse("#{dir}:#{file}") }
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe 'the moco file' do
|
123
|
+
|
124
|
+
before do
|
125
|
+
moco_file = fixtures_path('moco.rb')
|
126
|
+
MockOptions.send(:define_method, :load_moco_files) { load moco_file }
|
127
|
+
end
|
128
|
+
|
129
|
+
after do
|
130
|
+
MockOptions.send(:define_method, :load_moco_files) {}
|
131
|
+
Options.instance_variable_set(:@args, nil)
|
132
|
+
reset_register
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'can register new compilers' do
|
136
|
+
parse
|
137
|
+
assert_equal TextCompiler, MoCo.compiler_for('txt')
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'sets compiler options' do
|
141
|
+
parse
|
142
|
+
assert_equal ['pre'], TextCompiler.options[:preserve]
|
143
|
+
assert_equal :html5, TextCompiler.options[:format]
|
144
|
+
assert_equal true, TextCompiler.options[:ugly]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'sets general options' do
|
148
|
+
assert_equal false, parse[:reload]
|
149
|
+
end
|
150
|
+
|
151
|
+
specify 'the command line options have precedence' do
|
152
|
+
assert_equal true, parse('-r -o txt:format:xml')[:reload]
|
153
|
+
assert_equal 'xml', TextCompiler.options[:format]
|
154
|
+
end
|
155
|
+
|
156
|
+
specify 'MoCo.args expects a shell escaped string' do
|
157
|
+
MoCo.args(%(-o txt:foo:'The "Quote"'))
|
158
|
+
MoCo.args(%(-o txt:bar:The\\ \\"Quote\\"))
|
159
|
+
parse
|
160
|
+
assert_equal 'The "Quote"', TextCompiler.options[:foo]
|
161
|
+
assert_equal 'The "Quote"', TextCompiler.options[:bar]
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'finds the moco files in the current working directory' do
|
165
|
+
current_dir = Dir.pwd
|
166
|
+
Dir.chdir(tmp_dir)
|
167
|
+
touch([Dir.pwd + '/moco.rb', Dir.pwd + '/.moco'])
|
168
|
+
assert_includes Options.moco_files, Dir.pwd + '/moco.rb'
|
169
|
+
assert_includes Options.moco_files, Dir.pwd + '/.moco'
|
170
|
+
Dir.chdir(current_dir)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path('../../lib/moco', __FILE__)
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
COMPILERS = MoCo.compilers
|
6
|
+
TMP_DIR = Dir.mktmpdir('MoCo')
|
7
|
+
|
8
|
+
MiniTest::Unit.after_tests do
|
9
|
+
FileUtils.rm_rf(TMP_DIR)
|
10
|
+
end
|
11
|
+
|
12
|
+
def tmp_dir
|
13
|
+
Dir.mktmpdir(nil, TMP_DIR)
|
14
|
+
end
|
15
|
+
|
16
|
+
def fixtures_path(file = nil)
|
17
|
+
fixtures_dir = File.expand_path('../fixtures', __FILE__)
|
18
|
+
file ? File.join(fixtures_dir, file) : fixtures_dir
|
19
|
+
end
|
20
|
+
|
21
|
+
def touch(files, options = {})
|
22
|
+
Array(files).each do |file|
|
23
|
+
FileUtils.makedirs(File.dirname(file))
|
24
|
+
FileUtils.touch(file, options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset_register
|
29
|
+
register = MoCo::CompilerRegister.instance
|
30
|
+
register.instance_variable_set(:@compilers, COMPILERS.dup)
|
31
|
+
end
|
32
|
+
|
33
|
+
def reset_options(klass)
|
34
|
+
klass.instance_variable_set(:@options, {})
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_compiler_tests?(klass)
|
38
|
+
klass.new('')
|
39
|
+
rescue LoadError => e
|
40
|
+
warn "Skipping #{klass} tests (#{e.message.split("\n").first})"
|
41
|
+
end
|
42
|
+
|
43
|
+
def mock_compiler(klass, source_text, source_file = nil, compiled_file = nil)
|
44
|
+
source_file ||= "mock.#{MoCo.compilers.invert[klass]}"
|
45
|
+
mock = klass.new(source_file, compiled_file)
|
46
|
+
mock.define_singleton_method(:source_text) { source_text }
|
47
|
+
mock.define_singleton_method(:write_file) { |filename, text| }
|
48
|
+
mock
|
49
|
+
end
|
50
|
+
|
51
|
+
unless respond_to?(:define_singleton_method)
|
52
|
+
Object.send(:define_method, :define_singleton_method) do |name, &block|
|
53
|
+
singleton = class << self; self end
|
54
|
+
singleton.send(:define_method, name, &block)
|
55
|
+
end
|
56
|
+
Object.send(:public, :define_singleton_method)
|
57
|
+
end
|