nanoc 4.8.18 → 4.8.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +6 -0
- data/lib/nanoc.rb +5 -0
- data/lib/nanoc/base/entities/context.rb +9 -1
- data/lib/nanoc/base/services/checksummer.rb +1 -1
- data/lib/nanoc/data_sources/filesystem.rb +3 -104
- data/lib/nanoc/data_sources/filesystem/parser.rb +78 -0
- data/lib/nanoc/data_sources/filesystem/tools.rb +39 -0
- data/lib/nanoc/rule_dsl.rb +15 -3
- data/lib/nanoc/rule_dsl/{recording_executor.rb → action_recorder.rb} +20 -5
- data/lib/nanoc/rule_dsl/action_sequence_calculator.rb +7 -12
- data/lib/nanoc/rule_dsl/compilation_rule.rb +23 -0
- data/lib/nanoc/rule_dsl/compilation_rule_context.rb +91 -0
- data/lib/nanoc/rule_dsl/compiler_dsl.rb +6 -9
- data/lib/nanoc/rule_dsl/routing_rule.rb +29 -0
- data/lib/nanoc/rule_dsl/routing_rule_context.rb +6 -0
- data/lib/nanoc/rule_dsl/rule.rb +7 -55
- data/lib/nanoc/rule_dsl/rule_context.rb +7 -83
- data/lib/nanoc/rule_dsl/rules_loader.rb +0 -1
- data/lib/nanoc/spec.rb +14 -0
- data/lib/nanoc/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77b1cd3570e8e94e5d17d18bf9954f0ac8d8a45e48f4e3d2f7d39cbdc8a2e3ff
|
4
|
+
data.tar.gz: a5a95e6ab7be8df7c016fdd659bac76734965ed9aed677110647ae7d0cfa19b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5860e580a17a5ed72590cb7c81eb6b6e1649e5c2973a322ed1ca544af0faa4a37de23343151a6dbbe730cd022b9d58f54feae6546c7f243e7c359bc2e3f1ea2a
|
7
|
+
data.tar.gz: e8642774bd3d54418ae6c78392dedca7eecbc80b2d06d7e83aa9a579ab35074a06de192420476b1ca7dfb48e29f2c7fc3b809925faedb23cb5522b89f170b9f0
|
data/NEWS.md
CHANGED
data/lib/nanoc.rb
CHANGED
@@ -27,6 +27,11 @@ module Nanoc
|
|
27
27
|
def self.on_windows?
|
28
28
|
RUBY_PLATFORM =~ /windows|bccwin|cygwin|djgpp|mingw|mswin|wince/i
|
29
29
|
end
|
30
|
+
|
31
|
+
# Similar to `nil` except that it can only be compared against using
|
32
|
+
# `UNDEFINED.equal?(x)`. Used in places where `nil` already has meaning, and
|
33
|
+
# thus cannot be used to mean the presence of nothing.
|
34
|
+
UNDEFINED = Object.new
|
30
35
|
end
|
31
36
|
|
32
37
|
# Load general requirements
|
@@ -51,7 +51,15 @@ module Nanoc::Int
|
|
51
51
|
|
52
52
|
def respond_to_missing?(method, include_all)
|
53
53
|
ivar_name = '@' + method.to_s
|
54
|
-
|
54
|
+
|
55
|
+
valid_ivar_name =
|
56
|
+
if defined?(Contracts)
|
57
|
+
ivar_name =~ /\A@[A-Za-z_]+\z/
|
58
|
+
else
|
59
|
+
true # probably good enough
|
60
|
+
end
|
61
|
+
|
62
|
+
(valid_ivar_name && instance_variable_defined?(ivar_name)) || super
|
55
63
|
end
|
56
64
|
|
57
65
|
def include(mod)
|
@@ -98,7 +98,7 @@ module Nanoc::Int
|
|
98
98
|
StringUpdateBehavior
|
99
99
|
when Nanoc::View
|
100
100
|
UnwrapUpdateBehavior
|
101
|
-
when Nanoc::RuleDSL::
|
101
|
+
when Nanoc::RuleDSL::CompilationRuleContext
|
102
102
|
RuleContextUpdateBehavior
|
103
103
|
when Nanoc::Int::Context
|
104
104
|
ContextUpdateBehavior
|
@@ -379,114 +379,13 @@ module Nanoc::DataSources
|
|
379
379
|
end
|
380
380
|
end
|
381
381
|
|
382
|
-
# @return [ParseResult]
|
383
382
|
def parse(content_filename, meta_filename)
|
384
|
-
|
385
|
-
|
386
|
-
else
|
387
|
-
parse_with_frontmatter(content_filename)
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
# @return [ParseResult]
|
392
|
-
def parse_with_separate_meta_filename(content_filename, meta_filename)
|
393
|
-
content = content_filename ? read(content_filename) : ''
|
394
|
-
meta_raw = read(meta_filename)
|
395
|
-
meta = parse_metadata(meta_raw, meta_filename)
|
396
|
-
ParseResult.new(content: content, attributes: meta, attributes_data: meta_raw)
|
397
|
-
end
|
398
|
-
|
399
|
-
SEPARATOR = /(-{5}|-{3})/.source
|
400
|
-
|
401
|
-
# @return [ParseResult]
|
402
|
-
def parse_with_frontmatter(content_filename)
|
403
|
-
data = read(content_filename)
|
404
|
-
|
405
|
-
if data !~ /\A#{SEPARATOR}\s*$/
|
406
|
-
return ParseResult.new(content: data, attributes: {}, attributes_data: '')
|
407
|
-
end
|
408
|
-
|
409
|
-
pieces = data.split(/^#{SEPARATOR}[ \t]*\r?\n?/, 3)
|
410
|
-
if pieces.size < 4
|
411
|
-
raise Errors::InvalidFormat.new(content_filename)
|
412
|
-
end
|
413
|
-
|
414
|
-
meta = parse_metadata(pieces[2], content_filename)
|
415
|
-
content = pieces[4]
|
416
|
-
|
417
|
-
ParseResult.new(content: content, attributes: meta, attributes_data: pieces[2])
|
418
|
-
end
|
419
|
-
|
420
|
-
# @return [Hash]
|
421
|
-
def parse_metadata(data, filename)
|
422
|
-
begin
|
423
|
-
meta = YAML.load(data) || {}
|
424
|
-
rescue => e
|
425
|
-
raise Errors::UnparseableMetadata.new(filename, e)
|
426
|
-
end
|
427
|
-
|
428
|
-
verify_meta(meta, filename)
|
429
|
-
|
430
|
-
meta
|
431
|
-
end
|
432
|
-
|
433
|
-
class ParseResult
|
434
|
-
attr_reader :content
|
435
|
-
attr_reader :attributes
|
436
|
-
attr_reader :attributes_data
|
437
|
-
|
438
|
-
def initialize(content:, attributes:, attributes_data:)
|
439
|
-
@content = content
|
440
|
-
@attributes = attributes
|
441
|
-
@attributes_data = attributes_data
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
def verify_meta(meta, filename)
|
446
|
-
return if meta.is_a?(Hash)
|
447
|
-
|
448
|
-
raise Errors::InvalidMetadata.new(filename, meta.class)
|
449
|
-
end
|
450
|
-
|
451
|
-
# Reads the content of the file with the given name and returns a string
|
452
|
-
# in UTF-8 encoding. The original encoding of the string is derived from
|
453
|
-
# the default external encoding, but this can be overridden by the
|
454
|
-
# “encoding” configuration attribute in the data source configuration.
|
455
|
-
def read(filename)
|
456
|
-
# Read
|
457
|
-
begin
|
458
|
-
data = File.read(filename)
|
459
|
-
rescue => e
|
460
|
-
raise Errors::FileUnreadable.new(filename, e)
|
461
|
-
end
|
462
|
-
|
463
|
-
# Set original encoding, if any
|
464
|
-
if @config && @config[:encoding]
|
465
|
-
original_encoding = Encoding.find(@config[:encoding])
|
466
|
-
data.force_encoding(@config[:encoding])
|
467
|
-
else
|
468
|
-
original_encoding = data.encoding
|
469
|
-
end
|
470
|
-
|
471
|
-
# Set encoding to UTF-8
|
472
|
-
begin
|
473
|
-
data.encode!('UTF-8')
|
474
|
-
rescue
|
475
|
-
raise Errors::InvalidEncoding.new(filename, original_encoding)
|
476
|
-
end
|
477
|
-
|
478
|
-
# Verify
|
479
|
-
unless data.valid_encoding?
|
480
|
-
raise Errors::InvalidEncoding.new(filename, original_encoding)
|
481
|
-
end
|
482
|
-
|
483
|
-
# Remove UTF-8 BOM (ugly)
|
484
|
-
data.delete!("\xEF\xBB\xBF")
|
485
|
-
|
486
|
-
data
|
383
|
+
parser = Parser.new(config: @config)
|
384
|
+
parser.call(content_filename, meta_filename)
|
487
385
|
end
|
488
386
|
end
|
489
387
|
end
|
490
388
|
|
491
389
|
require_relative 'filesystem/tools'
|
492
390
|
require_relative 'filesystem/errors'
|
391
|
+
require_relative 'filesystem/parser'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
class Nanoc::DataSources::Filesystem
|
5
|
+
class Parser
|
6
|
+
SEPARATOR = /(-{5}|-{3})/.source
|
7
|
+
|
8
|
+
class ParseResult
|
9
|
+
attr_reader :content
|
10
|
+
attr_reader :attributes
|
11
|
+
attr_reader :attributes_data
|
12
|
+
|
13
|
+
def initialize(content:, attributes:, attributes_data:)
|
14
|
+
@content = content
|
15
|
+
@attributes = attributes
|
16
|
+
@attributes_data = attributes_data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(config:)
|
21
|
+
@config = config
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [ParseResult]
|
25
|
+
def call(content_filename, meta_filename)
|
26
|
+
if meta_filename
|
27
|
+
parse_with_separate_meta_filename(content_filename, meta_filename)
|
28
|
+
else
|
29
|
+
parse_with_frontmatter(content_filename)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [ParseResult]
|
34
|
+
def parse_with_separate_meta_filename(content_filename, meta_filename)
|
35
|
+
content = content_filename ? Tools.read_file(content_filename, config: @config) : ''
|
36
|
+
meta_raw = Tools.read_file(meta_filename, config: @config)
|
37
|
+
meta = parse_metadata(meta_raw, meta_filename)
|
38
|
+
ParseResult.new(content: content, attributes: meta, attributes_data: meta_raw)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [ParseResult]
|
42
|
+
def parse_with_frontmatter(content_filename)
|
43
|
+
data = Tools.read_file(content_filename, config: @config)
|
44
|
+
|
45
|
+
if data !~ /\A#{SEPARATOR}\s*$/
|
46
|
+
return ParseResult.new(content: data, attributes: {}, attributes_data: '')
|
47
|
+
end
|
48
|
+
|
49
|
+
pieces = data.split(/^#{SEPARATOR}[ \t]*\r?\n?/, 3)
|
50
|
+
if pieces.size < 4
|
51
|
+
raise Errors::InvalidFormat.new(content_filename)
|
52
|
+
end
|
53
|
+
|
54
|
+
meta = parse_metadata(pieces[2], content_filename)
|
55
|
+
content = pieces[4]
|
56
|
+
|
57
|
+
ParseResult.new(content: content, attributes: meta, attributes_data: pieces[2])
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Hash]
|
61
|
+
def parse_metadata(data, filename)
|
62
|
+
begin
|
63
|
+
meta = YAML.load(data) || {}
|
64
|
+
rescue => e
|
65
|
+
raise Errors::UnparseableMetadata.new(filename, e)
|
66
|
+
end
|
67
|
+
|
68
|
+
verify_meta(meta, filename)
|
69
|
+
|
70
|
+
meta
|
71
|
+
end
|
72
|
+
|
73
|
+
def verify_meta(meta, filename)
|
74
|
+
return if meta.is_a?(Hash)
|
75
|
+
raise Errors::InvalidMetadata.new(filename, meta.class)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -148,5 +148,44 @@ class Nanoc::DataSources::Filesystem < Nanoc::DataSource
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
module_function :resolve_symlink
|
151
|
+
|
152
|
+
# Reads the content of the file with the given name and returns a string
|
153
|
+
# in UTF-8 encoding. The original encoding of the string is derived from
|
154
|
+
# the default external encoding, but this can be overridden by the
|
155
|
+
# “encoding” configuration attribute in the data source configuration.
|
156
|
+
def read_file(filename, config:)
|
157
|
+
# Read
|
158
|
+
begin
|
159
|
+
data = File.read(filename)
|
160
|
+
rescue => e
|
161
|
+
raise Errors::FileUnreadable.new(filename, e)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Set original encoding, if any
|
165
|
+
if config && config[:encoding]
|
166
|
+
original_encoding = Encoding.find(config[:encoding])
|
167
|
+
data.force_encoding(config[:encoding])
|
168
|
+
else
|
169
|
+
original_encoding = data.encoding
|
170
|
+
end
|
171
|
+
|
172
|
+
# Set encoding to UTF-8
|
173
|
+
begin
|
174
|
+
data.encode!('UTF-8')
|
175
|
+
rescue
|
176
|
+
raise Errors::InvalidEncoding.new(filename, original_encoding)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Verify
|
180
|
+
unless data.valid_encoding?
|
181
|
+
raise Errors::InvalidEncoding.new(filename, original_encoding)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Remove UTF-8 BOM (ugly)
|
185
|
+
data.delete!("\xEF\xBB\xBF")
|
186
|
+
|
187
|
+
data
|
188
|
+
end
|
189
|
+
module_function :read_file
|
151
190
|
end
|
152
191
|
end
|
data/lib/nanoc/rule_dsl.rb
CHANGED
@@ -1,10 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Nanoc
|
4
|
+
# @api private
|
5
|
+
module RuleDSL
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
3
9
|
require_relative 'rule_dsl/compiler_dsl'
|
4
10
|
require_relative 'rule_dsl/action_provider'
|
5
|
-
require_relative 'rule_dsl/
|
6
|
-
require_relative 'rule_dsl/rule_context'
|
11
|
+
require_relative 'rule_dsl/action_recorder'
|
7
12
|
require_relative 'rule_dsl/action_sequence_calculator'
|
8
|
-
require_relative 'rule_dsl/rule'
|
9
13
|
require_relative 'rule_dsl/rules_collection'
|
10
14
|
require_relative 'rule_dsl/rules_loader'
|
15
|
+
|
16
|
+
require_relative 'rule_dsl/rule_context'
|
17
|
+
require_relative 'rule_dsl/compilation_rule_context'
|
18
|
+
require_relative 'rule_dsl/routing_rule_context'
|
19
|
+
|
20
|
+
require_relative 'rule_dsl/rule'
|
21
|
+
require_relative 'rule_dsl/compilation_rule'
|
22
|
+
require_relative 'rule_dsl/routing_rule'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Nanoc
|
4
4
|
module RuleDSL
|
5
|
-
class
|
5
|
+
class ActionRecorder
|
6
6
|
include Nanoc::Int::ContractsSupport
|
7
7
|
|
8
8
|
contract Nanoc::Int::ItemRep => C::Any
|
@@ -12,6 +12,7 @@ module Nanoc
|
|
12
12
|
@any_layouts = false
|
13
13
|
@last_snapshot = false
|
14
14
|
@pre_snapshot = false
|
15
|
+
@skip_routing_rule = false
|
15
16
|
end
|
16
17
|
|
17
18
|
def inspect
|
@@ -36,10 +37,19 @@ module Nanoc
|
|
36
37
|
@any_layouts = true
|
37
38
|
end
|
38
39
|
|
39
|
-
|
40
|
-
contract Symbol, C::KeywordArgs[path: C::Optional[
|
41
|
-
def snapshot(snapshot_name, path:
|
42
|
-
@
|
40
|
+
MaybePathlike = C::Or[nil, Nanoc::UNDEFINED, String, Nanoc::Identifier]
|
41
|
+
contract Symbol, C::KeywordArgs[path: C::Optional[MaybePathlike]] => nil
|
42
|
+
def snapshot(snapshot_name, path: Nanoc::UNDEFINED)
|
43
|
+
@skip_routing_rule = path.nil?
|
44
|
+
|
45
|
+
path =
|
46
|
+
if Nanoc::UNDEFINED.equal?(path) || path.nil?
|
47
|
+
nil
|
48
|
+
else
|
49
|
+
path.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
@action_sequence_builder.add_snapshot(snapshot_name, path)
|
43
53
|
case snapshot_name
|
44
54
|
when :last
|
45
55
|
@last_snapshot = true
|
@@ -59,6 +69,11 @@ module Nanoc
|
|
59
69
|
@any_layouts
|
60
70
|
end
|
61
71
|
|
72
|
+
contract C::None => C::Bool
|
73
|
+
def skip_routing_rule?
|
74
|
+
@skip_routing_rule
|
75
|
+
end
|
76
|
+
|
62
77
|
contract C::None => C::Bool
|
63
78
|
def last_snapshot?
|
64
79
|
@last_snapshot
|
@@ -1,10 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Nanoc::RuleDSL
|
4
|
-
# Calculates action sequences for objects that can be run through a rule (item
|
5
|
-
# representations and layouts).
|
6
|
-
#
|
7
|
-
# @api private
|
8
4
|
class ActionSequenceCalculator
|
9
5
|
DDMemoize.activate(self)
|
10
6
|
|
@@ -60,20 +56,20 @@ module Nanoc::RuleDSL
|
|
60
56
|
view_context =
|
61
57
|
Nanoc::ViewContextForPreCompilation.new(items: @site.items)
|
62
58
|
|
63
|
-
|
59
|
+
recorder = Nanoc::RuleDSL::ActionRecorder.new(rep)
|
64
60
|
rule = @rules_collection.compilation_rule_for(rep)
|
65
61
|
|
66
62
|
unless rule
|
67
63
|
raise NoActionSequenceForItemRepException.new(rep)
|
68
64
|
end
|
69
65
|
|
70
|
-
|
71
|
-
rule.apply_to(rep,
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
recorder.snapshot(:raw)
|
67
|
+
rule.apply_to(rep, recorder: recorder, site: @site, view_context: view_context)
|
68
|
+
recorder.snapshot(:post) if recorder.any_layouts?
|
69
|
+
recorder.snapshot(:last) unless recorder.last_snapshot?
|
70
|
+
recorder.snapshot(:pre) unless recorder.pre_snapshot?
|
75
71
|
|
76
|
-
copy_paths_from_routing_rules(compact_snapshots(
|
72
|
+
copy_paths_from_routing_rules(compact_snapshots(recorder.action_sequence), rep: rep)
|
77
73
|
end
|
78
74
|
|
79
75
|
# @param [Nanoc::Int::Layout] layout
|
@@ -138,7 +134,6 @@ module Nanoc::RuleDSL
|
|
138
134
|
basic_path =
|
139
135
|
routing_rule.apply_to(
|
140
136
|
rep,
|
141
|
-
executor: nil,
|
142
137
|
site: @site,
|
143
138
|
view_context: view_context,
|
144
139
|
)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc::RuleDSL
|
4
|
+
class CompilationRule < Rule
|
5
|
+
include Nanoc::Int::ContractsSupport
|
6
|
+
|
7
|
+
contract Nanoc::Int::ItemRep, C::KeywordArgs[
|
8
|
+
site: Nanoc::Int::Site,
|
9
|
+
recorder: Nanoc::RuleDSL::ActionRecorder,
|
10
|
+
view_context: Nanoc::ViewContextForPreCompilation,
|
11
|
+
] => C::Any
|
12
|
+
def apply_to(rep, site:, recorder:, view_context:)
|
13
|
+
context = Nanoc::RuleDSL::CompilationRuleContext.new(
|
14
|
+
rep: rep,
|
15
|
+
recorder: recorder,
|
16
|
+
site: site,
|
17
|
+
view_context: view_context,
|
18
|
+
)
|
19
|
+
|
20
|
+
context.instance_exec(matches(rep.item.identifier), &@block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc::RuleDSL
|
4
|
+
class CompilationRuleContext < RuleContext
|
5
|
+
include Nanoc::Int::ContractsSupport
|
6
|
+
|
7
|
+
contract C::KeywordArgs[
|
8
|
+
rep: Nanoc::Int::ItemRep,
|
9
|
+
site: Nanoc::Int::Site,
|
10
|
+
recorder: Nanoc::RuleDSL::ActionRecorder,
|
11
|
+
view_context: Nanoc::ViewContextForPreCompilation,
|
12
|
+
] => C::Any
|
13
|
+
def initialize(rep:, site:, recorder:, view_context:)
|
14
|
+
@_recorder = recorder
|
15
|
+
|
16
|
+
super(rep: rep, site: site, view_context: view_context)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Filters the current representation (calls {Nanoc::Int::ItemRep#filter} with
|
20
|
+
# the given arguments on the rep).
|
21
|
+
#
|
22
|
+
# @see Nanoc::Int::ItemRep#filter
|
23
|
+
#
|
24
|
+
# @param [Symbol] filter_name The name of the filter to run the item
|
25
|
+
# representations' content through
|
26
|
+
#
|
27
|
+
# @param [Hash] filter_args The filter arguments that should be passed to
|
28
|
+
# the filter's #run method
|
29
|
+
#
|
30
|
+
# @return [void]
|
31
|
+
def filter(filter_name, filter_args = {})
|
32
|
+
@_recorder.filter(filter_name, filter_args)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Layouts the current representation (calls {Nanoc::Int::ItemRep#layout} with
|
36
|
+
# the given arguments on the rep).
|
37
|
+
#
|
38
|
+
# @see Nanoc::Int::ItemRep#layout
|
39
|
+
#
|
40
|
+
# @param [String] layout_identifier The identifier of the layout the item
|
41
|
+
# should be laid out with
|
42
|
+
#
|
43
|
+
# @return [void]
|
44
|
+
def layout(layout_identifier, extra_filter_args = nil)
|
45
|
+
@_recorder.layout(layout_identifier, extra_filter_args)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Creates a snapshot of the current compiled item content. Calls
|
49
|
+
# {Nanoc::Int::ItemRep#snapshot} with the given arguments on the rep.
|
50
|
+
#
|
51
|
+
# @see Nanoc::Int::ItemRep#snapshot
|
52
|
+
#
|
53
|
+
# @param [Symbol] snapshot_name The name of the snapshot to create
|
54
|
+
#
|
55
|
+
# @param [String, nil] path
|
56
|
+
#
|
57
|
+
# @return [void]
|
58
|
+
def snapshot(snapshot_name, path: Nanoc::UNDEFINED)
|
59
|
+
@_recorder.snapshot(snapshot_name, path: path)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates a snapshot named :last the current compiled item content, with
|
63
|
+
# the given path. This is a convenience method for {#snapshot}.
|
64
|
+
#
|
65
|
+
# @see #snapshot
|
66
|
+
#
|
67
|
+
# @param [String] path
|
68
|
+
#
|
69
|
+
# @return [void]
|
70
|
+
def write(arg)
|
71
|
+
@_write_snapshot_counter ||= 0
|
72
|
+
snapshot_name = "_#{@_write_snapshot_counter}".to_sym
|
73
|
+
@_write_snapshot_counter += 1
|
74
|
+
|
75
|
+
case arg
|
76
|
+
when String, Nanoc::Identifier, nil
|
77
|
+
snapshot(snapshot_name, path: arg)
|
78
|
+
when Hash
|
79
|
+
if arg.key?(:ext)
|
80
|
+
ext = arg[:ext].sub(/\A\./, '')
|
81
|
+
path = @item.identifier.without_exts + '.' + ext
|
82
|
+
snapshot(snapshot_name, path: path)
|
83
|
+
else
|
84
|
+
raise ArgumentError, 'Cannot call #write this way (need path or :ext)'
|
85
|
+
end
|
86
|
+
else
|
87
|
+
raise ArgumentError, 'Cannot call #write this way (need path or :ext)'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Nanoc::RuleDSL
|
4
|
-
# Contains methods that will be executed by the site’s `Rules` file.
|
5
|
-
#
|
6
|
-
# @api private
|
7
4
|
class CompilerDSL < Nanoc::Int::Context
|
8
5
|
# The current rules filename.
|
9
6
|
#
|
@@ -74,7 +71,7 @@ module Nanoc::RuleDSL
|
|
74
71
|
def compile(identifier, rep: :default, &block)
|
75
72
|
raise ArgumentError.new('#compile requires a block') unless block_given?
|
76
73
|
|
77
|
-
rule = Nanoc::RuleDSL::
|
74
|
+
rule = Nanoc::RuleDSL::CompilationRule.new(create_pattern(identifier), rep, block)
|
78
75
|
@rules_collection.add_item_compilation_rule(rule)
|
79
76
|
end
|
80
77
|
|
@@ -114,7 +111,7 @@ module Nanoc::RuleDSL
|
|
114
111
|
def route(identifier, rep: :default, snapshot: :last, &block)
|
115
112
|
raise ArgumentError.new('#route requires a block') unless block_given?
|
116
113
|
|
117
|
-
rule = Nanoc::RuleDSL::
|
114
|
+
rule = Nanoc::RuleDSL::RoutingRule.new(create_pattern(identifier), rep, block, snapshot_name: snapshot)
|
118
115
|
@rules_collection.add_item_routing_rule(rule)
|
119
116
|
end
|
120
117
|
|
@@ -173,7 +170,7 @@ module Nanoc::RuleDSL
|
|
173
170
|
raise ArgumentError.new('#passthrough does not require a block') if block_given?
|
174
171
|
|
175
172
|
compilation_block = proc {}
|
176
|
-
compilation_rule = Nanoc::RuleDSL::
|
173
|
+
compilation_rule = Nanoc::RuleDSL::CompilationRule.new(create_pattern(identifier), rep, compilation_block)
|
177
174
|
@rules_collection.add_item_compilation_rule(compilation_rule)
|
178
175
|
|
179
176
|
# Create routing rule
|
@@ -188,7 +185,7 @@ module Nanoc::RuleDSL
|
|
188
185
|
item[:extension].nil? || (item[:content_filename].nil? && item.identifier =~ %r{#{item[:extension]}/$}) ? item.identifier.chop : item.identifier.chop + '.' + item[:extension]
|
189
186
|
end
|
190
187
|
end
|
191
|
-
routing_rule = Nanoc::RuleDSL::
|
188
|
+
routing_rule = Nanoc::RuleDSL::RoutingRule.new(create_pattern(identifier), rep, routing_block, snapshot_name: :last)
|
192
189
|
@rules_collection.add_item_routing_rule(routing_rule)
|
193
190
|
end
|
194
191
|
|
@@ -213,10 +210,10 @@ module Nanoc::RuleDSL
|
|
213
210
|
def ignore(identifier, rep: :default)
|
214
211
|
raise ArgumentError.new('#ignore does not require a block') if block_given?
|
215
212
|
|
216
|
-
compilation_rule = Nanoc::RuleDSL::
|
213
|
+
compilation_rule = Nanoc::RuleDSL::CompilationRule.new(create_pattern(identifier), rep, proc {})
|
217
214
|
@rules_collection.add_item_compilation_rule(compilation_rule)
|
218
215
|
|
219
|
-
routing_rule = Nanoc::RuleDSL::
|
216
|
+
routing_rule = Nanoc::RuleDSL::RoutingRule.new(create_pattern(identifier), rep, proc {}, snapshot_name: :last)
|
220
217
|
@rules_collection.add_item_routing_rule(routing_rule)
|
221
218
|
end
|
222
219
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc::RuleDSL
|
4
|
+
class RoutingRule < Rule
|
5
|
+
include Nanoc::Int::ContractsSupport
|
6
|
+
|
7
|
+
contract C::None => C::Maybe[Symbol]
|
8
|
+
attr_reader :snapshot_name
|
9
|
+
|
10
|
+
contract Nanoc::Int::Pattern, Symbol, Proc, C::KeywordArgs[snapshot_name: C::Optional[Symbol]] => C::Any
|
11
|
+
def initialize(pattern, rep_name, block, snapshot_name: nil)
|
12
|
+
super(pattern, rep_name, block)
|
13
|
+
|
14
|
+
@snapshot_name = snapshot_name
|
15
|
+
end
|
16
|
+
|
17
|
+
contract Nanoc::Int::ItemRep, C::KeywordArgs[
|
18
|
+
site: Nanoc::Int::Site,
|
19
|
+
view_context: Nanoc::ViewContextForPreCompilation,
|
20
|
+
] => C::Any
|
21
|
+
def apply_to(rep, site:, view_context:)
|
22
|
+
context = Nanoc::RuleDSL::RoutingRuleContext.new(
|
23
|
+
rep: rep, site: site, view_context: view_context,
|
24
|
+
)
|
25
|
+
|
26
|
+
context.instance_exec(matches(rep.item.identifier), &@block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/nanoc/rule_dsl/rule.rb
CHANGED
@@ -1,77 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Nanoc::RuleDSL
|
4
|
-
# Contains the processing information for a item.
|
5
|
-
#
|
6
|
-
# @api private
|
7
4
|
class Rule
|
8
5
|
include Nanoc::Int::ContractsSupport
|
9
6
|
|
10
|
-
|
11
|
-
# using this rule
|
7
|
+
contract C::None => Symbol
|
12
8
|
attr_reader :rep_name
|
13
9
|
|
14
|
-
|
15
|
-
# Ignored for compilation rules, but used for routing rules.
|
16
|
-
attr_reader :snapshot_name
|
17
|
-
|
10
|
+
contract C::None => Nanoc::Int::Pattern
|
18
11
|
attr_reader :pattern
|
19
12
|
|
20
|
-
|
21
|
-
|
22
|
-
# item rep as its argument.
|
23
|
-
#
|
24
|
-
# @param [Nanoc::Int::Pattern] pattern
|
25
|
-
#
|
26
|
-
# @param [String, Symbol] rep_name The name of the item representation
|
27
|
-
# where this rule can be applied to
|
28
|
-
#
|
29
|
-
# @param [Proc] block A block that will be called when matching items are
|
30
|
-
# compiled
|
31
|
-
#
|
32
|
-
# @param [Symbol, nil] snapshot_name The name of the snapshot this rule will
|
33
|
-
# apply to. Ignored for compilation rules, but used for routing rules.
|
34
|
-
def initialize(pattern, rep_name, block, snapshot_name: nil)
|
13
|
+
contract Nanoc::Int::Pattern, Symbol, Proc => C::Any
|
14
|
+
def initialize(pattern, rep_name, block)
|
35
15
|
@pattern = pattern
|
36
16
|
@rep_name = rep_name.to_sym
|
37
|
-
@snapshot_name = snapshot_name
|
38
17
|
@block = block
|
39
18
|
end
|
40
19
|
|
41
|
-
|
42
|
-
#
|
43
|
-
# @return [Boolean] true if this rule can be applied to the given item
|
44
|
-
# rep, false otherwise
|
20
|
+
contract Nanoc::Int::Item => C::Bool
|
45
21
|
def applicable_to?(item)
|
46
22
|
@pattern.match?(item.identifier)
|
47
23
|
end
|
48
24
|
|
49
|
-
|
50
|
-
|
51
|
-
executor: C::Or[nil, Nanoc::Int::Executor, Nanoc::RuleDSL::RecordingExecutor],
|
52
|
-
view_context: Nanoc::ViewContextForPreCompilation,
|
53
|
-
] => C::Any
|
54
|
-
def apply_to(rep, site:, executor:, view_context:)
|
55
|
-
# FIXME: allowing executor to be nil is ugly
|
56
|
-
|
57
|
-
context = Nanoc::RuleDSL::RuleContext.new(
|
58
|
-
rep: rep,
|
59
|
-
executor: executor,
|
60
|
-
site: site,
|
61
|
-
view_context: view_context,
|
62
|
-
)
|
63
|
-
|
64
|
-
context.instance_exec(matches(rep.item.identifier), &@block)
|
65
|
-
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
|
69
|
-
# Matches the rule regexp against items identifier and gives back group
|
70
|
-
# captures if any
|
71
|
-
#
|
72
|
-
# @param [String] identifier Identifier to capture groups for
|
73
|
-
#
|
74
|
-
# @return [nil, Array] Captured groups, if any
|
25
|
+
# @api private
|
26
|
+
contract Nanoc::Identifier => C::Or[nil, C::ArrayOf[String]]
|
75
27
|
def matches(identifier)
|
76
28
|
@pattern.captures(identifier)
|
77
29
|
end
|
@@ -1,19 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Nanoc::RuleDSL
|
4
|
-
# Provides a context in which compilation and routing rules can be executed.
|
5
|
-
# It provides access to the item representation that is being compiled or
|
6
|
-
# routed.
|
7
|
-
#
|
8
|
-
# @api private
|
9
4
|
class RuleContext < Nanoc::Int::Context
|
10
|
-
|
11
|
-
# @param [Nanoc::Int::Site] site
|
12
|
-
# @param [Nanoc::Int::Executor, Nanoc::RuleDSL::RecordingExecutor] executor
|
13
|
-
# @param [Nanoc::ViewContextForCompilation] view_context
|
14
|
-
def initialize(rep:, site:, executor:, view_context:)
|
15
|
-
@_executor = executor
|
5
|
+
include Nanoc::Int::ContractsSupport
|
16
6
|
|
7
|
+
contract C::KeywordArgs[
|
8
|
+
rep: Nanoc::Int::ItemRep,
|
9
|
+
site: Nanoc::Int::Site,
|
10
|
+
view_context: Nanoc::ViewContextForPreCompilation,
|
11
|
+
] => C::Any
|
12
|
+
def initialize(rep:, site:, view_context:)
|
17
13
|
super({
|
18
14
|
item: Nanoc::BasicItemView.new(rep.item, view_context),
|
19
15
|
rep: Nanoc::BasicItemRepView.new(rep, view_context),
|
@@ -23,77 +19,5 @@ module Nanoc::RuleDSL
|
|
23
19
|
config: Nanoc::ConfigView.new(site.config, view_context),
|
24
20
|
})
|
25
21
|
end
|
26
|
-
|
27
|
-
# Filters the current representation (calls {Nanoc::Int::ItemRep#filter} with
|
28
|
-
# the given arguments on the rep).
|
29
|
-
#
|
30
|
-
# @see Nanoc::Int::ItemRep#filter
|
31
|
-
#
|
32
|
-
# @param [Symbol] filter_name The name of the filter to run the item
|
33
|
-
# representations' content through
|
34
|
-
#
|
35
|
-
# @param [Hash] filter_args The filter arguments that should be passed to
|
36
|
-
# the filter's #run method
|
37
|
-
#
|
38
|
-
# @return [void]
|
39
|
-
def filter(filter_name, filter_args = {})
|
40
|
-
@_executor.filter(filter_name, filter_args)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Layouts the current representation (calls {Nanoc::Int::ItemRep#layout} with
|
44
|
-
# the given arguments on the rep).
|
45
|
-
#
|
46
|
-
# @see Nanoc::Int::ItemRep#layout
|
47
|
-
#
|
48
|
-
# @param [String] layout_identifier The identifier of the layout the item
|
49
|
-
# should be laid out with
|
50
|
-
#
|
51
|
-
# @return [void]
|
52
|
-
def layout(layout_identifier, extra_filter_args = nil)
|
53
|
-
@_executor.layout(layout_identifier, extra_filter_args)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Creates a snapshot of the current compiled item content. Calls
|
57
|
-
# {Nanoc::Int::ItemRep#snapshot} with the given arguments on the rep.
|
58
|
-
#
|
59
|
-
# @see Nanoc::Int::ItemRep#snapshot
|
60
|
-
#
|
61
|
-
# @param [Symbol] snapshot_name The name of the snapshot to create
|
62
|
-
#
|
63
|
-
# @param [String, nil] path
|
64
|
-
#
|
65
|
-
# @return [void]
|
66
|
-
def snapshot(snapshot_name, path: nil)
|
67
|
-
@_executor.snapshot(snapshot_name, path: path)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Creates a snapshot named :last the current compiled item content, with
|
71
|
-
# the given path. This is a convenience method for {#snapshot}.
|
72
|
-
#
|
73
|
-
# @see #snapshot
|
74
|
-
#
|
75
|
-
# @param [String] path
|
76
|
-
#
|
77
|
-
# @return [void]
|
78
|
-
def write(arg)
|
79
|
-
@_write_snapshot_counter ||= 0
|
80
|
-
snapshot_name = "_#{@_write_snapshot_counter}".to_sym
|
81
|
-
@_write_snapshot_counter += 1
|
82
|
-
|
83
|
-
case arg
|
84
|
-
when String, Nanoc::Identifier
|
85
|
-
snapshot(snapshot_name, path: arg)
|
86
|
-
when Hash
|
87
|
-
if arg.key?(:ext)
|
88
|
-
ext = arg[:ext].sub(/\A\./, '')
|
89
|
-
path = @item.identifier.without_exts + '.' + ext
|
90
|
-
snapshot(snapshot_name, path: path)
|
91
|
-
else
|
92
|
-
raise ArgumentError, 'Cannot call #write this way (need path or :ext)'
|
93
|
-
end
|
94
|
-
else
|
95
|
-
raise ArgumentError, 'Cannot call #write this way (need path or :ext)'
|
96
|
-
end
|
97
|
-
end
|
98
22
|
end
|
99
23
|
end
|
data/lib/nanoc/spec.rb
CHANGED
@@ -24,6 +24,20 @@ module Nanoc
|
|
24
24
|
def skip_unless_have_command(cmd)
|
25
25
|
skip "Could not find external command \"#{cmd}\"" unless command?(cmd)
|
26
26
|
end
|
27
|
+
|
28
|
+
def sleep_until(max: 3.0)
|
29
|
+
start = Time.now
|
30
|
+
loop do
|
31
|
+
diff = (Time.now - start).to_f
|
32
|
+
if diff > max
|
33
|
+
raise "Waited for #{diff}s for condition to become true, but it never did"
|
34
|
+
end
|
35
|
+
|
36
|
+
break if yield
|
37
|
+
|
38
|
+
sleep 0.1
|
39
|
+
end
|
40
|
+
end
|
27
41
|
end
|
28
42
|
|
29
43
|
class HelperContext
|
data/lib/nanoc/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nanoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.8.
|
4
|
+
version: 4.8.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Defreyne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -314,6 +314,7 @@ files:
|
|
314
314
|
- lib/nanoc/data_sources.rb
|
315
315
|
- lib/nanoc/data_sources/filesystem.rb
|
316
316
|
- lib/nanoc/data_sources/filesystem/errors.rb
|
317
|
+
- lib/nanoc/data_sources/filesystem/parser.rb
|
317
318
|
- lib/nanoc/data_sources/filesystem/tools.rb
|
318
319
|
- lib/nanoc/deploying.rb
|
319
320
|
- lib/nanoc/deploying/deployer.rb
|
@@ -375,9 +376,13 @@ files:
|
|
375
376
|
- lib/nanoc/helpers/xml_sitemap.rb
|
376
377
|
- lib/nanoc/rule_dsl.rb
|
377
378
|
- lib/nanoc/rule_dsl/action_provider.rb
|
379
|
+
- lib/nanoc/rule_dsl/action_recorder.rb
|
378
380
|
- lib/nanoc/rule_dsl/action_sequence_calculator.rb
|
381
|
+
- lib/nanoc/rule_dsl/compilation_rule.rb
|
382
|
+
- lib/nanoc/rule_dsl/compilation_rule_context.rb
|
379
383
|
- lib/nanoc/rule_dsl/compiler_dsl.rb
|
380
|
-
- lib/nanoc/rule_dsl/
|
384
|
+
- lib/nanoc/rule_dsl/routing_rule.rb
|
385
|
+
- lib/nanoc/rule_dsl/routing_rule_context.rb
|
381
386
|
- lib/nanoc/rule_dsl/rule.rb
|
382
387
|
- lib/nanoc/rule_dsl/rule_context.rb
|
383
388
|
- lib/nanoc/rule_dsl/rules_collection.rb
|