nanoc 3.4.3 → 3.5.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/CONTRIBUTING.md +25 -0
  2. data/Gemfile +3 -1
  3. data/Gemfile.lock +22 -13
  4. data/NEWS.md +27 -0
  5. data/README.md +3 -1
  6. data/lib/nanoc.rb +2 -2
  7. data/lib/nanoc/base/compilation/compiler_dsl.rb +19 -0
  8. data/lib/nanoc/base/core_ext/array.rb +18 -8
  9. data/lib/nanoc/base/core_ext/hash.rb +18 -8
  10. data/lib/nanoc/base/core_ext/pathname.rb +2 -8
  11. data/lib/nanoc/base/plugin_registry.rb +57 -19
  12. data/lib/nanoc/base/result_data/item_rep.rb +3 -15
  13. data/lib/nanoc/base/source_data/item.rb +1 -1
  14. data/lib/nanoc/base/source_data/layout.rb +1 -1
  15. data/lib/nanoc/base/source_data/site.rb +15 -19
  16. data/lib/nanoc/cli.rb +28 -23
  17. data/lib/nanoc/cli/command_runner.rb +4 -0
  18. data/lib/nanoc/cli/commands/autocompile.rb +15 -6
  19. data/lib/nanoc/cli/commands/check.rb +47 -0
  20. data/lib/nanoc/cli/commands/compile.rb +271 -195
  21. data/lib/nanoc/cli/commands/create-site.rb +5 -5
  22. data/lib/nanoc/cli/commands/deploy.rb +16 -4
  23. data/lib/nanoc/cli/commands/prune.rb +3 -3
  24. data/lib/nanoc/cli/commands/show-data.rb +73 -58
  25. data/lib/nanoc/cli/commands/show-rules.rb +1 -1
  26. data/lib/nanoc/cli/commands/validate-css.rb +2 -3
  27. data/lib/nanoc/cli/commands/validate-html.rb +2 -3
  28. data/lib/nanoc/cli/commands/validate-links.rb +5 -11
  29. data/lib/nanoc/cli/commands/view.rb +1 -1
  30. data/lib/nanoc/cli/commands/watch.rb +38 -20
  31. data/lib/nanoc/cli/error_handler.rb +122 -122
  32. data/lib/nanoc/data_sources.rb +2 -0
  33. data/lib/nanoc/data_sources/filesystem_unified.rb +1 -1
  34. data/lib/nanoc/data_sources/filesystem_verbose.rb +1 -1
  35. data/lib/nanoc/data_sources/static.rb +60 -0
  36. data/lib/nanoc/extra.rb +2 -0
  37. data/lib/nanoc/extra/checking.rb +16 -0
  38. data/lib/nanoc/extra/checking/check.rb +33 -0
  39. data/lib/nanoc/extra/checking/checks.rb +19 -0
  40. data/lib/nanoc/extra/checking/checks/css.rb +23 -0
  41. data/lib/nanoc/extra/checking/checks/external_links.rb +149 -0
  42. data/lib/nanoc/extra/checking/checks/html.rb +24 -0
  43. data/lib/nanoc/extra/checking/checks/internal_links.rb +57 -0
  44. data/lib/nanoc/extra/checking/checks/stale.rb +23 -0
  45. data/lib/nanoc/extra/checking/dsl.rb +31 -0
  46. data/lib/nanoc/extra/checking/issue.rb +19 -0
  47. data/lib/nanoc/extra/checking/runner.rb +130 -0
  48. data/lib/nanoc/extra/link_collector.rb +57 -0
  49. data/lib/nanoc/extra/pruner.rb +1 -1
  50. data/lib/nanoc/extra/validators/links.rb +5 -262
  51. data/lib/nanoc/extra/validators/w3c.rb +8 -76
  52. data/lib/nanoc/filters/colorize_syntax.rb +1 -1
  53. data/lib/nanoc/filters/handlebars.rb +2 -2
  54. data/lib/nanoc/filters/less.rb +1 -1
  55. data/lib/nanoc/filters/redcarpet.rb +1 -1
  56. data/lib/nanoc/filters/rubypants.rb +1 -1
  57. data/lib/nanoc/filters/slim.rb +1 -1
  58. data/lib/nanoc/helpers/blogging.rb +163 -104
  59. data/lib/nanoc/helpers/xml_sitemap.rb +9 -3
  60. data/tasks/doc.rake +2 -1
  61. data/test/base/core_ext/array_spec.rb +4 -4
  62. data/test/base/core_ext/hash_spec.rb +7 -7
  63. data/test/base/core_ext/pathname_spec.rb +12 -2
  64. data/test/base/test_compiler_dsl.rb +24 -0
  65. data/test/base/test_item_rep.rb +58 -26
  66. data/test/cli/commands/test_watch.rb +0 -8
  67. data/test/data_sources/test_static.rb +66 -0
  68. data/test/extra/checking/checks/test_css.rb +40 -0
  69. data/test/extra/checking/checks/test_external_links.rb +76 -0
  70. data/test/extra/checking/checks/test_html.rb +40 -0
  71. data/test/extra/checking/checks/test_internal_links.rb +46 -0
  72. data/test/extra/checking/checks/test_stale.rb +49 -0
  73. data/test/extra/checking/test_check.rb +16 -0
  74. data/test/extra/checking/test_dsl.rb +20 -0
  75. data/test/extra/checking/test_runner.rb +15 -0
  76. data/test/extra/test_link_collector.rb +93 -0
  77. data/test/extra/validators/test_links.rb +0 -64
  78. data/test/extra/validators/test_w3c.rb +20 -26
  79. data/test/filters/test_colorize_syntax.rb +15 -0
  80. data/test/filters/test_less.rb +14 -0
  81. data/test/filters/test_pandoc.rb +5 -1
  82. data/test/helpers/test_blogging.rb +52 -8
  83. data/test/helpers/test_xml_sitemap.rb +68 -0
  84. data/test/test_gem.rb +1 -1
  85. metadata +31 -6
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::Checking::Checks::HTMLTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_run_ok
8
+ with_site do |site|
9
+ # Create files
10
+ FileUtils.mkdir_p('output')
11
+ File.open('output/blah.html', 'w') { |io| io.write('<!DOCTYPE html><html><head><title>Hello</title></head><body><h1>Hi!</h1></body>') }
12
+ File.open('output/style.css', 'w') { |io| io.write('h1 { coxlor: rxed; }') }
13
+
14
+ # Run check
15
+ check = Nanoc::Extra::Checking::Checks::HTML.new(site)
16
+ check.run
17
+
18
+ # Check
19
+ assert check.issues.empty?
20
+ end
21
+ end
22
+
23
+ def test_run_error
24
+ with_site do |site|
25
+ # Create files
26
+ FileUtils.mkdir_p('output')
27
+ File.open('output/blah.html', 'w') { |io| io.write('<h2>Hi!</h1>') }
28
+ File.open('output/style.css', 'w') { |io| io.write('h1 { coxlor: rxed; }') }
29
+
30
+ # Run check
31
+ check = Nanoc::Extra::Checking::Checks::HTML.new(site)
32
+ check.run
33
+
34
+ # Check
35
+ refute check.issues.empty?
36
+ end
37
+ end
38
+
39
+ end
40
+
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::Checking::Checks::InternalLinksTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_run
8
+ with_site do |site|
9
+ # Create files
10
+ FileUtils.mkdir_p('output')
11
+ FileUtils.mkdir_p('output/stuff')
12
+ File.open('output/foo.txt', 'w') { |io| io.write('<a href="/broken">broken</a>') }
13
+ File.open('output/bar.html', 'w') { |io| io.write('<a href="/foo.txt">not broken</a>') }
14
+
15
+ # Create check
16
+ check = Nanoc::Extra::Checking::Checks::InternalLinks.new(site)
17
+ check.run
18
+
19
+ # Test
20
+ assert check.issues.empty?
21
+ end
22
+ end
23
+
24
+ def test_valid?
25
+ with_site do |site|
26
+ # Create files
27
+ FileUtils.mkdir_p('output')
28
+ FileUtils.mkdir_p('output/stuff')
29
+ File.open('output/origin', 'w') { |io| io.write('hi') }
30
+ File.open('output/foo', 'w') { |io| io.write('hi') }
31
+ File.open('output/stuff/blah', 'w') { |io| io.write('hi') }
32
+
33
+ # Create check
34
+ check = Nanoc::Extra::Checking::Checks::InternalLinks.new(site)
35
+
36
+ # Test
37
+ assert check.send(:valid?, 'foo', 'output/origin')
38
+ assert check.send(:valid?, 'origin', 'output/origin')
39
+ assert check.send(:valid?, 'stuff/blah', 'output/origin')
40
+ assert check.send(:valid?, '/foo', 'output/origin')
41
+ assert check.send(:valid?, '/origin', 'output/origin')
42
+ assert check.send(:valid?, '/stuff/blah', 'output/origin')
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::Checking::Checks::StaleTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def check_class
8
+ Nanoc::Extra::Checking::Checks::Stale
9
+ end
10
+
11
+ def calc_issues
12
+ site = Nanoc::Site.new('.')
13
+ check = check_class.new(site)
14
+ check.run
15
+ check.issues
16
+ end
17
+
18
+ def test_run_ok
19
+ with_site do |site|
20
+ assert Dir['content/*'].empty?
21
+ assert Dir['output/*'].empty?
22
+
23
+ # Empty
24
+ FileUtils.mkdir_p('output')
25
+ assert self.calc_issues.empty?
26
+
27
+ # One OK file
28
+ File.open('content/index.html', 'w') { |io| io.write('stuff') }
29
+ File.open('output/index.html', 'w') { |io| io.write('stuff') }
30
+ assert self.calc_issues.empty?
31
+ end
32
+ end
33
+
34
+ def test_run_error
35
+ with_site do |site|
36
+ assert Dir['content/*'].empty?
37
+ assert Dir['output/*'].empty?
38
+
39
+ File.open('content/index.html', 'w') { |io| io.write('stuff') }
40
+ File.open('output/WRONG.html', 'w') { |io| io.write('stuff') }
41
+ assert_equal 1, self.calc_issues.count
42
+ issue = self.calc_issues.to_a[0]
43
+ assert_equal "file without matching item", issue.description
44
+ assert_equal "output/WRONG.html", issue.subject
45
+ end
46
+ end
47
+
48
+ end
49
+
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::Checking::CheckTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_output_filenames
8
+ with_site do |site|
9
+ check = Nanoc::Extra::Checking::Check.new(site)
10
+ assert check.output_filenames.empty?
11
+ File.open('output/foo.html', 'w') { |io| io.write 'hello' }
12
+ assert_equal [ 'output/foo.html' ], check.output_filenames
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::Checking::DSLTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_from_file
8
+ with_site do |site|
9
+ File.open('Checks', 'w') { |io| io.write("check :foo do\n\nend\ndeploy_check :bar\n") }
10
+ dsl = Nanoc::Extra::Checking::DSL.from_file('Checks')
11
+
12
+ # One new check
13
+ refute Nanoc::Extra::Checking::Check.named(:foo).nil?
14
+
15
+ # One check marked for deployment
16
+ assert_equal [ :bar ], dsl.deploy_checks
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::Checking::RunnerTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_run
8
+ with_site do |site|
9
+ File.open('output/blah', 'w') { |io| io.write('I am stale! Haha!') }
10
+ runner = Nanoc::Extra::Checking::Runner.new(site)
11
+ runner.run_specific(%w( stale ))
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::Extra::LinkCollectorTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_all
8
+ # Create dummy data
9
+ File.open('file-a.html', 'w') do |io|
10
+ io << %[<a href="http://example.com/">A 1</a>\n]
11
+ io << %[<a href="https://example.com/">A 2</a>\n]
12
+ io << %[<a href="stuff/"A 3></a>\n]
13
+ io << %[<a name="href-less-anchor">A 4</a>]
14
+ io << %[<a href="https://example.com/with-fragment#moo">A 5</a>\n]
15
+ end
16
+ File.open('file-b.html', 'w') do |io|
17
+ io << %[<a href="mailto:bob@example.com">B 1</a>\n]
18
+ io << %[<a href="../stuff">B 2</a>\n]
19
+ io << %[<a href="/stuff">B 3</a>\n]
20
+ end
21
+
22
+ # Create validator
23
+ collector = Nanoc::Extra::LinkCollector.new(%w( file-a.html file-b.html ))
24
+
25
+ # Test
26
+ hrefs_with_filenames = collector.filenames_per_href
27
+ hrefs = hrefs_with_filenames.keys
28
+ assert_includes hrefs, 'http://example.com/'
29
+ assert_includes hrefs, 'https://example.com/'
30
+ assert_includes hrefs, 'stuff/'
31
+ refute_includes hrefs, nil
32
+ assert_includes hrefs, 'mailto:bob@example.com'
33
+ assert_includes hrefs, '../stuff'
34
+ assert_includes hrefs, '/stuff'
35
+ refute_includes hrefs, 'https://example.com/with-fragment#moo'
36
+ assert_includes hrefs, 'https://example.com/with-fragment'
37
+ end
38
+
39
+ def test_external
40
+ # Create dummy data
41
+ File.open('file-a.html', 'w') do |io|
42
+ io << %[<a href="http://example.com/">A 1</a>\n]
43
+ io << %[<a href="https://example.com/">A 2</a>\n]
44
+ io << %[<a href="stuff/"A 3></a>\n]
45
+ end
46
+ File.open('file-b.html', 'w') do |io|
47
+ io << %[<a href="mailto:bob@example.com">B 1</a>\n]
48
+ io << %[<a href="../stuff">B 2</a>\n]
49
+ io << %[<a href="/stuff">B 3</a>\n]
50
+ end
51
+
52
+ # Create validator
53
+ collector = Nanoc::Extra::LinkCollector.new(%w( file-a.html file-b.html ), :external)
54
+
55
+ # Test
56
+ hrefs_with_filenames = collector.filenames_per_href
57
+ hrefs = hrefs_with_filenames.keys
58
+ assert_includes hrefs, 'http://example.com/'
59
+ assert_includes hrefs, 'https://example.com/'
60
+ refute_includes hrefs, 'stuff/'
61
+ assert_includes hrefs, 'mailto:bob@example.com'
62
+ refute_includes hrefs, '../stuff'
63
+ refute_includes hrefs, '/stuff'
64
+ end
65
+
66
+ def test_internal
67
+ # Create dummy data
68
+ File.open('file-a.html', 'w') do |io|
69
+ io << %[<a href="http://example.com/">A 1</a>\n]
70
+ io << %[<a href="https://example.com/">A 2</a>\n]
71
+ io << %[<a href="stuff/"A 3></a>\n]
72
+ end
73
+ File.open('file-b.html', 'w') do |io|
74
+ io << %[<a href="mailto:bob@example.com">B 1</a>\n]
75
+ io << %[<a href="../stuff">B 2</a>\n]
76
+ io << %[<a href="/stuff">B 3</a>\n]
77
+ end
78
+
79
+ # Create validator
80
+ collector = Nanoc::Extra::LinkCollector.new(%w( file-a.html file-b.html ), :internal)
81
+
82
+ # Test
83
+ hrefs_with_filenames = collector.filenames_per_href
84
+ hrefs = hrefs_with_filenames.keys
85
+ refute_includes hrefs, 'http://example.com/'
86
+ refute_includes hrefs, 'https://example.com/'
87
+ assert_includes hrefs, 'stuff/'
88
+ refute_includes hrefs, 'mailto:bob@example.com'
89
+ assert_includes hrefs, '../stuff'
90
+ assert_includes hrefs, '/stuff'
91
+ end
92
+
93
+ end
@@ -4,68 +4,4 @@ class Nanoc::Extra::Validators::LinksTest < MiniTest::Unit::TestCase
4
4
 
