nanoc 3.4.3 → 3.5.0b1

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.
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