yarrow 0.7.1 → 0.7.3
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/.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
|