nanoc-core 4.11.1
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 +7 -0
- data/NEWS.md +3 -0
- data/README.md +3 -0
- data/lib/nanoc/core/binary_content.rb +12 -0
- data/lib/nanoc/core/checksummer.rb +287 -0
- data/lib/nanoc/core/code_snippet.rb +57 -0
- data/lib/nanoc/core/configuration-schema.json +122 -0
- data/lib/nanoc/core/configuration.rb +206 -0
- data/lib/nanoc/core/content.rb +46 -0
- data/lib/nanoc/core/context.rb +70 -0
- data/lib/nanoc/core/contracts_support.rb +131 -0
- data/lib/nanoc/core/core_ext/array.rb +54 -0
- data/lib/nanoc/core/core_ext/hash.rb +58 -0
- data/lib/nanoc/core/core_ext/string.rb +20 -0
- data/lib/nanoc/core/data_source.rb +170 -0
- data/lib/nanoc/core/directed_graph.rb +195 -0
- data/lib/nanoc/core/document.rb +124 -0
- data/lib/nanoc/core/error.rb +9 -0
- data/lib/nanoc/core/identifiable_collection.rb +142 -0
- data/lib/nanoc/core/identifier.rb +218 -0
- data/lib/nanoc/core/item.rb +11 -0
- data/lib/nanoc/core/item_collection.rb +15 -0
- data/lib/nanoc/core/item_rep.rb +92 -0
- data/lib/nanoc/core/layout.rb +11 -0
- data/lib/nanoc/core/layout_collection.rb +15 -0
- data/lib/nanoc/core/lazy_value.rb +38 -0
- data/lib/nanoc/core/notification_center.rb +97 -0
- data/lib/nanoc/core/pattern.rb +37 -0
- data/lib/nanoc/core/processing_action.rb +23 -0
- data/lib/nanoc/core/processing_actions/filter.rb +40 -0
- data/lib/nanoc/core/processing_actions/layout.rb +40 -0
- data/lib/nanoc/core/processing_actions/snapshot.rb +50 -0
- data/lib/nanoc/core/processing_actions.rb +12 -0
- data/lib/nanoc/core/regexp_pattern.rb +28 -0
- data/lib/nanoc/core/snapshot_def.rb +22 -0
- data/lib/nanoc/core/string_pattern.rb +29 -0
- data/lib/nanoc/core/temp_filename_factory.rb +53 -0
- data/lib/nanoc/core/textual_content.rb +41 -0
- data/lib/nanoc/core/version.rb +7 -0
- data/lib/nanoc/core.rb +60 -0
- data/lib/nanoc-core.rb +3 -0
- metadata +152 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class ItemRep
|
6
|
+
include Nanoc::Core::ContractsSupport
|
7
|
+
|
8
|
+
contract C::None => C::Bool
|
9
|
+
attr_accessor :compiled
|
10
|
+
alias compiled? compiled
|
11
|
+
|
12
|
+
contract C::None => C::HashOf[Symbol => C::IterOf[String]]
|
13
|
+
attr_reader :raw_paths
|
14
|
+
|
15
|
+
contract C::None => C::HashOf[Symbol => C::IterOf[String]]
|
16
|
+
attr_reader :paths
|
17
|
+
|
18
|
+
contract C::None => Nanoc::Core::Item
|
19
|
+
attr_reader :item
|
20
|
+
|
21
|
+
contract C::None => Symbol
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
contract C::None => C::IterOf[C::Named['Nanoc::Core::SnapshotDef']]
|
25
|
+
attr_accessor :snapshot_defs
|
26
|
+
|
27
|
+
contract C::None => C::Bool
|
28
|
+
attr_accessor :modified
|
29
|
+
alias modified? modified
|
30
|
+
|
31
|
+
contract Nanoc::Core::Item, Symbol => C::Any
|
32
|
+
def initialize(item, name)
|
33
|
+
# Set primary attributes
|
34
|
+
@item = item
|
35
|
+
@name = name
|
36
|
+
|
37
|
+
# Set default attributes
|
38
|
+
@raw_paths = {}
|
39
|
+
@paths = {}
|
40
|
+
@snapshot_defs = []
|
41
|
+
|
42
|
+
# Reset flags
|
43
|
+
@compiled = false
|
44
|
+
@modified = false
|
45
|
+
end
|
46
|
+
|
47
|
+
contract C::HashOf[Symbol => C::IterOf[C::AbsolutePathString]] => C::HashOf[Symbol => C::IterOf[C::AbsolutePathString]]
|
48
|
+
def raw_paths=(val)
|
49
|
+
@raw_paths = val
|
50
|
+
end
|
51
|
+
|
52
|
+
contract C::HashOf[Symbol => C::IterOf[String]] => C::HashOf[Symbol => C::IterOf[String]]
|
53
|
+
def paths=(val)
|
54
|
+
@paths = val
|
55
|
+
end
|
56
|
+
|
57
|
+
contract Symbol => C::Bool
|
58
|
+
def snapshot?(name)
|
59
|
+
snapshot_defs.any? { |sd| sd.name == name }
|
60
|
+
end
|
61
|
+
|
62
|
+
contract C::KeywordArgs[snapshot: C::Optional[Symbol]] => C::Maybe[String]
|
63
|
+
# Returns the item rep’s raw path. It includes the path to the output
|
64
|
+
# directory and the full filename.
|
65
|
+
def raw_path(snapshot: :last)
|
66
|
+
@raw_paths.fetch(snapshot, []).first
|
67
|
+
end
|
68
|
+
|
69
|
+
contract C::KeywordArgs[snapshot: C::Optional[Symbol]] => C::Maybe[String]
|
70
|
+
# Returns the item rep’s path, as used when being linked to. It starts
|
71
|
+
# with a slash and it is relative to the output directory. It does not
|
72
|
+
# include the path to the output directory. It will not include the
|
73
|
+
# filename if the filename is an index filename.
|
74
|
+
def path(snapshot: :last)
|
75
|
+
@paths.fetch(snapshot, []).first
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns an object that can be used for uniquely identifying objects.
|
79
|
+
def reference
|
80
|
+
"item_rep:#{item.identifier}:#{name}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s
|
84
|
+
"#{item.identifier} (rep name #{name.inspect})"
|
85
|
+
end
|
86
|
+
|
87
|
+
def inspect
|
88
|
+
"<#{self.class} name=\"#{name}\" raw_path=\"#{raw_path}\" item.identifier=\"#{item.identifier}\">"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class LayoutCollection < IdentifiableCollection
|
6
|
+
def initialize(config, objects = [])
|
7
|
+
initialize_basic(config, objects, 'layouts')
|
8
|
+
end
|
9
|
+
|
10
|
+
def reference
|
11
|
+
'layouts'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
# Holds a value that might be generated lazily.
|
6
|
+
class LazyValue
|
7
|
+
include Nanoc::Core::ContractsSupport
|
8
|
+
|
9
|
+
# Takes a value or a proc to generate the value
|
10
|
+
def initialize(value_or_proc)
|
11
|
+
@value = { raw: value_or_proc }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the value, generated when needed
|
15
|
+
def value
|
16
|
+
if @value.key?(:raw)
|
17
|
+
value = @value.delete(:raw)
|
18
|
+
@value[:final] = value.respond_to?(:call) ? value.call : value
|
19
|
+
@value.__nanoc_freeze_recursively if frozen?
|
20
|
+
end
|
21
|
+
@value[:final]
|
22
|
+
end
|
23
|
+
|
24
|
+
contract C::Func[C::Any => C::Any] => self
|
25
|
+
# Returns a new lazy value that will apply the given transformation when the value is requested.
|
26
|
+
def map
|
27
|
+
self.class.new(-> { yield(value) })
|
28
|
+
end
|
29
|
+
|
30
|
+
contract C::None => self
|
31
|
+
def freeze
|
32
|
+
super
|
33
|
+
@value.__nanoc_freeze_recursively unless @value[:raw]
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
# Provides a way to send notifications between objects. It allows blocks
|
6
|
+
# associated with a certain notification name to be registered; these blocks
|
7
|
+
# will be called when the notification with the given name is posted.
|
8
|
+
#
|
9
|
+
# It is a slightly different implementation of the Observer pattern; the
|
10
|
+
# table of subscribers is not stored in the observable object itself, but in
|
11
|
+
# the notification center.
|
12
|
+
class NotificationCenter
|
13
|
+
DONE = Object.new
|
14
|
+
SYNC = Object.new
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@thread = nil
|
18
|
+
|
19
|
+
# name => observers dictionary
|
20
|
+
@notifications = Hash.new { |hash, name| hash[name] = [] }
|
21
|
+
|
22
|
+
@queue = Queue.new
|
23
|
+
|
24
|
+
@sync_queue = Queue.new
|
25
|
+
on(SYNC, self) { @sync_queue << true }
|
26
|
+
end
|
27
|
+
|
28
|
+
def start
|
29
|
+
@thread ||= Thread.new do
|
30
|
+
Thread.current.abort_on_exception = true
|
31
|
+
|
32
|
+
loop do
|
33
|
+
elem = @queue.pop
|
34
|
+
break if DONE.equal?(elem)
|
35
|
+
|
36
|
+
name = elem[0]
|
37
|
+
args = elem[1]
|
38
|
+
|
39
|
+
@notifications[name].each do |observer|
|
40
|
+
observer[:block].call(*args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def stop
|
47
|
+
@queue << DONE
|
48
|
+
@thread.join
|
49
|
+
end
|
50
|
+
|
51
|
+
def on(name, id = nil, &block)
|
52
|
+
@notifications[name] << { id: id, block: block }
|
53
|
+
end
|
54
|
+
|
55
|
+
def remove(name, id)
|
56
|
+
@notifications[name].reject! { |i| i[:id] == id }
|
57
|
+
end
|
58
|
+
|
59
|
+
def post(name, *args)
|
60
|
+
@queue << [name, args]
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def sync
|
65
|
+
post(SYNC)
|
66
|
+
@sync_queue.pop
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
def instance
|
71
|
+
@_instance ||= new.tap(&:start)
|
72
|
+
end
|
73
|
+
|
74
|
+
def on(name, id = nil, &block)
|
75
|
+
instance.on(name, id, &block)
|
76
|
+
end
|
77
|
+
|
78
|
+
def post(name, *args)
|
79
|
+
instance.post(name, *args)
|
80
|
+
end
|
81
|
+
|
82
|
+
def remove(name, id)
|
83
|
+
instance.remove(name, id)
|
84
|
+
end
|
85
|
+
|
86
|
+
def reset
|
87
|
+
instance.stop
|
88
|
+
@_instance = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def sync
|
92
|
+
instance.sync
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class Pattern
|
6
|
+
include Nanoc::Core::ContractsSupport
|
7
|
+
|
8
|
+
contract C::Any => self
|
9
|
+
def self.from(obj)
|
10
|
+
case obj
|
11
|
+
when Nanoc::Core::StringPattern, Nanoc::Core::RegexpPattern
|
12
|
+
obj
|
13
|
+
when String
|
14
|
+
Nanoc::Core::StringPattern.new(obj)
|
15
|
+
when Regexp
|
16
|
+
Nanoc::Core::RegexpPattern.new(obj)
|
17
|
+
when Symbol
|
18
|
+
Nanoc::Core::StringPattern.new(obj.to_s)
|
19
|
+
else
|
20
|
+
raise ArgumentError, "Do not know how to convert `#{obj.inspect}` into a Nanoc::Pattern"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(_obj)
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
|
28
|
+
def match?(_identifier)
|
29
|
+
raise NotImplementedError
|
30
|
+
end
|
31
|
+
|
32
|
+
def captures(_identifier)
|
33
|
+
raise NotImplementedError
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class ProcessingAction
|
6
|
+
def serialize
|
7
|
+
raise NotImplementedError.new('Nanoc::ProcessingAction subclasses must implement #serialize and #to_s')
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
raise NotImplementedError.new('Nanoc::ProcessingAction subclasses must implement #serialize and #to_s')
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
format(
|
16
|
+
'<%s %s>',
|
17
|
+
self.class.to_s,
|
18
|
+
serialize[1..-1].map(&:inspect).join(', '),
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
module ProcessingActions
|
6
|
+
class Filter < Nanoc::Core::ProcessingAction
|
7
|
+
# filter :foo
|
8
|
+
# filter :foo, params
|
9
|
+
|
10
|
+
attr_reader :filter_name
|
11
|
+
attr_reader :params
|
12
|
+
|
13
|
+
def initialize(filter_name, params)
|
14
|
+
@filter_name = filter_name
|
15
|
+
@params = params
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize
|
19
|
+
[:filter, @filter_name, Nanoc::Core::Checksummer.calc(@params)]
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"filter #{@filter_name.inspect}, #{@params.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def hash
|
27
|
+
self.class.hash ^ filter_name.hash ^ params.hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
self.class == other.class && filter_name == other.filter_name && params == other.params
|
32
|
+
end
|
33
|
+
|
34
|
+
def eql?(other)
|
35
|
+
self == other
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
module ProcessingActions
|
6
|
+
class Layout < Nanoc::Core::ProcessingAction
|
7
|
+
# layout '/foo.erb'
|
8
|
+
# layout '/foo.erb', params
|
9
|
+
|
10
|
+
attr_reader :layout_identifier
|
11
|
+
attr_reader :params
|
12
|
+
|
13
|
+
def initialize(layout_identifier, params)
|
14
|
+
@layout_identifier = layout_identifier
|
15
|
+
@params = params
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize
|
19
|
+
[:layout, @layout_identifier, Nanoc::Core::Checksummer.calc(@params)]
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"layout #{@layout_identifier.inspect}, #{@params.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def hash
|
27
|
+
self.class.hash ^ layout_identifier.hash ^ params.hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
self.class == other.class && layout_identifier == other.layout_identifier && params == other.params
|
32
|
+
end
|
33
|
+
|
34
|
+
def eql?(other)
|
35
|
+
self == other
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
module ProcessingActions
|
6
|
+
class Snapshot < Nanoc::Core::ProcessingAction
|
7
|
+
# snapshot :before_layout
|
8
|
+
# snapshot :before_layout, path: '/about.md'
|
9
|
+
|
10
|
+
include Nanoc::Core::ContractsSupport
|
11
|
+
|
12
|
+
attr_reader :snapshot_names
|
13
|
+
attr_reader :paths
|
14
|
+
|
15
|
+
contract C::IterOf[Symbol], C::IterOf[String] => C::Any
|
16
|
+
def initialize(snapshot_names, paths)
|
17
|
+
@snapshot_names = snapshot_names
|
18
|
+
@paths = paths
|
19
|
+
end
|
20
|
+
|
21
|
+
contract C::None => Array
|
22
|
+
def serialize
|
23
|
+
[:snapshot, @snapshot_names, true, @paths]
|
24
|
+
end
|
25
|
+
|
26
|
+
contract C::KeywordArgs[snapshot_names: C::Optional[C::IterOf[Symbol]], paths: C::Optional[C::IterOf[String]]] => self
|
27
|
+
def update(snapshot_names: [], paths: [])
|
28
|
+
self.class.new(@snapshot_names + snapshot_names.to_a, @paths + paths.to_a)
|
29
|
+
end
|
30
|
+
|
31
|
+
contract C::None => String
|
32
|
+
def to_s
|
33
|
+
"snapshot #{@snapshot_names.inspect}, paths: #{@paths.inspect}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def hash
|
37
|
+
self.class.hash ^ snapshot_names.hash ^ paths.hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
self.class == other.class && snapshot_names == other.snapshot_names && paths == other.paths
|
42
|
+
end
|
43
|
+
|
44
|
+
def eql?(other)
|
45
|
+
self == other
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
module ProcessingActions
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'nanoc/core/processing_actions/filter'
|
11
|
+
require 'nanoc/core/processing_actions/layout'
|
12
|
+
require 'nanoc/core/processing_actions/snapshot'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class RegexpPattern < Pattern
|
6
|
+
contract Regexp => C::Any
|
7
|
+
def initialize(regexp)
|
8
|
+
@regexp = regexp
|
9
|
+
end
|
10
|
+
|
11
|
+
contract C::Or[Nanoc::Core::Identifier, String] => C::Bool
|
12
|
+
def match?(identifier)
|
13
|
+
(identifier.to_s =~ @regexp) != nil
|
14
|
+
end
|
15
|
+
|
16
|
+
contract C::Or[Nanoc::Core::Identifier, String] => C::Maybe[C::ArrayOf[String]]
|
17
|
+
def captures(identifier)
|
18
|
+
matches = @regexp.match(identifier.to_s)
|
19
|
+
matches&.captures
|
20
|
+
end
|
21
|
+
|
22
|
+
contract C::None => String
|
23
|
+
def to_s
|
24
|
+
@regexp.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class SnapshotDef
|
6
|
+
include Nanoc::Core::ContractsSupport
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :binary
|
10
|
+
|
11
|
+
contract Symbol, C::KeywordArgs[binary: C::Optional[C::Bool]] => C::Any
|
12
|
+
def initialize(name, binary:)
|
13
|
+
@name = name
|
14
|
+
@binary = binary
|
15
|
+
end
|
16
|
+
|
17
|
+
def binary?
|
18
|
+
@binary
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class StringPattern < Pattern
|
6
|
+
MATCH_OPTS = File::FNM_PATHNAME | File::FNM_EXTGLOB
|
7
|
+
|
8
|
+
contract String => C::Any
|
9
|
+
def initialize(string)
|
10
|
+
@string = string
|
11
|
+
end
|
12
|
+
|
13
|
+
contract C::Or[Nanoc::Core::Identifier, String] => C::Bool
|
14
|
+
def match?(identifier)
|
15
|
+
File.fnmatch(@string, identifier.to_s, MATCH_OPTS)
|
16
|
+
end
|
17
|
+
|
18
|
+
contract C::Or[Nanoc::Core::Identifier, String] => nil
|
19
|
+
def captures(_identifier)
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
contract C::None => String
|
24
|
+
def to_s
|
25
|
+
@string
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class TempFilenameFactory
|
6
|
+
# @return [String] The root directory for all temporary filenames
|
7
|
+
attr_reader :root_dir
|
8
|
+
|
9
|
+
# @return [Nanoc::Core::TempFilenameFactory] A common instance
|
10
|
+
def self.instance
|
11
|
+
@instance ||= new
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@counts = {}
|
16
|
+
@root_dir = Dir.mktmpdir('nanoc')
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [String] prefix A string prefix to include in the temporary
|
20
|
+
# filename, often the type of filename being provided.
|
21
|
+
#
|
22
|
+
# @return [String] A new unused filename
|
23
|
+
def create(prefix)
|
24
|
+
count = @counts.fetch(prefix, 0)
|
25
|
+
@counts[prefix] = count + 1
|
26
|
+
|
27
|
+
dirname = File.join(@root_dir, prefix)
|
28
|
+
filename = File.join(@root_dir, prefix, count.to_s)
|
29
|
+
|
30
|
+
FileUtils.mkdir_p(dirname)
|
31
|
+
|
32
|
+
filename
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param [String] prefix A string prefix that indicates which temporary
|
36
|
+
# filenames should be deleted.
|
37
|
+
#
|
38
|
+
# @return [void]
|
39
|
+
def cleanup(prefix)
|
40
|
+
path = File.join(@root_dir, prefix)
|
41
|
+
if File.exist?(path)
|
42
|
+
FileUtils.rm_rf(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
@counts.delete(prefix)
|
46
|
+
|
47
|
+
if @counts.empty? && File.directory?(@root_dir)
|
48
|
+
FileUtils.rm_rf(@root_dir)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class TextualContent < Content
|
6
|
+
contract C::None => String
|
7
|
+
def string
|
8
|
+
@string.value
|
9
|
+
end
|
10
|
+
|
11
|
+
contract C::Or[String, Proc], C::KeywordArgs[filename: C::Optional[C::Maybe[String]]] => C::Any
|
12
|
+
def initialize(string, filename: nil)
|
13
|
+
super(filename)
|
14
|
+
@string = Nanoc::Core::LazyValue.new(string)
|
15
|
+
end
|
16
|
+
|
17
|
+
contract C::None => self
|
18
|
+
def freeze
|
19
|
+
super
|
20
|
+
@string.freeze
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
contract C::None => C::Bool
|
25
|
+
def binary?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
contract C::None => Array
|
30
|
+
def marshal_dump
|
31
|
+
[filename, string]
|
32
|
+
end
|
33
|
+
|
34
|
+
contract Array => C::Any
|
35
|
+
def marshal_load(array)
|
36
|
+
@filename = array[0]
|
37
|
+
@string = Nanoc::Core::LazyValue.new(array[1])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|