5
5
  include Nanoc::TestHelpers
6
6
 
7
- def test_is_external_href?
8
- # Create validator
9
- validator = Nanoc::Extra::Validators::Links.new(nil, nil)
10
-
11
- # Test
12
- assert validator.send(:is_external_href?, 'http://example.com/')
13
- assert validator.send(:is_external_href?, 'https://example.com/')
14
- assert validator.send(:is_external_href?, 'mailto:bob@example.com')
15
- assert !validator.send(:is_external_href?, '../stuff')
16
- assert !validator.send(:is_external_href?, '/stuff')
17
- end
18
-
19
- def test_is_valid_internal_href?
20
- # Create files
21
- FileUtils.mkdir_p('output')
22
- FileUtils.mkdir_p('output/stuff')
23
- File.open('output/origin', 'w') { |io| io.write('hi') }
24
- File.open('output/foo', 'w') { |io| io.write('hi') }
25
- File.open('output/stuff/blah', 'w') { |io| io.write('hi') }
26
-
27
- # Create validator
28
- validator = Nanoc::Extra::Validators::Links.new('output', [ 'index.html' ])
29
-
30
- # Test
31
- assert validator.send(:is_valid_internal_href?, 'foo', 'output/origin')
32
- assert validator.send(:is_valid_internal_href?, 'origin', 'output/origin')
33
- assert validator.send(:is_valid_internal_href?, 'stuff/blah', 'output/origin')
34
- assert validator.send(:is_valid_internal_href?, '/foo', 'output/origin')
35
- assert validator.send(:is_valid_internal_href?, '/origin', 'output/origin')
36
- assert validator.send(:is_valid_internal_href?, '/stuff/blah', 'output/origin')
37
- end
38
-
39
- def test_is_valid_external_href?
40
- # Create validator
41
- validator = Nanoc::Extra::Validators::Links.new('output', [ 'index.html' ])
42
- validator.stubs(:fetch_http_status_for).returns(200)
43
-
44
- # Test
45
- assert validator.send(:is_valid_external_href?, 'http://example.com/')
46
- assert validator.send(:is_valid_external_href?, 'https://example.com/')
47
- assert validator.send(:is_valid_external_href?, 'foo://example.com/')
48
- refute validator.send(:is_valid_external_href?, 'http://example.com/">')
49
- end
50
-
51
- def test_fetch_http_status_for
52
- @app = lambda { |env| [ env['REQUEST_PATH'][1..-1].to_i, {}, [ '... Useless body ...' ] ] }
53
- @server = nil
54
-
55
- @thread = Thread.new do
56
- Rack::Handler::WEBrick.run(@app, :Host => @host='127.0.0.1', :Port => @port=9204) do |server|
57
- @server = server
58
- end
59
- end
60
-
61
- Thread.pass until @server
62
-
63
- validator = Nanoc::Extra::Validators::Links.new('output', [ 'index.html' ])
64
- assert_equal 200, validator.send(:fetch_http_status_for, URI.parse('http://127.0.0.1:9204/200'))
65
- assert_equal 404, validator.send(:fetch_http_status_for, URI.parse('http://127.0.0.1:9204/404'))
66
-
67
- @server.stop
68
- @thread.kill
69
- end
70
-
71
7
  end
