nanoc 3.4.3 → 3.5.0b1
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTING.md +25 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +22 -13
- data/NEWS.md +27 -0
- data/README.md +3 -1
- data/lib/nanoc.rb +2 -2
- data/lib/nanoc/base/compilation/compiler_dsl.rb +19 -0
- data/lib/nanoc/base/core_ext/array.rb +18 -8
- data/lib/nanoc/base/core_ext/hash.rb +18 -8
- data/lib/nanoc/base/core_ext/pathname.rb +2 -8
- data/lib/nanoc/base/plugin_registry.rb +57 -19
- data/lib/nanoc/base/result_data/item_rep.rb +3 -15
- data/lib/nanoc/base/source_data/item.rb +1 -1
- data/lib/nanoc/base/source_data/layout.rb +1 -1
- data/lib/nanoc/base/source_data/site.rb +15 -19
- data/lib/nanoc/cli.rb +28 -23
- data/lib/nanoc/cli/command_runner.rb +4 -0
- data/lib/nanoc/cli/commands/autocompile.rb +15 -6
- data/lib/nanoc/cli/commands/check.rb +47 -0
- data/lib/nanoc/cli/commands/compile.rb +271 -195
- data/lib/nanoc/cli/commands/create-site.rb +5 -5
- data/lib/nanoc/cli/commands/deploy.rb +16 -4
- data/lib/nanoc/cli/commands/prune.rb +3 -3
- data/lib/nanoc/cli/commands/show-data.rb +73 -58
- data/lib/nanoc/cli/commands/show-rules.rb +1 -1
- data/lib/nanoc/cli/commands/validate-css.rb +2 -3
- data/lib/nanoc/cli/commands/validate-html.rb +2 -3
- data/lib/nanoc/cli/commands/validate-links.rb +5 -11
- data/lib/nanoc/cli/commands/view.rb +1 -1
- data/lib/nanoc/cli/commands/watch.rb +38 -20
- data/lib/nanoc/cli/error_handler.rb +122 -122
- data/lib/nanoc/data_sources.rb +2 -0
- data/lib/nanoc/data_sources/filesystem_unified.rb +1 -1
- data/lib/nanoc/data_sources/filesystem_verbose.rb +1 -1
- data/lib/nanoc/data_sources/static.rb +60 -0
- data/lib/nanoc/extra.rb +2 -0
- data/lib/nanoc/extra/checking.rb +16 -0
- data/lib/nanoc/extra/checking/check.rb +33 -0
- data/lib/nanoc/extra/checking/checks.rb +19 -0
- data/lib/nanoc/extra/checking/checks/css.rb +23 -0
- data/lib/nanoc/extra/checking/checks/external_links.rb +149 -0
- data/lib/nanoc/extra/checking/checks/html.rb +24 -0
- data/lib/nanoc/extra/checking/checks/internal_links.rb +57 -0
- data/lib/nanoc/extra/checking/checks/stale.rb +23 -0
- data/lib/nanoc/extra/checking/dsl.rb +31 -0
- data/lib/nanoc/extra/checking/issue.rb +19 -0
- data/lib/nanoc/extra/checking/runner.rb +130 -0
- data/lib/nanoc/extra/link_collector.rb +57 -0
- data/lib/nanoc/extra/pruner.rb +1 -1
- data/lib/nanoc/extra/validators/links.rb +5 -262
- data/lib/nanoc/extra/validators/w3c.rb +8 -76
- data/lib/nanoc/filters/colorize_syntax.rb +1 -1
- data/lib/nanoc/filters/handlebars.rb +2 -2
- data/lib/nanoc/filters/less.rb +1 -1
- data/lib/nanoc/filters/redcarpet.rb +1 -1
- data/lib/nanoc/filters/rubypants.rb +1 -1
- data/lib/nanoc/filters/slim.rb +1 -1
- data/lib/nanoc/helpers/blogging.rb +163 -104
- data/lib/nanoc/helpers/xml_sitemap.rb +9 -3
- data/tasks/doc.rake +2 -1
- data/test/base/core_ext/array_spec.rb +4 -4
- data/test/base/core_ext/hash_spec.rb +7 -7
- data/test/base/core_ext/pathname_spec.rb +12 -2
- data/test/base/test_compiler_dsl.rb +24 -0
- data/test/base/test_item_rep.rb +58 -26
- data/test/cli/commands/test_watch.rb +0 -8
- data/test/data_sources/test_static.rb +66 -0
- data/test/extra/checking/checks/test_css.rb +40 -0
- data/test/extra/checking/checks/test_external_links.rb +76 -0
- data/test/extra/checking/checks/test_html.rb +40 -0
- data/test/extra/checking/checks/test_internal_links.rb +46 -0
- data/test/extra/checking/checks/test_stale.rb +49 -0
- data/test/extra/checking/test_check.rb +16 -0
- data/test/extra/checking/test_dsl.rb +20 -0
- data/test/extra/checking/test_runner.rb +15 -0
- data/test/extra/test_link_collector.rb +93 -0
- data/test/extra/validators/test_links.rb +0 -64
- data/test/extra/validators/test_w3c.rb +20 -26
- data/test/filters/test_colorize_syntax.rb +15 -0
- data/test/filters/test_less.rb +14 -0
- data/test/filters/test_pandoc.rb +5 -1
- data/test/helpers/test_blogging.rb +52 -8
- data/test/helpers/test_xml_sitemap.rb +68 -0
- data/test/test_gem.rb +1 -1
- metadata +31 -6
data/lib/nanoc/data_sources.rb
CHANGED
@@ -5,9 +5,11 @@ module Nanoc::DataSources
|
|
5
5
|
autoload 'Filesystem', 'nanoc/data_sources/filesystem'
|
6
6
|
autoload 'FilesystemUnified', 'nanoc/data_sources/filesystem_unified'
|
7
7
|
autoload 'FilesystemVerbose', 'nanoc/data_sources/filesystem_verbose'
|
8
|
+
autoload 'Static', 'nanoc/data_sources/static'
|
8
9
|
|
9
10
|
Nanoc::DataSource.register '::Nanoc::DataSources::FilesystemVerbose', :filesystem_verbose
|
10
11
|
Nanoc::DataSource.register '::Nanoc::DataSources::FilesystemUnified', :filesystem_unified
|
12
|
+
Nanoc::DataSource.register '::Nanoc::DataSources::Static', :static
|
11
13
|
|
12
14
|
# Deprecated; fetch data from online data sources manually instead
|
13
15
|
# TODO [in nanoc 4.0] remove me
|
@@ -85,7 +85,7 @@ module Nanoc::DataSources
|
|
85
85
|
# Write item
|
86
86
|
FileUtils.mkdir_p(parent_path)
|
87
87
|
File.open(path, 'w') do |io|
|
88
|
-
meta = attributes.
|
88
|
+
meta = attributes.stringify_keys_recursively
|
89
89
|
unless meta == {}
|
90
90
|
io.write(YAML.dump(meta).strip + "\n")
|
91
91
|
io.write("---\n\n")
|
@@ -63,7 +63,7 @@ module Nanoc::DataSources
|
|
63
63
|
|
64
64
|
# Create files
|
65
65
|
FileUtils.mkdir_p(dir_path)
|
66
|
-
File.open(meta_filename, 'w') { |io| io.write(YAML.dump(attributes.
|
66
|
+
File.open(meta_filename, 'w') { |io| io.write(YAML.dump(attributes.stringify_keys_recursively)) }
|
67
67
|
File.open(content_filename, 'w') { |io| io.write(content) }
|
68
68
|
end
|
69
69
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc::DataSources
|
4
|
+
|
5
|
+
# The static data source provides items from a single directory. Unlike the
|
6
|
+
# filesystem data sources, static provides no additional item metadata. In
|
7
|
+
# addition, all items are treated as 'binary', regardless of their extension
|
8
|
+
# or content. As such, it is most useful for simple assets, not for normal
|
9
|
+
# content.
|
10
|
+
#
|
11
|
+
# The identifier for static items is the full item path. For example, if your
|
12
|
+
# static data source item_root is `static`, an item named `foo.css` would have
|
13
|
+
# the identifier `/static/foo.css/`. Note that, unlike the filesystem data
|
14
|
+
# sources, `foo/index.html` and `foo.yaml` receive no special treatment. They
|
15
|
+
# are simple static items, just like `foo.css`.
|
16
|
+
#
|
17
|
+
# The default data source directory is `static/`, but this can be overridden
|
18
|
+
# in the data source configuration:
|
19
|
+
#
|
20
|
+
# data_sources:
|
21
|
+
# - type: static
|
22
|
+
# prefix: assets
|
23
|
+
#
|
24
|
+
# Unless the `hide_items` configuration attribute is false, items from static
|
25
|
+
# data sources will have the :is_hidden attribute set by default, which will
|
26
|
+
# exclude them from the Blogging helper's atom feed generator, among other
|
27
|
+
# things.
|
28
|
+
class Static < Nanoc::DataSource
|
29
|
+
identifier :static
|
30
|
+
|
31
|
+
def items
|
32
|
+
# Get prefix
|
33
|
+
prefix = config[:prefix] || 'static'
|
34
|
+
|
35
|
+
# Get all files under prefix dir
|
36
|
+
filenames = Dir[prefix + '/**/*'].select { |f| File.file?(f) }
|
37
|
+
|
38
|
+
# Convert filenames to items
|
39
|
+
filenames.map do |filename|
|
40
|
+
attributes = {
|
41
|
+
:extension => File.extname(filename)[1..-1],
|
42
|
+
:filename => filename,
|
43
|
+
}
|
44
|
+
attributes[:is_hidden] = true unless config[:hide_items] == false
|
45
|
+
identifier = filename[(prefix.length+1)..-1] + '/'
|
46
|
+
|
47
|
+
mtime = File.mtime(filename)
|
48
|
+
checksum = Pathname.new(filename).checksum
|
49
|
+
|
50
|
+
Nanoc::Item.new(
|
51
|
+
filename,
|
52
|
+
attributes,
|
53
|
+
identifier,
|
54
|
+
:binary => true, :mtime => mtime, :checksum => checksum
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
data/lib/nanoc/extra.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
module Nanoc::Extra
|
4
4
|
|
5
5
|
autoload 'AutoCompiler', 'nanoc/extra/auto_compiler'
|
6
|
+
autoload 'Checking', 'nanoc/extra/checking'
|
6
7
|
autoload 'CHiCk', 'nanoc/extra/chick'
|
8
|
+
autoload 'LinkCollector', 'nanoc/extra/link_collector.rb'
|
7
9
|
autoload 'Pruner', 'nanoc/extra/pruner'
|
8
10
|
autoload 'Validators', 'nanoc/extra/validators'
|
9
11
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc::Extra
|
4
|
+
|
5
|
+
module Checking
|
6
|
+
|
7
|
+
autoload 'Check', 'nanoc/extra/checking/check'
|
8
|
+
autoload 'DSL', 'nanoc/extra/checking/dsl'
|
9
|
+
autoload 'Runner', 'nanoc/extra/checking/runner.rb'
|
10
|
+
autoload 'Issue', 'nanoc/extra/checking/issue'
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'nanoc/extra/checking/checks'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc::Extra::Checking
|
4
|
+
|
5
|
+
class Check
|
6
|
+
|
7
|
+
extend Nanoc::PluginRegistry::PluginMethods
|
8
|
+
|
9
|
+
attr_reader :site
|
10
|
+
attr_reader :issues
|
11
|
+
|
12
|
+
def initialize(site)
|
13
|
+
@site = site
|
14
|
+
@issues = Set.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
raise NotImplementedError.new("Nanoc::Extra::Checking::Check subclasses must implement #run")
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_issue(desc, params={})
|
22
|
+
subject = params.fetch(:subject, nil)
|
23
|
+
|
24
|
+
@issues << Issue.new(desc, subject, self.class)
|
25
|
+
end
|
26
|
+
|
27
|
+
def output_filenames
|
28
|
+
Dir[@site.config[:output_dir] + '/**/*'].select{ |f| File.file?(f) }
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc::Extra::Checking::Checks
|
4
|
+
|
5
|
+
autoload 'CSS', 'nanoc/extra/checking/checks/css'
|
6
|
+
autoload 'ExternalLinks', 'nanoc/extra/checking/checks/external_links'
|
7
|
+
autoload 'HTML', 'nanoc/extra/checking/checks/html'
|
8
|
+
autoload 'InternalLinks', 'nanoc/extra/checking/checks/internal_links'
|
9
|
+
autoload 'Stale', 'nanoc/extra/checking/checks/stale'
|
10
|
+
|
11
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::CSS', :css
|
12
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::ExternalLinks', :external_links
|
13
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::ExternalLinks', :elinks
|
14
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::HTML', :html
|
15
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::InternalLinks', :internal_links
|
16
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::InternalLinks', :ilinks
|
17
|
+
Nanoc::Extra::Checking::Check.register '::Nanoc::Extra::Checking::Checks::Stale', :stale
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ::Nanoc::Extra::Checking::Checks
|
4
|
+
|
5
|
+
class CSS < ::Nanoc::Extra::Checking::Check
|
6
|
+
|
7
|
+
identifier :css
|
8
|
+
|
9
|
+
def run
|
10
|
+
require 'w3c_validators'
|
11
|
+
|
12
|
+
Dir[site.config[:output_dir] + '/**/*.css'].each do |filename|
|
13
|
+
results = ::W3CValidators::CSSValidator.new.validate_file(filename)
|
14
|
+
results.errors.each do |e|
|
15
|
+
desc = e.message.gsub(%r{\s+}, ' ').strip
|
16
|
+
self.add_issue(desc, :subject => filename)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'timeout'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
module ::Nanoc::Extra::Checking::Checks
|
10
|
+
|
11
|
+
# A validator that verifies that all external links point to a location that exists.
|
12
|
+
class ExternalLinks < ::Nanoc::Extra::Checking::Check
|
13
|
+
|
14
|
+
identifiers :external_links, :elinks
|
15
|
+
|
16
|
+
def run
|
17
|
+
# Find all broken external hrefs
|
18
|
+
# TODO de-duplicate this (duplicated in internal links check)
|
19
|
+
filenames = self.output_filenames.select { |f| File.extname(f) == '.html' }
|
20
|
+
hrefs_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :external).filenames_per_href
|
21
|
+
results = self.select_invalid(hrefs_with_filenames.keys)
|
22
|
+
|
23
|
+
# Report them
|
24
|
+
results.each do |res|
|
25
|
+
filenames = hrefs_with_filenames[res.href]
|
26
|
+
filenames.each do |filename|
|
27
|
+
self.add_issue(
|
28
|
+
"reference to #{res.href}: #{res.explanation}",
|
29
|
+
:subject => filename)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Result
|
35
|
+
|
36
|
+
attr_reader :href
|
37
|
+
attr_reader :explanation
|
38
|
+
|
39
|
+
def initialize(href, explanation)
|
40
|
+
@href = href
|
41
|
+
@explanation = explanation
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class ArrayEnumerator
|
47
|
+
|
48
|
+
def initialize(array)
|
49
|
+
@array = array
|
50
|
+
@index = 0
|
51
|
+
@mutex = Mutex.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def next
|
55
|
+
@mutex.synchronize do
|
56
|
+
@index += 1
|
57
|
+
return @array[@index-1]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
def select_invalid(hrefs)
|
64
|
+
enum = ArrayEnumerator.new(hrefs.sort)
|
65
|
+
mutex = Mutex.new
|
66
|
+
invalid = Set.new
|
67
|
+
|
68
|
+
threads = []
|
69
|
+
10.times do
|
70
|
+
threads << Thread.new do
|
71
|
+
loop do
|
72
|
+
href = enum.next
|
73
|
+
break if href.nil?
|
74
|
+
res = self.validate(href)
|
75
|
+
if res
|
76
|
+
mutex.synchronize do
|
77
|
+
invalid << res
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
threads.each { |t| t.join }
|
84
|
+
|
85
|
+
invalid
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate(href)
|
89
|
+
# Parse
|
90
|
+
url = nil
|
91
|
+
begin
|
92
|
+
url = URI.parse(href)
|
93
|
+
rescue URI::InvalidURIError
|
94
|
+
return Result.new(href, 'invalid URI')
|
95
|
+
end
|
96
|
+
|
97
|
+
# Skip non-HTTP URLs
|
98
|
+
return nil if url.scheme !~ /^https?$/
|
99
|
+
|
100
|
+
# Get status
|
101
|
+
res = nil
|
102
|
+
5.times do |i|
|
103
|
+
begin
|
104
|
+
Timeout::timeout(10) do
|
105
|
+
res = request_url_once(url)
|
106
|
+
end
|
107
|
+
rescue => e
|
108
|
+
return Result.new(href, e.message)
|
109
|
+
end
|
110
|
+
|
111
|
+
if res.code =~ /^3..$/
|
112
|
+
if i == 4
|
113
|
+
return Result.new(href, 'too many redirects')
|
114
|
+
end
|
115
|
+
|
116
|
+
# Find proper location
|
117
|
+
location = res['Location']
|
118
|
+
if location !~ /^https?:\/\//
|
119
|
+
base_url = url.dup
|
120
|
+
base_url.path = (location =~ /^\// ? '' : '/')
|
121
|
+
base_url.query = nil
|
122
|
+
base_url.fragment = nil
|
123
|
+
location = base_url.to_s + location
|
124
|
+
end
|
125
|
+
|
126
|
+
url = URI.parse(location)
|
127
|
+
elsif res.code == '200'
|
128
|
+
return nil
|
129
|
+
else
|
130
|
+
return Result.new(href, res.code)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
raise 'should not have gotten here'
|
134
|
+
end
|
135
|
+
|
136
|
+
def request_url_once(url)
|
137
|
+
path = (url.path.nil? || url.path.empty? ? '/' : url.path)
|
138
|
+
req = Net::HTTP::Head.new(path)
|
139
|
+
http = Net::HTTP.new(url.host, url.port)
|
140
|
+
if url.instance_of? URI::HTTPS
|
141
|
+
http.use_ssl = true
|
142
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
143
|
+
end
|
144
|
+
res = http.request(req)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ::Nanoc::Extra::Checking::Checks
|
4
|
+
|
5
|
+
class HTML < ::Nanoc::Extra::Checking::Check
|
6
|
+
|
7
|
+
identifier :html
|
8
|
+
|
9
|
+
def run
|
10
|
+
require 'w3c_validators'
|
11
|
+
|
12
|
+
Dir[site.config[:output_dir] + '/**/*.{htm,html}'].each do |filename|
|
13
|
+
results = ::W3CValidators::MarkupValidator.new.validate_file(filename)
|
14
|
+
results.errors.each do |e|
|
15
|
+
desc = e.message.gsub(%r{\s+}, ' ').strip
|
16
|
+
self.add_issue(desc, :subject => filename)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc::Extra::Checking::Checks
|
4
|
+
|
5
|
+
# A check that verifies that all internal links point to a location that exists.
|
6
|
+
class InternalLinks < ::Nanoc::Extra::Checking::Check
|
7
|
+
|
8
|
+
# Starts the validator. The results will be printed to stdout.
|
9
|
+
#
|
10
|
+
# @return [void]
|
11
|
+
def run
|
12
|
+
# TODO de-duplicate this (duplicated in external links check)
|
13
|
+
filenames = self.output_filenames.select { |f| File.extname(f) == '.html' }
|
14
|
+
hrefs_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :internal).filenames_per_href
|
15
|
+
hrefs_with_filenames.each_pair do |href, filenames|
|
16
|
+
filenames.each do |filename|
|
17
|
+
unless valid?(href, filename)
|
18
|
+
self.add_issue(
|
19
|
+
"reference to #{href}",
|
20
|
+
:subject => filename)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def valid?(href, origin)
|
29
|
+
# Skip hrefs that point to self
|
30
|
+
# FIXME this is ugly and won’t always be correct
|
31
|
+
return true if href == '.'
|
32
|
+
|
33
|
+
# Remove target
|
34
|
+
path = href.sub(/#.*$/, '')
|
35
|
+
return true if path.empty?
|
36
|
+
|
37
|
+
# Make absolute
|
38
|
+
if path[0, 1] == '/'
|
39
|
+
path = @site.config[:output_dir] + path
|
40
|
+
else
|
41
|
+
path = ::File.expand_path(path, ::File.dirname(origin))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Check whether file exists
|
45
|
+
return true if File.file?(path)
|
46
|
+
|
47
|
+
# Check whether directory with index file exists
|
48
|
+
return true if File.directory?(path) && @site.config[:index_filenames].any? { |fn| File.file?(File.join(path, fn)) }
|
49
|
+
|
50
|
+
# Nope :(
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc::Extra::Checking::Checks
|
4
|
+
|
5
|
+
class Stale < ::Nanoc::Extra::Checking::Check
|
6
|
+
|
7
|
+
def run
|
8
|
+
require 'set'
|
9
|
+
item_rep_paths = Set.new(@site.items.collect { |i| i.reps }.flatten.collect { |r| r.raw_path })
|
10
|
+
self.output_filenames.each do |f|
|
11
|
+
if !item_rep_paths.include?(f)
|
12
|
+
self.add_issue(
|
13
|
+
"file without matching item",
|
14
|
+
:subject => f)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|