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