@@ -6,41 +6,35 @@ class Nanoc::Extra::Validators::W3CTest < MiniTest::Unit::TestCase
6
6
 
7
7
  def test_simple
8
8
  if_have 'w3c_validators' do
9
- # Create some sample files
10
- %w{ foo bar baz }.each do |filename|
11
- %w{ xxx yyy }.each do |extension|
12
- File.open("#{filename}.#{extension}", 'w') { |io| io.write("hello") }
9
+ with_site do |site|
10
+ # Create some sample files
11
+ %w{ foo bar baz }.each do |filename|
12
+ %w{ xxx yyy }.each do |extension|
13
+ File.open("output/#{filename}.#{extension}", 'w') { |io| io.write("hello") }
14
+ end
13
15
  end
14
- end
15
16
 
16
- # Create validator
17
- w3c = Nanoc::Extra::Validators::W3C.new('.', [ :xxx ])
18
-
19
- # Configure expectations
20
- validator_result = mock
21
- validator_result.expects(:errors).times(3)
22
- validator = mock
23
- validator.expects(:validate_file).times(3).returns(validator_result)
24
- w3c.expects(:types_to_extensions).with([ :xxx ]).returns([ 'xxx' ])
25
- w3c.expects(:validator_for).with('xxx').times(3).returns(validator)
26
- w3c.expects(:validation_started).times(3)
27
- w3c.expects(:validation_ended).times(3)
28
-
29
- # Run
30
- w3c.run
17
+ # Create validator
18
+ w3c = Nanoc::Extra::Validators::W3C.new('.', [ :html ])
19
+
20
+ # Run
21
+ w3c.run
22
+ end
31
23
  end
