nanoc 4.8.18 → 4.8.19
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/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
|