yarrow 0.7.1 → 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.gitignore +1 -0
- data/lib/yarrow/config.rb +9 -7
- data/lib/yarrow/configuration.rb +4 -4
- data/lib/yarrow/console_runner.rb +5 -8
- data/lib/yarrow/content/expansion.rb +16 -0
- data/lib/yarrow/content/expansion_strategy.rb +51 -0
- data/lib/yarrow/content/graph.rb +16 -3
- data/lib/yarrow/content/manifest.rb +61 -0
- data/lib/yarrow/content/model.rb +46 -0
- data/lib/yarrow/content/policy.rb +48 -0
- data/lib/yarrow/content/resource.rb +29 -0
- data/lib/yarrow/content/source.rb +70 -3
- data/lib/yarrow/content/tree_expansion.rb +92 -0
- data/lib/yarrow/generator.rb +49 -19
- data/lib/yarrow/output/result.rb +13 -0
- data/lib/yarrow/output/web/indexed_file.rb +7 -1
- data/lib/yarrow/schema/definitions.rb +30 -0
- data/lib/yarrow/schema/dictionary.rb +49 -0
- data/lib/yarrow/schema/entity.rb +51 -0
- data/lib/yarrow/schema/types.rb +73 -0
- data/lib/yarrow/schema/value.rb +46 -0
- data/lib/yarrow/schema.rb +28 -119
- data/lib/yarrow/symbols.rb +15 -0
- data/lib/yarrow/version.rb +1 -1
- data/lib/yarrow.rb +15 -4
- data/yarrow.gemspec +2 -2
- metadata +22 -12
- data/lib/yarrow/content/collection_expander.rb +0 -218
- data/lib/yarrow/content/content_type.rb +0 -42
- data/lib/yarrow/content/source_collector.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c49c3ae295fd127f7533a0af4c543d5315a2929a580a21b6b4c26379e519490
|
4
|
+
data.tar.gz: 6867e3004c89dc7362a83378f3b0d55a14803d513cc77445c7893a31ffb4e4bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0056694b64f9ac4d000e85341570b4a5b630f27b5de15d5dcf12eeae1dc3625368abfd1d65a6c0a26f9793cbd6993e076c7e46d76ef97007874e8dddfd75c7af'
|
7
|
+
data.tar.gz: fa5469997f6e674f3f2b1daf8bbc525637b2cbb2db7b9a8a1d494c85b1ce4d2725753ece2a2d114a905b994fe96f99e9db09178fa6f92483d4ee5d6208a500ad
|
data/.github/workflows/ruby.yml
CHANGED
data/.gitignore
CHANGED
data/lib/yarrow/config.rb
CHANGED
@@ -42,19 +42,21 @@ module Yarrow
|
|
42
42
|
:root_dir
|
43
43
|
)
|
44
44
|
|
45
|
-
# Top level root config namespace.
|
46
|
-
#
|
45
|
+
# Top level root config namespace.
|
46
|
+
#
|
47
|
+
# `content_dir` and `output_dir` are placeholders and should be overriden
|
48
|
+
# with more fine-grained config for web and book outputs in future.
|
47
49
|
#
|
48
50
|
# Additional server config is optional and only needed if running the dev
|
49
51
|
# server locally.
|
50
52
|
#
|
51
53
|
# TODO: meta should be union of Type::Optional and Config::Meta
|
52
54
|
Instance = Yarrow::Schema::Value.new(
|
53
|
-
|
54
|
-
|
55
|
-
output_dir:
|
56
|
-
meta:
|
57
|
-
server:
|
55
|
+
project_dir: :path,
|
56
|
+
content_dir: :path,
|
57
|
+
output_dir: :path,
|
58
|
+
meta: :any,
|
59
|
+
server: :any
|
58
60
|
)
|
59
61
|
end
|
60
62
|
end
|
data/lib/yarrow/configuration.rb
CHANGED
@@ -52,13 +52,13 @@ module Yarrow
|
|
52
52
|
# automated as part of the schema types or a default value should be
|
53
53
|
# generated here (eg: `"#{Dir.pwd}/docs"`)
|
54
54
|
out_dir_or_string = config[:output_dir] || ""
|
55
|
-
source_dir_or_string = config[:
|
56
|
-
content_dir_or_string = config[:
|
55
|
+
source_dir_or_string = config[:project_dir] || ""
|
56
|
+
content_dir_or_string = config[:content_dir] || ""
|
57
57
|
|
58
58
|
Yarrow::Config::Instance.new(
|
59
59
|
output_dir: Pathname.new(File.expand_path(out_dir_or_string)),
|
60
|
-
|
61
|
-
|
60
|
+
project_dir: Pathname.new(File.expand_path(source_dir_or_string)),
|
61
|
+
content_dir: Pathname.new(File.expand_path(content_dir_or_string)),
|
62
62
|
meta: meta_obj,
|
63
63
|
server: server_obj
|
64
64
|
)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module Yarrow
|
2
|
-
|
3
2
|
class ConsoleRunner
|
4
3
|
|
5
4
|
SUCCESS = 0
|
@@ -100,7 +99,6 @@ module Yarrow
|
|
100
99
|
end
|
101
100
|
|
102
101
|
def normalize_theme_path
|
103
|
-
|
104
102
|
# noop
|
105
103
|
end
|
106
104
|
|
@@ -139,12 +137,11 @@ module Yarrow
|
|
139
137
|
@options.has_key? option
|
140
138
|
end
|
141
139
|
|
142
|
-
def
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
# noop
|
140
|
+
def run_generation_process
|
141
|
+
generator = Generator.new(@config)
|
142
|
+
generator.process do |manifest|
|
143
|
+
p manifest
|
144
|
+
end
|
148
145
|
end
|
149
146
|
|
150
147
|
def print_header
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
class Expansion
|
4
|
+
def initialize(model)
|
5
|
+
@model = model
|
6
|
+
end
|
7
|
+
|
8
|
+
def expand(graph)
|
9
|
+
@model.each_policy do |policy|
|
10
|
+
strategy = TreeExpansion.new(graph)
|
11
|
+
strategy.expand(policy)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
class ExpansionStrategy
|
4
|
+
include Yarrow::Tools::FrontMatter
|
5
|
+
|
6
|
+
attr_reader :graph
|
7
|
+
|
8
|
+
def initialize(graph)
|
9
|
+
@graph = graph
|
10
|
+
end
|
11
|
+
|
12
|
+
# Extract collection level configuration/metadata from the root node for
|
13
|
+
# this content type.
|
14
|
+
def extract_metadata(node, type)
|
15
|
+
# TODO: support _index or _slug convention as well
|
16
|
+
meta_file = node.out(slug: type.to_s).first
|
17
|
+
|
18
|
+
if meta_file
|
19
|
+
# Process metadata and add it to the collection node
|
20
|
+
# TODO: pass in content converter object
|
21
|
+
# TODO: index/body content by default if extracted from frontmatter
|
22
|
+
body, data = process_content(meta_file.props[:entry])
|
23
|
+
else
|
24
|
+
# Otherwise, assume default collection behaviour
|
25
|
+
data = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Generate a default title if not provided in metadata
|
29
|
+
unless data.key?(:title)
|
30
|
+
data[:title] = type.to_s.capitalize
|
31
|
+
end
|
32
|
+
|
33
|
+
data
|
34
|
+
end
|
35
|
+
|
36
|
+
# Workaround for handling meta and content source in multiple files or a single
|
37
|
+
# file with front matter.
|
38
|
+
def process_content(path)
|
39
|
+
case path.extname
|
40
|
+
when '.htm', '.md'
|
41
|
+
read_split_content(path.to_s, symbolize_keys: true)
|
42
|
+
# when '.md'
|
43
|
+
# body, data = read_split_content(path.to_s, symbolize_keys: true)
|
44
|
+
# [Kramdown::Document.new(body).to_html, data]
|
45
|
+
when '.yml'
|
46
|
+
[nil, YAML.load(File.read(path.to_s), symbolize_names: true)]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/yarrow/content/graph.rb
CHANGED
@@ -2,9 +2,12 @@ module Yarrow
|
|
2
2
|
module Content
|
3
3
|
# A directed graph of every element of content in the project.
|
4
4
|
class Graph
|
5
|
-
# Construct a graph collected from
|
5
|
+
# Construct a graph collected from files and directories in the configured
|
6
|
+
# content directory.
|
7
|
+
#
|
8
|
+
# @return [Yarrow::Content::Graph]
|
6
9
|
def self.from_source(config)
|
7
|
-
new(
|
10
|
+
new(Source.collect(config.content_dir), config)
|
8
11
|
end
|
9
12
|
|
10
13
|
attr_reader :graph, :config
|
@@ -15,7 +18,7 @@ module Yarrow
|
|
15
18
|
end
|
16
19
|
|
17
20
|
def expand_pages
|
18
|
-
expander = Yarrow::Content::
|
21
|
+
expander = Yarrow::Content::Expansion.new(Yarrow::Content::Model.new)
|
19
22
|
expander.expand(graph)
|
20
23
|
end
|
21
24
|
|
@@ -28,6 +31,16 @@ module Yarrow
|
|
28
31
|
def directories
|
29
32
|
graph.nodes(:directory)
|
30
33
|
end
|
34
|
+
|
35
|
+
# List of mapped content object collections
|
36
|
+
def collections
|
37
|
+
graph.nodes(:collection)
|
38
|
+
end
|
39
|
+
|
40
|
+
# List of mapped content object items
|
41
|
+
def items
|
42
|
+
graph.nodes(:item)
|
43
|
+
end
|
31
44
|
end
|
32
45
|
end
|
33
46
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
class Manifest
|
4
|
+
def self.build(graph)
|
5
|
+
manifest = new
|
6
|
+
|
7
|
+
graph.n(:collection).each do |collection|
|
8
|
+
|
9
|
+
unless collection.props[:content_only]
|
10
|
+
manifest.add_document(collection_context(collection))
|
11
|
+
end
|
12
|
+
|
13
|
+
unless collection.props[:index_only]
|
14
|
+
collection.out(:item).each do |item|
|
15
|
+
#if item[:entity].status.to_sym == :published
|
16
|
+
manifest.add_document(item_context(item))
|
17
|
+
#end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
manifest
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :documents, :assets
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@documents = []
|
29
|
+
@assets = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.collection_context(collection)
|
33
|
+
Yarrow::Output::Context.new(
|
34
|
+
parent: collection.in(:collection).first,
|
35
|
+
name: collection.props[:name],
|
36
|
+
#url: collection.props[:url],
|
37
|
+
title: collection.props[:title],
|
38
|
+
type: collection.props[:type]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.item_context(item)
|
43
|
+
Yarrow::Output::Context.new(
|
44
|
+
parent: item.in(:collection).first,
|
45
|
+
name: item.props[:name],
|
46
|
+
#url: item.props[:url],
|
47
|
+
title: item.props[:title],
|
48
|
+
type: item.props[:type]
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_document(document)
|
53
|
+
@documents << document
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_asset(asset)
|
57
|
+
@assets << asset
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
ContentSpec = Yarrow::Schema::Value.new(:namespace, :model) do
|
4
|
+
def to_world
|
5
|
+
"world"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
ContentPolicy = Yarrow::Schema::Value.new(
|
10
|
+
:dir,
|
11
|
+
:file,
|
12
|
+
:expansion,
|
13
|
+
:container,
|
14
|
+
:record
|
15
|
+
)
|
16
|
+
|
17
|
+
class Model
|
18
|
+
def initialize(spec=nil, namespace=nil)
|
19
|
+
@namespace = []
|
20
|
+
@namespace << namespace unless namespace.nil?
|
21
|
+
|
22
|
+
@policies = if spec.nil?
|
23
|
+
spec = {
|
24
|
+
root: ContentPolicy.new(
|
25
|
+
expansion: :tree,
|
26
|
+
dir: "*",
|
27
|
+
file: "*.md",
|
28
|
+
:container => :pages,
|
29
|
+
:record => :page
|
30
|
+
)
|
31
|
+
}
|
32
|
+
else
|
33
|
+
spec.model
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def each_policy(&block)
|
38
|
+
@policies.each_value(&block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def policy_for(policy_key)
|
42
|
+
@policies[policy_key]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
class Policy
|
4
|
+
Options = Yarrow::Schema::Value.new(
|
5
|
+
:container,
|
6
|
+
:entity,
|
7
|
+
:extensions,
|
8
|
+
:match_path
|
9
|
+
)
|
10
|
+
|
11
|
+
DEFAULT_EXTENSIONS = [".md", ".yml", ".htm"]
|
12
|
+
|
13
|
+
DEFAULT_MATCH_PATH = "."
|
14
|
+
|
15
|
+
def self.from_name(name)
|
16
|
+
new(Options.new(container: name.to_sym))
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(properties)
|
20
|
+
unless properties.respond_to?(:container) || properties.respond_to?(:entity)
|
21
|
+
raise "Must provide a container name or entity name"
|
22
|
+
end
|
23
|
+
|
24
|
+
@properties = properties
|
25
|
+
end
|
26
|
+
|
27
|
+
def container
|
28
|
+
return @properties.container if @properties.container
|
29
|
+
Yarrow::Symbols.to_plural(@properties.entity)
|
30
|
+
end
|
31
|
+
|
32
|
+
def entity
|
33
|
+
return @properties.entity if @properties.entity
|
34
|
+
Yarrow::Symbols.to_singular(@properties.container)
|
35
|
+
end
|
36
|
+
|
37
|
+
def extensions
|
38
|
+
return @properties.extensions if @properties.extensions
|
39
|
+
DEFAULT_EXTENSIONS
|
40
|
+
end
|
41
|
+
|
42
|
+
def match_path
|
43
|
+
return @properties.match_path if @properties.match_path
|
44
|
+
DEFAULT_MATCH_PATH
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
class Resource < Schema::Entity
|
4
|
+
attribute :id, :string
|
5
|
+
attribute :name, :string
|
6
|
+
attribute :title, :string
|
7
|
+
attribute :url, :string
|
8
|
+
attribute :content, :string
|
9
|
+
|
10
|
+
def self.from_frontmatter_url(data, url_field)
|
11
|
+
new({
|
12
|
+
id: data[:id],
|
13
|
+
name: data[:name],
|
14
|
+
title: data[:title],
|
15
|
+
content: data[:content],
|
16
|
+
url: data[url_field]
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_template_url(data, template, &block)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_source_path(data, &block)
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,10 +1,77 @@
|
|
1
1
|
module Yarrow
|
2
2
|
module Content
|
3
|
+
# Collects a digraph of all directories and files underneath the given input
|
4
|
+
# directory.
|
3
5
|
class Source
|
4
|
-
|
6
|
+
def self.collect(input_dir)
|
7
|
+
Mementus::Graph.new(is_mutable: true) do
|
8
|
+
root = create_node do |root|
|
9
|
+
root.label = :root
|
10
|
+
end
|
5
11
|
|
6
|
-
|
7
|
-
|
12
|
+
root_dir_entry = Pathname.new(input_dir)
|
13
|
+
|
14
|
+
root_dir = create_node do |dir|
|
15
|
+
dir.label = :directory
|
16
|
+
dir.props = {
|
17
|
+
name: root_dir_entry.basename.to_s,
|
18
|
+
path: root_dir_entry.to_s,
|
19
|
+
entry: root_dir_entry
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
create_edge do |child|
|
24
|
+
child.label = :child
|
25
|
+
child.from = root.id
|
26
|
+
child.to = root_dir.id
|
27
|
+
end
|
28
|
+
|
29
|
+
directories = {
|
30
|
+
root_dir_entry.to_s => root_dir.id
|
31
|
+
}
|
32
|
+
|
33
|
+
Pathname.glob("#{input_dir}/**/**").each do |entry|
|
34
|
+
if entry.directory?
|
35
|
+
content_node = create_node do |dir|
|
36
|
+
dir.label = :directory
|
37
|
+
# dir.props[:name] = entry.basename.to_s
|
38
|
+
# dir.props[:slug] = entry.basename.to_s
|
39
|
+
# dir.props[:path] = entry.to_s
|
40
|
+
# dir.props[:entry] = entry
|
41
|
+
dir.props = {
|
42
|
+
name: entry.basename.to_s,
|
43
|
+
path: entry.to_s,
|
44
|
+
entry: entry
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
directories[entry.to_s] = content_node.id
|
49
|
+
else
|
50
|
+
content_node = create_node do |file|
|
51
|
+
file.label = :file
|
52
|
+
# file.props[:name] = entry.basename.to_s
|
53
|
+
# file.props[:slug] = entry.basename.sub_ext('').to_s
|
54
|
+
# file.props[:path] = entry.to_s
|
55
|
+
# file.props[:entry] = entry
|
56
|
+
|
57
|
+
file.props = {
|
58
|
+
name: entry.basename.to_s,
|
59
|
+
ext: entry.extname.to_s,
|
60
|
+
path: entry.to_s,
|
61
|
+
entry: entry
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if directories.key?(entry.dirname.to_s)
|
67
|
+
create_edge do |edge|
|
68
|
+
edge.label = :child
|
69
|
+
edge.from = directories[entry.dirname.to_s]
|
70
|
+
edge.to = content_node
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
8
75
|
end
|
9
76
|
end
|
10
77
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
class TreeExpansion < ExpansionStrategy
|
4
|
+
def expand(policy)
|
5
|
+
#p graph.n(:root).out(:directory).to_a.count
|
6
|
+
#policy.match()
|
7
|
+
|
8
|
+
#p graph.n(:root).out(:directory).first.props[:name]
|
9
|
+
|
10
|
+
expand_impl(policy)
|
11
|
+
end
|
12
|
+
|
13
|
+
def expand_impl(policy)
|
14
|
+
type = policy.container
|
15
|
+
|
16
|
+
# If match path represents entire content dir, then include the entire
|
17
|
+
# content dir instead of scanning from a subfolder matching the name of
|
18
|
+
# the collection.
|
19
|
+
#start_node = if policy.match_path == "."
|
20
|
+
start_node = if true
|
21
|
+
graph.n(:root)
|
22
|
+
else
|
23
|
+
graph.n(:root).out(name: type.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Extract metadata from given start node
|
27
|
+
collection_metadata = extract_metadata(start_node, type)
|
28
|
+
|
29
|
+
# Collect all nested collections in the subgraph for this content type
|
30
|
+
subcollections = {}
|
31
|
+
item_links = []
|
32
|
+
index = nil
|
33
|
+
|
34
|
+
# Scan and collect all nested files from the root
|
35
|
+
start_node.depth_first.each do |node|
|
36
|
+
if node.label == :directory
|
37
|
+
# Create a collection node representing a collection of documents
|
38
|
+
index = graph.create_node do |collection_node|
|
39
|
+
collection_node.label = :collection
|
40
|
+
collection_node.props[:type] = type
|
41
|
+
collection_node.props[:name] = node.props[:name]
|
42
|
+
|
43
|
+
# TODO: title needs to be defined from metadata
|
44
|
+
collection_node.props[:title] = node.props[:name].capitalize
|
45
|
+
end
|
46
|
+
|
47
|
+
# Add this collection id to the lookup table for edge construction
|
48
|
+
subcollections[node.props[:path]] = index
|
49
|
+
|
50
|
+
# Join the collection to its parent
|
51
|
+
unless node.props[:slug] == type.to_s || !subcollections.key?(node.props[:entry].parent.to_s)
|
52
|
+
graph.create_edge do |edge|
|
53
|
+
edge.label = :child
|
54
|
+
edge.from = subcollections[node.props[:entry].parent.to_s].id
|
55
|
+
edge.to = index.id
|
56
|
+
end
|
57
|
+
end
|
58
|
+
elsif node.label == :file
|
59
|
+
body, meta = process_content(node.props[:entry])
|
60
|
+
|
61
|
+
# Create an item node representing a file mapped to a unique content object
|
62
|
+
item = graph.create_node do |item_node|
|
63
|
+
item_node.label = :item
|
64
|
+
item_node.props[:type] = policy.record
|
65
|
+
item_node.props[:name] = node.props[:entry].basename(node.props[:entry].extname).to_s
|
66
|
+
item_node.props[:body] = body if body
|
67
|
+
item_node.props[:title] = meta[:title] if meta
|
68
|
+
# TODO: better handling of metadata on node props
|
69
|
+
end
|
70
|
+
|
71
|
+
# We may not have an expanded node for the parent collection if this is a
|
72
|
+
# preorder traversal so save it for later
|
73
|
+
item_links << {
|
74
|
+
parent_path: node.props[:entry].parent.to_s,
|
75
|
+
item_id: item.id
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Once all files and directories have been expanded, connect all the child
|
81
|
+
# edges between collections and items
|
82
|
+
item_links.each do |item_link|
|
83
|
+
graph.create_edge do |edge|
|
84
|
+
edge.label = :child
|
85
|
+
edge.from = subcollections[item_link[:parent_path]].id
|
86
|
+
edge.to = item_link[:item_id]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/yarrow/generator.rb
CHANGED
@@ -1,27 +1,57 @@
|
|
1
1
|
module Yarrow
|
2
|
+
class ScanSource < Process::StepProcessor
|
3
|
+
accepts Config::Instance
|
4
|
+
provides Content::Graph
|
5
|
+
|
6
|
+
def step(config)
|
7
|
+
Yarrow::Content::Graph.from_source(config)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class ExpandCollections < Process::StepProcessor
|
12
|
+
accepts Content::Graph
|
13
|
+
provides Content::Graph
|
14
|
+
|
15
|
+
def step(content)
|
16
|
+
expander = Content::Expansion.new(Yarrow::Content::Model.new)
|
17
|
+
expander.expand(content.graph)
|
18
|
+
content
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class FlattenManifest < Process::StepProcessor
|
23
|
+
accepts Content::Graph
|
24
|
+
provides Content::Manifest
|
25
|
+
|
26
|
+
def step(content)
|
27
|
+
Content::Manifest.build(content.graph)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class BuildOutput < Process::StepProcessor
|
32
|
+
accepts Content::Manifest
|
33
|
+
provides Output::Result
|
34
|
+
end
|
2
35
|
|
3
36
|
# Generates documentation from a model.
|
4
|
-
#
|
5
|
-
# Subclasses of Generator need to override the template methods,
|
6
|
-
# to specify a particular file structure to output.
|
7
37
|
class Generator
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@target = target
|
12
|
-
@site_tree = site_tree
|
38
|
+
def initialize(config)
|
39
|
+
@config = config
|
40
|
+
@workflow = Process::Workflow.new(config)
|
13
41
|
end
|
14
|
-
|
15
|
-
def
|
16
|
-
|
17
|
-
|
42
|
+
|
43
|
+
def process(&block)
|
44
|
+
workflow.connect(ScanSource.new)
|
45
|
+
workflow.connect(ExpandCollections.new)
|
46
|
+
workflow.connect(FlattenManifest.new)
|
47
|
+
|
48
|
+
workflow.process do |result|
|
49
|
+
block.call(result)
|
18
50
|
end
|
19
51
|
end
|
20
|
-
|
21
|
-
def build_docs
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
52
|
|
27
|
-
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :config, :workflow
|
56
|
+
end
|
57
|
+
end
|
@@ -27,12 +27,18 @@ module Yarrow
|
|
27
27
|
|
28
28
|
target_path = Pathname.new("#{docroot}#{path}")
|
29
29
|
|
30
|
-
|
30
|
+
ensure_dir_exists!(target_path.dirname)
|
31
31
|
|
32
32
|
File.open(target_path.to_s, WRITE_MODE) do |file|
|
33
33
|
file.puts(content)
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
def ensure_dir_exists!(target)
|
38
|
+
unless File.directory?(target)
|
39
|
+
FileUtils.mkdir_p(target)
|
40
|
+
end
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|