32
24
  end
33
25
 
34
26
  def test_with_unknown_types
35
27
  if_have 'w3c_validators' do
36
- # Create validator
37
- w3c = Nanoc::Extra::Validators::W3C.new('.', [ :foo ])
28
+ with_site do |site|
29
+ # Create validator
30
+ w3c = Nanoc::Extra::Validators::W3C.new('.', [ :foo ])
38
31
 
39
- # Test
40
- exception = assert_raises RuntimeError do
41
- w3c.run
32
+ # Test
33
+ exception = assert_raises Nanoc::Errors::GenericTrivial do
34
+ w3c.run
35
+ end
36
+ assert_equal 'unknown type(s) specified: foo', exception.message
42
37
  end
43
- assert_equal 'unknown type: foo', exception.message
44
38
  end
45
39
  end
46
40
 
@@ -88,6 +88,21 @@ EOS
88
88
  end
89
89
  end
90
90
 
91
+ def test_coderay_with_comment_in_middle
92
+ if_have 'coderay', 'nokogiri' do
93
+ # Create filter
94
+ filter = ::Nanoc::Filters::ColorizeSyntax.new
95
+
96
+ # Get input and expected output
97
+ input = %[<pre title="moo"><code>def moo ; end\n#!ruby\n# comment</code></pre>]
98
+ expected_output = "<pre title=\"moo\"><code>def moo ; end\n#!ruby\n# comment</code></pre>"
99
+
100
+ # Run filter
101
+ actual_output = filter.run(input)
102
+ assert_equal(expected_output, actual_output)
103
+ end
104
+ end
105
+
91
106
  def test_coderay_with_comment_and_class
92
107
  if_have 'coderay', 'nokogiri' do
93
108
  # Create filter
@@ -110,4 +110,18 @@ class Nanoc::Filters::LessTest < MiniTest::Unit::TestCase
110
110
  end
111
111
  end
112
112
 
113
+ def test_compression
114
+ if_have 'less' do
115
+ # Create item
116
+ @item = Nanoc::Item.new("blah", { :content_filename => 'content/foo/bar.txt' }, '/foo/bar/')
117
+
118
+ # Create filter
119
+ filter = ::Nanoc::Filters::Less.new(:item => @item, :items => [ @item ])
120
+
121
+ # Run filter with compress option
122
+ result = filter.run('.foo { bar: a; } .bar { foo: b; }', :compress => true)
123
+ assert_match(/^\.foo{bar:a;}\n\.bar{foo:b;}/, result)
124
+ end
125
+ end
126
+
113
127
  end