nanoc 3.7.5 → 3.8.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 +4 -4
- data/ChangeLog +2 -2
- data/Gemfile +1 -1
- data/NEWS.md +24 -3
- data/README.md +1 -1
- data/bin/nanoc +1 -1
- data/lib/nanoc/base/compilation/dependency_tracker.rb +1 -1
- data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +1 -1
- data/lib/nanoc/base/compilation/rule.rb +15 -1
- data/lib/nanoc/base/result_data/item_rep.rb +27 -10
- data/lib/nanoc/base/source_data/item_array.rb +2 -0
- data/lib/nanoc/base/source_data/site.rb +1 -0
- data/lib/nanoc/cli.rb +16 -7
- data/lib/nanoc/cli/commands/autocompile.rb +1 -1
- data/lib/nanoc/cli/commands/create-site.rb +2 -2
- data/lib/nanoc/cli/commands/show-rules.rb +3 -6
- data/lib/nanoc/cli/commands/watch.rb +3 -3
- data/lib/nanoc/cli/error_handler.rb +1 -1
- data/lib/nanoc/cli/logger.rb +3 -5
- data/lib/nanoc/data_sources/filesystem.rb +2 -2
- data/lib/nanoc/extra/auto_compiler.rb +1 -1
- data/lib/nanoc/extra/checking/checks.rb +2 -0
- data/lib/nanoc/extra/checking/checks/mixed_content.rb +31 -0
- data/lib/nanoc/extra/deployers/fog.rb +24 -0
- data/lib/nanoc/extra/link_collector.rb +42 -9
- data/lib/nanoc/extra/pruner.rb +1 -1
- data/lib/nanoc/filters/colorize_syntax.rb +4 -4
- data/lib/nanoc/filters/pandoc.rb +23 -4
- data/lib/nanoc/filters/sass/sass_filesystem_importer.rb +4 -2
- data/lib/nanoc/helpers/blogging.rb +17 -6
- data/lib/nanoc/helpers/tagging.rb +1 -1
- data/lib/nanoc/helpers/text.rb +1 -1
- data/lib/nanoc/version.rb +1 -1
- data/tasks/test.rake +1 -1
- data/test/base/test_item_array.rb +8 -0
- data/test/base/test_item_rep.rb +51 -0
- data/test/base/test_item_rep_recorder_proxy.rb +19 -0
- data/test/base/test_rule.rb +10 -0
- data/test/cli/commands/test_create_site.rb +13 -0
- data/test/cli/test_cli.rb +30 -0
- data/test/extra/checking/checks/test_mixed_content.rb +188 -0
- data/test/extra/deployers/test_fog.rb +32 -0
- data/test/filters/test_pandoc.rb +17 -3
- data/test/filters/test_sass.rb +11 -0
- data/test/helper.rb +3 -3
- data/test/helpers/test_blogging.rb +30 -0
- metadata +6 -3
@@ -8,6 +8,10 @@ module Nanoc::Extra::Deployers
|
|
8
8
|
# deploy:
|
9
9
|
# public:
|
10
10
|
# kind: fog
|
11
|
+
# bucket: nanoc-site
|
12
|
+
# cdn_id: XXXXXX
|
13
|
+
# preprod:
|
14
|
+
# kind: fog
|
11
15
|
# provider: local
|
12
16
|
# local_root: ~/myCloud
|
13
17
|
# bucket: nanoc-site
|
@@ -25,6 +29,7 @@ module Nanoc::Extra::Deployers
|
|
25
29
|
src = File.expand_path(source_path)
|
26
30
|
bucket = config.delete(:bucket) || config.delete(:bucket_name)
|
27
31
|
path = config.delete(:path)
|
32
|
+
cdn_id = config.delete(:cdn_id)
|
28
33
|
|
29
34
|
config.delete(:kind)
|
30
35
|
|
@@ -33,6 +38,7 @@ module Nanoc::Extra::Deployers
|
|
33
38
|
|
34
39
|
# Mock if necessary
|
35
40
|
if self.dry_run?
|
41
|
+
puts 'Dry run - simulation'
|
36
42
|
::Fog.mock!
|
37
43
|
end
|
38
44
|
|
@@ -51,6 +57,7 @@ module Nanoc::Extra::Deployers
|
|
51
57
|
|
52
58
|
# Create bucket if necessary
|
53
59
|
if should_create_bucket
|
60
|
+
puts 'Creating bucket'
|
54
61
|
directory = connection.directories.create(key: bucket, prefix: path)
|
55
62
|
end
|
56
63
|
|
@@ -63,6 +70,7 @@ module Nanoc::Extra::Deployers
|
|
63
70
|
files += set
|
64
71
|
end
|
65
72
|
keys_to_destroy = files.all.map(&:key)
|
73
|
+
keys_to_invalidate = []
|
66
74
|
|
67
75
|
# Upload all the files in the output folder to the clouds
|
68
76
|
puts 'Uploading local files'
|
@@ -75,6 +83,7 @@ module Nanoc::Extra::Deployers
|
|
75
83
|
body: File.open(file_path),
|
76
84
|
public: true)
|
77
85
|
keys_to_destroy.delete(key)
|
86
|
+
keys_to_invalidate.push(key)
|
78
87
|
end
|
79
88
|
end
|
80
89
|
|
@@ -84,6 +93,21 @@ module Nanoc::Extra::Deployers
|
|
84
93
|
directory.files.get(key).destroy
|
85
94
|
end
|
86
95
|
|
96
|
+
# invalidate CDN objects
|
97
|
+
if cdn_id
|
98
|
+
puts 'Invalidating CDN distribution'
|
99
|
+
keys_to_invalidate.concat(keys_to_destroy)
|
100
|
+
cdn = ::Fog::CDN.new(config)
|
101
|
+
# fog cannot mock CDN requests
|
102
|
+
unless self.dry_run?
|
103
|
+
distribution = cdn.get_distribution(cdn_id)
|
104
|
+
# usual limit per invalidation: 1000 objects
|
105
|
+
keys_to_invalidate.each_slice(1000) do |paths|
|
106
|
+
cdn.post_invalidation(distribution, paths)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
87
111
|
puts 'Done!'
|
88
112
|
end
|
89
113
|
|
@@ -4,6 +4,17 @@ require 'set'
|
|
4
4
|
|
5
5
|
module ::Nanoc::Extra
|
6
6
|
class LinkCollector
|
7
|
+
URI_ATTRS = {
|
8
|
+
'a' => :href,
|
9
|
+
'audio' => :src,
|
10
|
+
'form' => :action,
|
11
|
+
'iframe' => :src,
|
12
|
+
'img' => :src,
|
13
|
+
'link' => :href,
|
14
|
+
'script' => :src,
|
15
|
+
'video' => :src
|
16
|
+
}
|
17
|
+
|
7
18
|
def initialize(filenames, mode = nil)
|
8
19
|
Nanoc::Extra::JRubyNokogiriWarner.check_and_warn
|
9
20
|
|
@@ -33,24 +44,46 @@ module ::Nanoc::Extra
|
|
33
44
|
filenames_per_href
|
34
45
|
end
|
35
46
|
|
47
|
+
def filenames_per_resource_uri
|
48
|
+
require 'nokogiri'
|
49
|
+
filenames_per_resource_uri = {}
|
50
|
+
@filenames.each do |filename|
|
51
|
+
resource_uris_in_file(filename).each do |resouce_uri|
|
52
|
+
filenames_per_resource_uri[resouce_uri] ||= Set.new
|
53
|
+
filenames_per_resource_uri[resouce_uri] << filename
|
54
|
+
end
|
55
|
+
end
|
56
|
+
filenames_per_resource_uri
|
57
|
+
end
|
58
|
+
|
36
59
|
def external_href?(href)
|
37
60
|
href =~ %r{^(\/\/|[a-z\-]+:)}
|
38
61
|
end
|
39
62
|
|
40
63
|
def hrefs_in_file(filename)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
64
|
+
uris_in_file filename, %w(a img)
|
65
|
+
end
|
66
|
+
|
67
|
+
def resource_uris_in_file(filename)
|
68
|
+
uris_in_file filename, %w(audio form img iframe link script video)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
45
72
|
|
46
|
-
|
47
|
-
|
48
|
-
|
73
|
+
def uris_in_file(filename, tag_names)
|
74
|
+
uris = Set.new
|
75
|
+
doc = Nokogiri::HTML(::File.read(filename))
|
76
|
+
tag_names.each do |tag_name|
|
77
|
+
attr = URI_ATTRS[tag_name]
|
78
|
+
doc.css(tag_name).each do |e|
|
79
|
+
uris << e[attr] unless e[attr].nil?
|
80
|
+
end
|
81
|
+
end
|
49
82
|
|
50
83
|
# Strip fragment
|
51
|
-
|
84
|
+
uris.map! { |href| href.gsub(/#.*$/, '') }
|
52
85
|
|
53
|
-
|
86
|
+
uris.select(&@filter)
|
54
87
|
end
|
55
88
|
end
|
56
89
|
end
|
data/lib/nanoc/extra/pruner.rb
CHANGED
@@ -29,7 +29,7 @@ module Nanoc::Filters
|
|
29
29
|
#
|
30
30
|
# * `:coderay` for [Coderay](http://coderay.rubychan.de/)
|
31
31
|
# * `:pygmentize` for [pygmentize](http://pygments.org/docs/cmdline/), the
|
32
|
-
#
|
32
|
+
# command-line frontend for [Pygments](http://pygments.org/)
|
33
33
|
# * `:pygmentsrb` for [pygments.rb](https://github.com/tmm1/pygments.rb),
|
34
34
|
# a Ruby interface for [Pygments](http://pygments.org/)
|
35
35
|
# * `:simon_highlight` for [Highlight](http://www.andre-simon.de/doku/highlight/en/highlight.html)
|
@@ -201,7 +201,7 @@ module Nanoc::Filters
|
|
201
201
|
end
|
202
202
|
|
203
203
|
# Runs the content through [pygmentize](http://pygments.org/docs/cmdline/),
|
204
|
-
# the
|
204
|
+
# the command-line frontend for [Pygments](http://pygments.org/).
|
205
205
|
#
|
206
206
|
# @api private
|
207
207
|
#
|
@@ -216,7 +216,7 @@ module Nanoc::Filters
|
|
216
216
|
check_availability('pygmentize', '-V')
|
217
217
|
|
218
218
|
params[:encoding] ||= 'utf-8'
|
219
|
-
params[:nowrap]
|
219
|
+
params[:nowrap] ||= 'True'
|
220
220
|
|
221
221
|
cmd = ['pygmentize', '-l', language, '-f', 'html']
|
222
222
|
cmd << '-O' << params.map { |k, v| "#{k}=#{v}" }.join(',') unless params.empty?
|
@@ -246,7 +246,7 @@ module Nanoc::Filters
|
|
246
246
|
args[:lexer] ||= language
|
247
247
|
args[:options] ||= {}
|
248
248
|
args[:options][:encoding] ||= 'utf-8'
|
249
|
-
args[:options][:nowrap]
|
249
|
+
args[:options][:nowrap] ||= 'True'
|
250
250
|
|
251
251
|
Pygments.highlight(code, args)
|
252
252
|
end
|
data/lib/nanoc/filters/pandoc.rb
CHANGED
@@ -5,14 +5,33 @@ module Nanoc::Filters
|
|
5
5
|
requires 'pandoc-ruby'
|
6
6
|
|
7
7
|
# Runs the content through [Pandoc](http://johnmacfarlane.net/pandoc/)
|
8
|
-
# using [PandocRuby](https://github.com/alphabetum/pandoc-ruby).
|
9
|
-
#
|
8
|
+
# using [PandocRuby](https://github.com/alphabetum/pandoc-ruby).
|
9
|
+
#
|
10
|
+
# Arguments can be passed to PandocRuby in two ways:
|
11
|
+
#
|
12
|
+
# * Use the `:args` option. This approach is more flexible, since it
|
13
|
+
# allows passing an array instead of a hash.
|
14
|
+
#
|
15
|
+
# * Pass the arguments directly to the filter. With this approach, only
|
16
|
+
# hashes can be passed, which is more limiting than the `:args` approach.
|
17
|
+
#
|
18
|
+
# The `:args` approach is recommended.
|
19
|
+
#
|
20
|
+
# @example Passing arguments using `:arg`
|
21
|
+
#
|
22
|
+
# filter :pandoc, args: [:s, {:f => :markdown, :to => :html}, 'no-wrap', :toc]
|
23
|
+
#
|
24
|
+
# @example Passing arguments not using `:arg`
|
25
|
+
#
|
26
|
+
# filter :pandoc, :f => :markdown, :to => :html
|
10
27
|
#
|
11
28
|
# @param [String] content The content to filter
|
12
29
|
#
|
13
30
|
# @return [String] The filtered content
|
14
|
-
def run(content,
|
15
|
-
|
31
|
+
def run(content, params = {})
|
32
|
+
args = params.key?(:args) ? params[:args] : params
|
33
|
+
|
34
|
+
PandocRuby.convert(content, *args)
|
16
35
|
end
|
17
36
|
end
|
18
37
|
end
|
@@ -10,8 +10,10 @@ class ::Sass::Importers::Filesystem
|
|
10
10
|
|
11
11
|
# Create dependency
|
12
12
|
filter = options[:nanoc_current_filter]
|
13
|
-
|
14
|
-
|
13
|
+
if filter
|
14
|
+
item = filter.imported_filename_to_item(full_filename)
|
15
|
+
filter.depend_on([item]) unless item.nil?
|
16
|
+
end
|
15
17
|
|
16
18
|
# Call original _find
|
17
19
|
_orig_find(dir, name, options)
|
@@ -56,6 +56,7 @@ module Nanoc::Helpers
|
|
56
56
|
|
57
57
|
attr_accessor :limit
|
58
58
|
attr_accessor :relevant_articles
|
59
|
+
attr_accessor :preserve_order
|
59
60
|
attr_accessor :content_proc
|
60
61
|
attr_accessor :excerpt_proc
|
61
62
|
attr_accessor :title
|
@@ -85,9 +86,13 @@ module Nanoc::Helpers
|
|
85
86
|
protected
|
86
87
|
|
87
88
|
def sorted_relevant_articles
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
all = relevant_articles
|
90
|
+
|
91
|
+
unless @preserve_order
|
92
|
+
all = all.sort_by { |a| attribute_to_time(a[:created_at]) }
|
93
|
+
end
|
94
|
+
|
95
|
+
all.reverse.first(limit)
|
91
96
|
end
|
92
97
|
|
93
98
|
def last_article
|
@@ -172,7 +177,7 @@ module Nanoc::Helpers
|
|
172
177
|
if a[:author_name] || a[:author_uri]
|
173
178
|
xml.author do
|
174
179
|
xml.name a[:author_name] || author_name
|
175
|
-
xml.uri a[:author_uri]
|
180
|
+
xml.uri a[:author_uri] || author_uri
|
176
181
|
end
|
177
182
|
end
|
178
183
|
|
@@ -268,8 +273,13 @@ module Nanoc::Helpers
|
|
268
273
|
# @option params [Number] :limit (5) The maximum number of articles to
|
269
274
|
# show
|
270
275
|
#
|
271
|
-
# @option params [Array] :articles (
|
272
|
-
#
|
276
|
+
# @option params [Array] :articles (articles) A list of articles to include
|
277
|
+
# in the feed
|
278
|
+
#
|
279
|
+
# @option params [Boolean] :preserve_order (false) Whether or not the
|
280
|
+
# ordering of the list of articles should be preserved. If false, the
|
281
|
+
# articles will be sorted by `created_at`. If true, the list of articles
|
282
|
+
# will be used as-is, and should have the most recent articles last.
|
273
283
|
#
|
274
284
|
# @option params [Proc] :content_proc (->{ |article|
|
275
285
|
# article.compiled_content(:snapshot => :pre) }) A proc that returns the
|
@@ -303,6 +313,7 @@ module Nanoc::Helpers
|
|
303
313
|
# Fill builder
|
304
314
|
builder.limit = params[:limit] || 5
|
305
315
|
builder.relevant_articles = params[:articles] || articles || []
|
316
|
+
builder.preserve_order = params.fetch(:preserve_order, false)
|
306
317
|
builder.content_proc = params[:content_proc] || ->(a) { a.compiled_content(snapshot: :pre) }
|
307
318
|
builder.excerpt_proc = params[:excerpt_proc] || ->(a) { a[:excerpt] }
|
308
319
|
builder.title = params[:title] || @item[:title] || @site.config[:title]
|
@@ -29,7 +29,7 @@ module Nanoc::Helpers
|
|
29
29
|
#
|
30
30
|
# @return [String] A hyperlinked list of tags for the given item
|
31
31
|
def tags_for(item, params = {})
|
32
|
-
base_url = params[:base_url]
|
32
|
+
base_url = params[:base_url] || 'http://technorati.com/tag/'
|
33
33
|
none_text = params[:none_text] || '(none)'
|
34
34
|
separator = params[:separator] || ', '
|
35
35
|
|
data/lib/nanoc/helpers/text.rb
CHANGED
data/lib/nanoc/version.rb
CHANGED
data/tasks/test.rake
CHANGED
@@ -12,7 +12,7 @@ def run_tests(dir_glob)
|
|
12
12
|
test_files = Dir["#{dir_glob}*_spec.rb"] + Dir["#{dir_glob}test_*.rb"]
|
13
13
|
test_files.each { |f| require f }
|
14
14
|
|
15
|
-
res =
|
15
|
+
res = Minitest.run(ENV['ARGS'].split)
|
16
16
|
exit(res) if res != 0
|
17
17
|
end
|
18
18
|
|
@@ -96,6 +96,14 @@ class Nanoc::ItemArrayTest < Nanoc::TestCase
|
|
96
96
|
assert_nil @items.at('/tenthousand/')
|
97
97
|
end
|
98
98
|
|
99
|
+
def test_regex
|
100
|
+
foo = Nanoc::Item.new('Item Foo', {}, '/foo/')
|
101
|
+
@items << foo
|
102
|
+
|
103
|
+
assert_equal [@one], @items[/n/]
|
104
|
+
assert_equal [@two, foo], @items[%r{o/}]
|
105
|
+
end
|
106
|
+
|
99
107
|
def test_less_than_less_than
|
100
108
|
assert_nil @items[2]
|
101
109
|
assert_nil @items['/foo/']
|
data/test/base/test_item_rep.rb
CHANGED
@@ -77,6 +77,57 @@ class Nanoc::ItemRepTest < Nanoc::TestCase
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
def test_compiled_content_with_moving_pre_snapshot
|
81
|
+
# Create rep
|
82
|
+
item = Nanoc::Item.new(
|
83
|
+
'blah blah', {}, '/',
|
84
|
+
binary: false
|
85
|
+
)
|
86
|
+
rep = Nanoc::ItemRep.new(item, nil)
|
87
|
+
rep.expects(:compiled?).returns(false)
|
88
|
+
rep.instance_eval { @content = { pre: 'pre!', last: 'last!' } }
|
89
|
+
|
90
|
+
# Check
|
91
|
+
assert_raises(Nanoc::Errors::UnmetDependency) do
|
92
|
+
rep.compiled_content(snapshot: :pre)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_compiled_content_with_non_moving_pre_snapshot
|
97
|
+
# Create rep
|
98
|
+
item = Nanoc::Item.new(
|
99
|
+
'blah blah', {}, '/',
|
100
|
+
binary: false
|
101
|
+
)
|
102
|
+
rep = Nanoc::ItemRep.new(item, nil)
|
103
|
+
rep.expects(:compiled?).returns(false)
|
104
|
+
rep.snapshots = [[:pre, true]]
|
105
|
+
rep.instance_eval { @content = { pre: 'pre!', post: 'post!', last: 'last!' } }
|
106
|
+
|
107
|
+
# Check
|
108
|
+
assert_equal 'pre!', rep.compiled_content(snapshot: :pre)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_compiled_content_with_final_pre_snapshot_in_layout
|
112
|
+
# Mock layout
|
113
|
+
layout = Nanoc::Layout.new(
|
114
|
+
%(BEFORE <%= @item_rep.compiled_content(snapshot: :pre) %> AFTER),
|
115
|
+
{},
|
116
|
+
'/somelayout/')
|
117
|
+
|
118
|
+
# Create item and item rep
|
119
|
+
item = Nanoc::Item.new(
|
120
|
+
'blah blah', {}, '/',
|
121
|
+
binary: false
|
122
|
+
)
|
123
|
+
rep = create_rep_for(item, :foo)
|
124
|
+
rep.assigns = { item_rep: rep }
|
125
|
+
|
126
|
+
# Run and check
|
127
|
+
rep.layout(layout, :erb, {})
|
128
|
+
assert_equal('BEFORE blah blah AFTER', rep.instance_eval { @content[:last] })
|
129
|
+
end
|
130
|
+
|
80
131
|
def test_filter
|
81
132
|
# Mock site
|
82
133
|
site = MiniTest::Mock.new
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class Nanoc::ItemRepRecorderProxyTest < Nanoc::TestCase
|
4
|
+
def test_double_names
|
5
|
+
proxy = Nanoc::ItemRepRecorderProxy.new(mock)
|
6
|
+
|
7
|
+
proxy.snapshot(:foo, stuff: :giraffe)
|
8
|
+
assert_raises(Nanoc::Errors::CannotCreateMultipleSnapshotsWithSameName) do
|
9
|
+
proxy.snapshot(:foo, stuff: :donkey)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_double_params
|
14
|
+
proxy = Nanoc::ItemRepRecorderProxy.new(mock)
|
15
|
+
|
16
|
+
proxy.snapshot(:foo)
|
17
|
+
proxy.snapshot(:bar)
|
18
|
+
end
|
19
|
+
end
|
data/test/base/test_rule.rb
CHANGED
@@ -12,4 +12,14 @@ class Nanoc::RuleTest < Nanoc::TestCase
|
|
12
12
|
def test_apply_to
|
13
13
|
# TODO: implement
|
14
14
|
end
|
15
|
+
|
16
|
+
def test_matches
|
17
|
+
regexp = %r</(.*)/(.*)/>
|
18
|
+
identifier = '/anything/else/'
|
19
|
+
expected = ['anything', 'else']
|
20
|
+
|
21
|
+
rule = Nanoc::Rule.new(regexp, :string, Proc.new {})
|
22
|
+
|
23
|
+
assert_equal expected, rule.send(:matches, identifier)
|
24
|
+
end
|
15
25
|
end
|