yarrow 0.8.1 → 0.8.2
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/lib/yarrow/config.rb +12 -2
- data/lib/yarrow/configuration.rb +13 -1
- data/lib/yarrow/content/expansion/strategy.rb +53 -0
- data/lib/yarrow/content/expansion/tree.rb +90 -0
- data/lib/yarrow/content/graph.rb +0 -5
- data/lib/yarrow/content/model.rb +11 -34
- data/lib/yarrow/content/policy.rb +75 -18
- data/lib/yarrow/defaults.yml +5 -0
- data/lib/yarrow/generator.rb +2 -2
- data/lib/yarrow/schema/definitions.rb +3 -3
- data/lib/yarrow/version.rb +1 -1
- data/lib/yarrow.rb +7 -9
- metadata +3 -4
- data/lib/yarrow/content/expansion.rb +0 -16
- data/lib/yarrow/content/expansion_strategy.rb +0 -51
- data/lib/yarrow/content/tree_expansion.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ea37c60e3c8bfe51e6ceb9425f0d0c81b93757a681c7987f7852c3335644824
|
4
|
+
data.tar.gz: 19cd090d3b3348f633f5d303d8b826fd2b8c054b790136355a41d9b4f0f098c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebd0dd29f6d8800b20560c2e24fd2988caecf19e9ae5f3e44a3d0b427afc9201971be1b086705e72c874683d30625821b270e6ad944c5c28ca9b6cd9ecd65ea2
|
7
|
+
data.tar.gz: 92d36891c8a270ff663a299b2a217ffe3bb6985200e70d84c4c9d29ee87bb00fb7b2e824e0d932d585b5f8b4a22d578748ee58ad3ae022aa8f1b8ab04117ac6f
|
data/lib/yarrow/config.rb
CHANGED
@@ -40,7 +40,16 @@ module Yarrow
|
|
40
40
|
:middleware
|
41
41
|
)
|
42
42
|
|
43
|
-
|
43
|
+
# Yarrow::Schema.define do
|
44
|
+
# type :config_source_map, Yarrow::Schema::Types::Instance.of(Hash).accept(Symbol)
|
45
|
+
# end
|
46
|
+
|
47
|
+
class Content < Yarrow::Schema::Entity[:__config_content]
|
48
|
+
attribute :module, :string
|
49
|
+
attribute :source_map, :hash
|
50
|
+
end
|
51
|
+
|
52
|
+
class Output < Yarrow::Schema::Entity[:__config_output]
|
44
53
|
attribute :generator, :string
|
45
54
|
attribute :template_dir, :path
|
46
55
|
#attribute :scripts, :array
|
@@ -52,7 +61,8 @@ module Yarrow
|
|
52
61
|
attribute :output_dir, :path
|
53
62
|
attribute :meta, :any
|
54
63
|
attribute :server, :any
|
55
|
-
|
64
|
+
attribute :content, :__config_content
|
65
|
+
#attribute :output, :__config_output
|
56
66
|
end
|
57
67
|
#
|
58
68
|
# `content_dir` and `output_dir` are placeholders and should be overriden
|
data/lib/yarrow/configuration.rb
CHANGED
@@ -48,6 +48,17 @@ module Yarrow
|
|
48
48
|
nil
|
49
49
|
end
|
50
50
|
|
51
|
+
content_obj = if config.key?(:content)
|
52
|
+
Yarrow::Config::Content.new(config[:content])
|
53
|
+
else
|
54
|
+
Yarrow::Config::Content.new({
|
55
|
+
module: "",
|
56
|
+
source_map: {
|
57
|
+
pages: :page
|
58
|
+
}
|
59
|
+
})
|
60
|
+
end
|
61
|
+
|
51
62
|
# TODO: messy hack to get rid of Hashie::Mash, this should either be
|
52
63
|
# automated as part of the schema types or a default value should be
|
53
64
|
# generated here (eg: `"#{Dir.pwd}/docs"`)
|
@@ -58,7 +69,8 @@ module Yarrow
|
|
58
69
|
output_dir: Pathname.new(File.expand_path(out_dir_or_string)),
|
59
70
|
source_dir: Pathname.new(File.expand_path(source_dir_or_string)),
|
60
71
|
meta: meta_obj,
|
61
|
-
server: server_obj
|
72
|
+
server: server_obj,
|
73
|
+
content: content_obj
|
62
74
|
)
|
63
75
|
end
|
64
76
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
module Expansion
|
4
|
+
class Strategy
|
5
|
+
include Yarrow::Tools::FrontMatter
|
6
|
+
|
7
|
+
attr_reader :graph
|
8
|
+
|
9
|
+
def initialize(graph)
|
10
|
+
@graph = graph
|
11
|
+
end
|
12
|
+
|
13
|
+
# Extract collection level configuration/metadata from the root node for
|
14
|
+
# this content type.
|
15
|
+
def extract_metadata(node, type)
|
16
|
+
# TODO: support _index or _slug convention as well
|
17
|
+
meta_file = node.out(slug: type.to_s).first
|
18
|
+
|
19
|
+
if meta_file
|
20
|
+
# Process metadata and add it to the collection node
|
21
|
+
# TODO: pass in content converter object
|
22
|
+
# TODO: index/body content by default if extracted from frontmatter
|
23
|
+
body, data = process_content(meta_file.props[:entry])
|
24
|
+
else
|
25
|
+
# Otherwise, assume default collection behaviour
|
26
|
+
data = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Generate a default title if not provided in metadata
|
30
|
+
unless data.key?(:title)
|
31
|
+
data[:title] = type.to_s.capitalize
|
32
|
+
end
|
33
|
+
|
34
|
+
data
|
35
|
+
end
|
36
|
+
|
37
|
+
# Workaround for handling meta and content source in multiple files or a single
|
38
|
+
# file with front matter.
|
39
|
+
def process_content(path)
|
40
|
+
case path.extname
|
41
|
+
when '.htm', '.md'
|
42
|
+
read_split_content(path.to_s, symbolize_keys: true)
|
43
|
+
# when '.md'
|
44
|
+
# body, data = read_split_content(path.to_s, symbolize_keys: true)
|
45
|
+
# [Kramdown::Document.new(body).to_html, data]
|
46
|
+
when '.yml'
|
47
|
+
[nil, YAML.load(File.read(path.to_s), symbolize_names: true)]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Content
|
3
|
+
module Expansion
|
4
|
+
class Tree < Strategy
|
5
|
+
def expand(policy)
|
6
|
+
#p graph.n(:root).out(:directory).to_a.count
|
7
|
+
#policy.match()
|
8
|
+
|
9
|
+
#p graph.n(:root).out(:directory).first.props[:name]
|
10
|
+
type = policy.container
|
11
|
+
|
12
|
+
# If match path represents entire content dir, then include the entire
|
13
|
+
# content dir instead of scanning from a subfolder matching the name of
|
14
|
+
# the collection.
|
15
|
+
#start_node = if policy.match_path == "."
|
16
|
+
start_node = if true
|
17
|
+
# TODO: match against source_dir
|
18
|
+
graph.n(:root).out(:directory)
|
19
|
+
else
|
20
|
+
graph.n(:root).out(name: policy.container.to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Extract metadata from given start node
|
24
|
+
collection_metadata = extract_metadata(start_node, policy.container)
|
25
|
+
|
26
|
+
# Collect all nested collections in the subgraph for this content type
|
27
|
+
subcollections = {}
|
28
|
+
item_links = []
|
29
|
+
index = nil
|
30
|
+
|
31
|
+
# Scan and collect all nested files from the root
|
32
|
+
start_node.depth_first.each do |node|
|
33
|
+
if node.label == :directory
|
34
|
+
# Create a collection node representing a collection of documents
|
35
|
+
index = graph.create_node do |collection_node|
|
36
|
+
collection_node.label = :collection
|
37
|
+
collection_node.props[:type] = policy.container
|
38
|
+
collection_node.props[:name] = node.props[:name]
|
39
|
+
|
40
|
+
# TODO: title needs to be defined from metadata
|
41
|
+
collection_node.props[:title] = node.props[:name].capitalize
|
42
|
+
end
|
43
|
+
|
44
|
+
# Add this collection id to the lookup table for edge construction
|
45
|
+
subcollections[node.props[:path]] = index
|
46
|
+
|
47
|
+
# Join the collection to its parent
|
48
|
+
unless node.props[:slug] == type.to_s || !subcollections.key?(node.props[:entry].parent.to_s)
|
49
|
+
graph.create_edge do |edge|
|
50
|
+
edge.label = :child
|
51
|
+
edge.from = subcollections[node.props[:entry].parent.to_s].id
|
52
|
+
edge.to = index.id
|
53
|
+
end
|
54
|
+
end
|
55
|
+
elsif node.label == :file
|
56
|
+
body, meta = process_content(node.props[:entry])
|
57
|
+
|
58
|
+
# Create an item node representing a file mapped to a unique content object
|
59
|
+
item = graph.create_node do |item_node|
|
60
|
+
item_node.label = :item
|
61
|
+
item_node.props[:type] = policy.entity
|
62
|
+
item_node.props[:name] = node.props[:entry].basename(node.props[:entry].extname).to_s
|
63
|
+
item_node.props[:body] = body if body
|
64
|
+
item_node.props[:title] = meta[:title] if meta
|
65
|
+
# TODO: better handling of metadata on node props
|
66
|
+
end
|
67
|
+
|
68
|
+
# We may not have an expanded node for the parent collection if this is a
|
69
|
+
# preorder traversal so save it for later
|
70
|
+
item_links << {
|
71
|
+
parent_path: node.props[:entry].parent.to_s,
|
72
|
+
item_id: item.id
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Once all files and directories have been expanded, connect all the child
|
78
|
+
# edges between collections and items
|
79
|
+
item_links.each do |item_link|
|
80
|
+
graph.create_edge do |edge|
|
81
|
+
edge.label = :child
|
82
|
+
edge.from = subcollections[item_link[:parent_path]].id
|
83
|
+
edge.to = item_link[:item_id]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/yarrow/content/graph.rb
CHANGED
data/lib/yarrow/content/model.rb
CHANGED
@@ -1,45 +1,22 @@
|
|
1
1
|
module Yarrow
|
2
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
3
|
class Model
|
18
|
-
def initialize(
|
19
|
-
@
|
20
|
-
|
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
|
4
|
+
def initialize(content_config)
|
5
|
+
@policies = {}
|
6
|
+
content_config.source_map.each_entry do |policy_label, policy_spec|
|
7
|
+
@policies[policy_label] = Policy.from_spec(policy_label, policy_spec)
|
34
8
|
end
|
35
9
|
end
|
36
10
|
|
37
|
-
def
|
38
|
-
@policies.each_value
|
11
|
+
def expand(graph)
|
12
|
+
@policies.each_value do |policy|
|
13
|
+
strategy = Expansion::Tree.new(graph)
|
14
|
+
strategy.expand(policy)
|
15
|
+
end
|
39
16
|
end
|
40
17
|
|
41
|
-
def policy_for(
|
42
|
-
@policies[
|
18
|
+
def policy_for(policy_label)
|
19
|
+
@policies[policy_label]
|
43
20
|
end
|
44
21
|
end
|
45
22
|
end
|
@@ -1,47 +1,104 @@
|
|
1
1
|
module Yarrow
|
2
2
|
module Content
|
3
3
|
class Policy
|
4
|
-
Options = Yarrow::Schema::Value.new(
|
5
|
-
:container,
|
6
|
-
:entity,
|
7
|
-
:extensions,
|
8
|
-
:match_path
|
9
|
-
)
|
10
|
-
|
11
4
|
DEFAULT_HOME_NESTING = false
|
12
5
|
|
6
|
+
DEFAULT_EXPANSION = :tree
|
7
|
+
|
13
8
|
DEFAULT_EXTENSIONS = [".md", ".yml", ".htm"]
|
14
9
|
|
15
10
|
DEFAULT_MATCH_PATH = "."
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
# Construct a content policy from the given source specification.
|
13
|
+
def self.from_spec(policy_label, policy_props, module_prefix="")
|
14
|
+
# TODO: validate length, structure etc
|
15
|
+
|
16
|
+
# If the spec holds a symbol value then treat it as a container => entity mapping
|
17
|
+
if policy_props.is_a?(Symbol)
|
18
|
+
new(policy_label, policy_props, DEFAULT_EXPANSION, DEFAULT_EXTENSIONS, DEFAULT_MATCH_PATH, module_prefix)
|
19
|
+
|
20
|
+
# Otherwise scan through all the props and fill in any gaps
|
21
|
+
else
|
22
|
+
# Use explicit container name if provided
|
23
|
+
container = if policy_props.key?(:container)
|
24
|
+
policy_props[:container]
|
25
|
+
else
|
26
|
+
# If an entity name is provided use its plural for the container name
|
27
|
+
if policy_props.key?(:entity)
|
28
|
+
Yarrow::Symbols.to_plural(policy_props[:entity])
|
29
|
+
else
|
30
|
+
Yarrow::Symbols.to_plural(label)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Use explicit entity name if provided
|
35
|
+
entity = if policy_props.key?(:entity)
|
36
|
+
policy_props[:entity]
|
37
|
+
else
|
38
|
+
if policy_props.key?(:container)
|
39
|
+
Yarrow::Symbols.to_singular(policy_props[:container])
|
40
|
+
else
|
41
|
+
Yarrow::Symbols.to_singular(label)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set expansion strategy
|
46
|
+
expansion = if policy_props.key?(:expansion)
|
47
|
+
policy_props[:expansion]
|
48
|
+
else
|
49
|
+
DEFAULT_EXPANSION
|
50
|
+
end
|
51
|
+
|
52
|
+
# Set list of extensions to turn into documents
|
53
|
+
extensions = if policy_props.key?(:extensions)
|
54
|
+
policy_props[:extensions]
|
55
|
+
else
|
56
|
+
DEFAULT_EXTENSIONS
|
57
|
+
end
|
20
58
|
|
21
|
-
|
22
|
-
|
23
|
-
|
59
|
+
# TODO: handle this in expansion strategies
|
60
|
+
match_path = DEFAULT_MATCH_PATH
|
61
|
+
|
62
|
+
# Construct the new policy
|
63
|
+
new(container, entity, expansion, extensions, match_path, module_prefix)
|
24
64
|
end
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :container, :entity, :expansion, :extensions, :match_path, :module
|
68
|
+
|
69
|
+
def initialize(container, entity, expansion, extensions, match_path, module_prefix)
|
70
|
+
@container = container
|
71
|
+
@entity = entity
|
72
|
+
@expansion = expansion
|
73
|
+
@extensions = extensions
|
74
|
+
@match_path = match_path
|
75
|
+
@module_prefix = module_prefix
|
76
|
+
end
|
77
|
+
|
78
|
+
def container_const
|
79
|
+
@container_const ||= Yarrow::Symbols.to_module_const([module_prefix, container])
|
80
|
+
end
|
25
81
|
|
26
|
-
|
82
|
+
def entity_const
|
83
|
+
@entity_const ||= Yarrow::Symbols.to_module_const([module_prefix, entity])
|
27
84
|
end
|
28
85
|
|
29
|
-
def
|
86
|
+
def _container
|
30
87
|
return @properties.container if @properties.container
|
31
88
|
Yarrow::Symbols.to_plural(@properties.entity)
|
32
89
|
end
|
33
90
|
|
34
|
-
def
|
91
|
+
def _entity
|
35
92
|
return @properties.entity if @properties.entity
|
36
93
|
Yarrow::Symbols.to_singular(@properties.container)
|
37
94
|
end
|
38
95
|
|
39
|
-
def
|
96
|
+
def _extensions
|
40
97
|
return @properties.extensions if @properties.extensions
|
41
98
|
DEFAULT_EXTENSIONS
|
42
99
|
end
|
43
100
|
|
44
|
-
def
|
101
|
+
def _match_path
|
45
102
|
return @properties.match_path if @properties.match_path
|
46
103
|
DEFAULT_MATCH_PATH
|
47
104
|
end
|
data/lib/yarrow/defaults.yml
CHANGED
data/lib/yarrow/generator.rb
CHANGED
@@ -13,8 +13,8 @@ module Yarrow
|
|
13
13
|
provides Content::Graph
|
14
14
|
|
15
15
|
def step(content)
|
16
|
-
|
17
|
-
|
16
|
+
model = Content::Model.new(content.config.content)
|
17
|
+
model.expand(content.graph)
|
18
18
|
content
|
19
19
|
end
|
20
20
|
end
|
@@ -8,7 +8,7 @@ module Yarrow
|
|
8
8
|
path: Types::Instance.of(Pathname).accept(String),
|
9
9
|
any: Types::Any.new,
|
10
10
|
array: Types::List.of(Types::Any),
|
11
|
-
hash: Types::
|
11
|
+
hash: Types::Instance.of(Hash)
|
12
12
|
}
|
13
13
|
|
14
14
|
TEMPLATE_TYPES = {
|
@@ -40,7 +40,7 @@ module Yarrow
|
|
40
40
|
|
41
41
|
# Get reference to the type class we want to resolve
|
42
42
|
template_type = TEMPLATE_TYPES[key_id]
|
43
|
-
|
43
|
+
|
44
44
|
# Resolve the type to an instance depending on structure of its template args
|
45
45
|
resolved_type = if value_id.is_a?(Hash)
|
46
46
|
# Map template with two argument constructor
|
@@ -55,7 +55,7 @@ module Yarrow
|
|
55
55
|
|
56
56
|
# Cache the resolved type for later reference
|
57
57
|
DEFINED_TYPES[identifier] = resolved_type
|
58
|
-
|
58
|
+
|
59
59
|
# Return the resolve type
|
60
60
|
resolved_type
|
61
61
|
else
|
data/lib/yarrow/version.rb
CHANGED
data/lib/yarrow.rb
CHANGED
@@ -14,19 +14,15 @@ require "yarrow/schema/dictionary"
|
|
14
14
|
require "yarrow/schema/entity"
|
15
15
|
require "yarrow/schema/value"
|
16
16
|
require "yarrow/schema/registry"
|
17
|
-
require "yarrow/config"
|
18
|
-
require "yarrow/configuration"
|
19
|
-
require "yarrow/console_runner"
|
20
17
|
require "yarrow/tools/front_matter"
|
21
18
|
require "yarrow/tools/content_utils"
|
22
19
|
require "yarrow/content/graph"
|
20
|
+
require "yarrow/content/policy"
|
21
|
+
require "yarrow/content/model"
|
23
22
|
require "yarrow/content/source"
|
24
|
-
require "yarrow/content/expansion"
|
25
|
-
require "yarrow/content/
|
26
|
-
require "yarrow/content/tree_expansion"
|
23
|
+
require "yarrow/content/expansion/strategy"
|
24
|
+
require "yarrow/content/expansion/tree"
|
27
25
|
require "yarrow/content/resource"
|
28
|
-
require "yarrow/content/model"
|
29
|
-
require "yarrow/content/policy"
|
30
26
|
require "yarrow/web/manifest"
|
31
27
|
require "yarrow/web/document"
|
32
28
|
require "yarrow/web/generator"
|
@@ -36,12 +32,14 @@ require "yarrow/output/web/indexed_file"
|
|
36
32
|
require "yarrow/content_map"
|
37
33
|
require "yarrow/server"
|
38
34
|
require "yarrow/server/livereload"
|
39
|
-
|
40
35
|
require "yarrow/process/workflow"
|
41
36
|
require "yarrow/process/step_processor"
|
42
37
|
require "yarrow/process/expand_content"
|
43
38
|
require "yarrow/process/extract_source"
|
44
39
|
require "yarrow/process/project_manifest"
|
40
|
+
require "yarrow/config"
|
41
|
+
require "yarrow/configuration"
|
42
|
+
require "yarrow/console_runner"
|
45
43
|
|
46
44
|
require "yarrow/generator"
|
47
45
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yarrow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Rickerby
|
@@ -260,14 +260,13 @@ files:
|
|
260
260
|
- lib/yarrow/config.rb
|
261
261
|
- lib/yarrow/configuration.rb
|
262
262
|
- lib/yarrow/console_runner.rb
|
263
|
-
- lib/yarrow/content/expansion.rb
|
264
|
-
- lib/yarrow/content/
|
263
|
+
- lib/yarrow/content/expansion/strategy.rb
|
264
|
+
- lib/yarrow/content/expansion/tree.rb
|
265
265
|
- lib/yarrow/content/graph.rb
|
266
266
|
- lib/yarrow/content/model.rb
|
267
267
|
- lib/yarrow/content/policy.rb
|
268
268
|
- lib/yarrow/content/resource.rb
|
269
269
|
- lib/yarrow/content/source.rb
|
270
|
-
- lib/yarrow/content/tree_expansion.rb
|
271
270
|
- lib/yarrow/content_map.rb
|
272
271
|
- lib/yarrow/defaults.yml
|
273
272
|
- lib/yarrow/generator.rb
|
@@ -1,16 +0,0 @@
|
|
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
|
@@ -1,51 +0,0 @@
|
|
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
|
@@ -1,88 +0,0 @@
|
|
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
|
-
type = policy.container
|
10
|
-
|
11
|
-
# If match path represents entire content dir, then include the entire
|
12
|
-
# content dir instead of scanning from a subfolder matching the name of
|
13
|
-
# the collection.
|
14
|
-
#start_node = if policy.match_path == "."
|
15
|
-
start_node = if true
|
16
|
-
# TODO: match against source_dir
|
17
|
-
graph.n(:root).out(:directory)
|
18
|
-
else
|
19
|
-
graph.n(:root).out(name: policy.container.to_s)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Extract metadata from given start node
|
23
|
-
collection_metadata = extract_metadata(start_node, policy.container)
|
24
|
-
|
25
|
-
# Collect all nested collections in the subgraph for this content type
|
26
|
-
subcollections = {}
|
27
|
-
item_links = []
|
28
|
-
index = nil
|
29
|
-
|
30
|
-
# Scan and collect all nested files from the root
|
31
|
-
start_node.depth_first.each do |node|
|
32
|
-
if node.label == :directory
|
33
|
-
# Create a collection node representing a collection of documents
|
34
|
-
index = graph.create_node do |collection_node|
|
35
|
-
collection_node.label = :collection
|
36
|
-
collection_node.props[:type] = policy.container
|
37
|
-
collection_node.props[:name] = node.props[:name]
|
38
|
-
|
39
|
-
# TODO: title needs to be defined from metadata
|
40
|
-
collection_node.props[:title] = node.props[:name].capitalize
|
41
|
-
end
|
42
|
-
|
43
|
-
# Add this collection id to the lookup table for edge construction
|
44
|
-
subcollections[node.props[:path]] = index
|
45
|
-
|
46
|
-
# Join the collection to its parent
|
47
|
-
unless node.props[:slug] == type.to_s || !subcollections.key?(node.props[:entry].parent.to_s)
|
48
|
-
graph.create_edge do |edge|
|
49
|
-
edge.label = :child
|
50
|
-
edge.from = subcollections[node.props[:entry].parent.to_s].id
|
51
|
-
edge.to = index.id
|
52
|
-
end
|
53
|
-
end
|
54
|
-
elsif node.label == :file
|
55
|
-
body, meta = process_content(node.props[:entry])
|
56
|
-
|
57
|
-
# Create an item node representing a file mapped to a unique content object
|
58
|
-
item = graph.create_node do |item_node|
|
59
|
-
item_node.label = :item
|
60
|
-
item_node.props[:type] = policy.record
|
61
|
-
item_node.props[:name] = node.props[:entry].basename(node.props[:entry].extname).to_s
|
62
|
-
item_node.props[:body] = body if body
|
63
|
-
item_node.props[:title] = meta[:title] if meta
|
64
|
-
# TODO: better handling of metadata on node props
|
65
|
-
end
|
66
|
-
|
67
|
-
# We may not have an expanded node for the parent collection if this is a
|
68
|
-
# preorder traversal so save it for later
|
69
|
-
item_links << {
|
70
|
-
parent_path: node.props[:entry].parent.to_s,
|
71
|
-
item_id: item.id
|
72
|
-
}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Once all files and directories have been expanded, connect all the child
|
77
|
-
# edges between collections and items
|
78
|
-
item_links.each do |item_link|
|
79
|
-
graph.create_edge do |edge|
|
80
|
-
edge.label = :child
|
81
|
-
edge.from = subcollections[item_link[:parent_path]].id
|
82
|
-
edge.to = item_link[:item_id]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|