nanoc-core 4.11.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|