yarrow 0.9.2 → 0.9.4
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 +2 -2
- data/README.md +10 -7
- data/lib/yarrow/config.rb +76 -13
- data/lib/yarrow/configuration.rb +5 -18
- data/lib/yarrow/content/collection.rb +7 -0
- data/lib/yarrow/content/expansion/aggregator.rb +3 -3
- data/lib/yarrow/content/expansion/filename_map.rb +1 -1
- data/lib/yarrow/content/policy.rb +48 -42
- data/lib/yarrow/defaults.yml +15 -2
- data/lib/yarrow/output/build.rb +37 -0
- data/lib/yarrow/schema/definitions.rb +1 -1
- data/lib/yarrow/schema/dictionary.rb +3 -2
- data/lib/yarrow/schema/entity.rb +18 -12
- data/lib/yarrow/schema/types.rb +63 -33
- data/lib/yarrow/schema/value.rb +21 -12
- data/lib/yarrow/symbols.rb +14 -0
- data/lib/yarrow/version.rb +1 -1
- data/lib/yarrow/web/document.rb +22 -1
- data/lib/yarrow/web/manifest.rb +22 -0
- data/lib/yarrow/web/url.rb +29 -0
- data/lib/yarrow.rb +3 -2
- metadata +5 -9
- data/lib/yarrow/assets/manifest.rb +0 -118
- data/lib/yarrow/assets/pipeline.rb +0 -126
- data/lib/yarrow/assets.rb +0 -2
- data/lib/yarrow/output/context.rb +0 -16
- data/lib/yarrow/output/web/indexed_file.rb +0 -45
- data/lib/yarrow/source/graph.rb +0 -6
- data/lib/yarrow/tools/front_matter.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9312b361a125e332c4283433f1b26d29eda2a66c19b08023778eb77ea4b7e297
|
4
|
+
data.tar.gz: 04d6809bb61575cb508b0abb87de095e5bc8c861261177558eb602c95f6913a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c9869456f8255277347e442693d68e894b4af657f82ecba0024a9b3d624cfd4393e83f30f4e98f8cb3897bbbc36c15fcd564060fc940a0de727c193f38ceb3b
|
7
|
+
data.tar.gz: 6ed205652f8a844e87d6c9c5c447d34a65e7e26bfcdc661b742ff26079796082b8b1fcf7fd7d521d37885f79ea83342dcf07e605e64ee5d84d1a8a447d556266
|
data/.github/workflows/ruby.yml
CHANGED
@@ -10,10 +10,10 @@ jobs:
|
|
10
10
|
fail-fast: false
|
11
11
|
matrix:
|
12
12
|
os: [ubuntu-latest, macos-latest]
|
13
|
-
ruby: [
|
13
|
+
ruby: [3.1, 3.2, "3.3.0-preview1"]
|
14
14
|
runs-on: ${{ matrix.os }}
|
15
15
|
steps:
|
16
|
-
- uses: actions/checkout@
|
16
|
+
- uses: actions/checkout@v4
|
17
17
|
- name: Set up Ruby
|
18
18
|
uses: ruby/setup-ruby@v1
|
19
19
|
with:
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ gem 'yarrow'
|
|
29
29
|
Status
|
30
30
|
------
|
31
31
|
|
32
|
-
Yarrow is an extraction from several existing private documentation projects. This repo is in alpha state, which means that many of the useful features are not yet folded into this codebase.
|
32
|
+
Yarrow is an extraction from several existing private documentation projects. ~~This repo is in alpha state, which means that many of the useful features are not yet folded into this codebase.~~ This repo is in flux as it is being used on several live projects, but lacks documentation and a unified command line tool.
|
33
33
|
|
34
34
|
Yarrow is being slowly developed as a part-time project to scratch a few itches. New features and bugfixes are pushed straight to `main`, and releases of the Gem are kept more or less in sync with the planned roadmap.
|
35
35
|
|
@@ -40,12 +40,15 @@ A rough sketch of the project direction.
|
|
40
40
|
|
41
41
|
| Version | Features |
|
42
42
|
|---------|-------------------------------------------------|
|
43
|
-
| `0.
|
44
|
-
| `0.
|
45
|
-
| `0.
|
46
|
-
| `0.
|
47
|
-
| `0.
|
48
|
-
| `
|
43
|
+
| `0.10` | Filename map expansion strategy |
|
44
|
+
| `0.11` | Directory merge expansion strategy |
|
45
|
+
| `0.12` | Basename merge expansion strategy |
|
46
|
+
| `0.13` | Resources and Assets vocabulary |
|
47
|
+
| `0.14` | Flatten namespaces and clean up modules |
|
48
|
+
| `0.15` | Web template mapping and markup generators |
|
49
|
+
| `0.16` | Document custom Markdown components |
|
50
|
+
| `0.17` | Publishing support for S3 and GitHub/Netlify |
|
51
|
+
| `0.18` | Clean up local web server and watcher |
|
49
52
|
|
50
53
|
License
|
51
54
|
-------
|
data/lib/yarrow/config.rb
CHANGED
@@ -10,11 +10,11 @@ module Yarrow
|
|
10
10
|
# For larger web publishing projects, this should be moved out into a
|
11
11
|
# template context or language/translation files to make it editable
|
12
12
|
# for a larger group of people.
|
13
|
-
Meta
|
14
|
-
:title,
|
15
|
-
:author
|
13
|
+
class Meta < Yarrow::Schema::Entity
|
14
|
+
attribute :title, :string
|
15
|
+
attribute :author, :string
|
16
16
|
# :copyright TODO: what other basic details to include?
|
17
|
-
|
17
|
+
end
|
18
18
|
|
19
19
|
# Dev server config. This is mainly useful if you want to set up a specific
|
20
20
|
# chain of Rack middleware and handlers. If you don’t care about default
|
@@ -52,27 +52,90 @@ module Yarrow
|
|
52
52
|
# :__config_source_map,
|
53
53
|
# Yarrow::Schema::Types::Map.of(Symbol)
|
54
54
|
# )
|
55
|
-
|
56
|
-
class Content < Yarrow::Schema::Entity[:__config_content]
|
55
|
+
class Content < Yarrow::Schema::Entity
|
57
56
|
attribute :module, :string
|
58
57
|
#attribute :source_map, :__config_source_map
|
59
58
|
attribute :source_map, :hash
|
60
59
|
end
|
60
|
+
|
61
|
+
# Template engine and site generator configuration block
|
62
|
+
class OutputGenerator < Yarrow::Schema::Entity
|
63
|
+
attribute :engine, :string
|
64
|
+
attribute :template_dir, :string
|
65
|
+
attribute :options, :hash
|
66
|
+
end
|
67
|
+
|
68
|
+
# Document mapping configuration block
|
69
|
+
class OutputManifest < Yarrow::Schema::Entity
|
70
|
+
attribute :layout, :string
|
71
|
+
attribute :scheme, :string
|
72
|
+
|
73
|
+
DEFAULT_URL_SCHEME = "/{ancestors*}"
|
74
|
+
|
75
|
+
def self.from_spec(input, context)
|
76
|
+
attrs = {}
|
77
|
+
|
78
|
+
if input.is_a?(TrueClass)
|
79
|
+
attrs[:layout] = context[:key].to_s
|
80
|
+
elsif input.is_a?(FalseClass)
|
81
|
+
raise "Reconciliation for content type #{context[:key]} cannot be skipped (yet)"
|
82
|
+
elsif input.is_a?(Symbol)
|
83
|
+
attrs[:layout] = input.to_s
|
84
|
+
elsif input.is_a?(String)
|
85
|
+
attrs[:layout] = context[:key].to_s
|
86
|
+
attrs[:scheme] = input
|
87
|
+
elsif input.is_a?(Hash)
|
88
|
+
attrs = input
|
89
|
+
else
|
90
|
+
raise "Invalid data for output manifest: #{input.class}"
|
91
|
+
end
|
92
|
+
|
93
|
+
unless attrs.key?(:scheme)
|
94
|
+
attrs[:scheme] = DEFAULT_URL_SCHEME
|
95
|
+
end
|
96
|
+
|
97
|
+
new(attrs)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Define output document map type
|
102
|
+
Yarrow::Schema::Definitions.register(
|
103
|
+
:yarrow_config_output_manifest_spec,
|
104
|
+
Yarrow::Schema::Types::Map.of(Symbol => OutputManifest).accept_elements(Hash)
|
105
|
+
.accept_elements(TrueClass, :from_spec)
|
106
|
+
.accept_elements(FalseClass, :from_spec)
|
107
|
+
.accept_elements(Symbol, :from_spec)
|
108
|
+
.accept_elements(String, :from_spec)
|
109
|
+
)
|
110
|
+
|
111
|
+
# Manifest reconciliation configuration block
|
112
|
+
class OutputReconcile < Yarrow::Schema::Entity
|
113
|
+
attribute :match, :string
|
114
|
+
attribute :manifest, :yarrow_config_output_manifest_spec
|
115
|
+
end
|
61
116
|
|
62
|
-
|
63
|
-
|
64
|
-
attribute :
|
65
|
-
|
117
|
+
# Output configuration block
|
118
|
+
class Output < Yarrow::Schema::Entity
|
119
|
+
attribute :target, :string
|
120
|
+
attribute :generator, :yarrow_config_output_generator
|
121
|
+
attribute :reconcile, :yarrow_config_output_reconcile
|
66
122
|
end
|
67
123
|
|
124
|
+
# Define output schema list type
|
125
|
+
Yarrow::Schema::Definitions.register(
|
126
|
+
:yarrow_config_output_list,
|
127
|
+
Yarrow::Schema::Types::List.of(Output).accept_elements(Hash)
|
128
|
+
)
|
129
|
+
|
68
130
|
# Top level root config namespace.
|
69
131
|
class Instance < Yarrow::Schema::Entity
|
70
132
|
attribute :source_dir, :path
|
71
133
|
attribute :output_dir, :path
|
72
|
-
attribute :meta, :
|
134
|
+
attribute :meta, :yarrow_config_meta
|
73
135
|
attribute :server, :any
|
74
|
-
attribute :content, :
|
75
|
-
attribute :output, :
|
136
|
+
attribute :content, :yarrow_config_content
|
137
|
+
attribute :output, :yarrow_config_output_list
|
138
|
+
#attribute :output, :any
|
76
139
|
end
|
77
140
|
#
|
78
141
|
# `content_dir` and `output_dir` are placeholders and should be overriden
|
data/lib/yarrow/configuration.rb
CHANGED
@@ -1,21 +1,11 @@
|
|
1
1
|
module Yarrow
|
2
2
|
class Configuration
|
3
3
|
class << self
|
4
|
-
# Merges the given configuration or hash-like object with the
|
5
|
-
# registered global configuration.
|
6
|
-
#
|
7
|
-
# @param [Hash, Hashie::Mash, Yarrow::Configuration]
|
8
|
-
#
|
9
|
-
def merge(config)
|
10
|
-
instance.deep_merge!(config)
|
11
|
-
end
|
12
|
-
|
13
4
|
# Loads a configuration object from the given YAML file.
|
14
5
|
#
|
15
6
|
# @param [String] path to YAML file
|
16
7
|
#
|
17
8
|
# @return [Yarrow::Config]
|
18
|
-
#
|
19
9
|
def load(file)
|
20
10
|
coerce_config_struct(YAML.load(File.read(file), symbolize_names: true))
|
21
11
|
end
|
@@ -34,12 +24,9 @@ module Yarrow
|
|
34
24
|
# TODO: this should be folded into the schema machinery with type coercions
|
35
25
|
def coerce_config_struct(config)
|
36
26
|
meta_obj = if config.key?(:meta)
|
37
|
-
|
38
|
-
title: config[:meta][:title],
|
39
|
-
author: config[:meta][:author]
|
40
|
-
)
|
27
|
+
config[:meta]
|
41
28
|
else
|
42
|
-
|
29
|
+
raise "missing :meta key in config"
|
43
30
|
end
|
44
31
|
|
45
32
|
server_obj = if config.key?(:server)
|
@@ -49,7 +36,7 @@ module Yarrow
|
|
49
36
|
end
|
50
37
|
|
51
38
|
content_obj = if config.key?(:content)
|
52
|
-
|
39
|
+
config[:content]
|
53
40
|
else
|
54
41
|
Yarrow::Config::Content.new({
|
55
42
|
module: "",
|
@@ -60,9 +47,9 @@ module Yarrow
|
|
60
47
|
end
|
61
48
|
|
62
49
|
output_obj = if config.key?(:output)
|
63
|
-
|
50
|
+
config[:output]
|
64
51
|
else
|
65
|
-
|
52
|
+
raise "missing :output key in config"
|
66
53
|
end
|
67
54
|
|
68
55
|
# TODO: messy hack to get rid of Hashie::Mash, this should either be
|
@@ -36,7 +36,7 @@ module Yarrow
|
|
36
36
|
}
|
37
37
|
collection_node.label = :collection
|
38
38
|
collection_node.props[:type] = type
|
39
|
-
collection_node.props[:
|
39
|
+
collection_node.props[:collection] = collection_const.new(attributes)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Add this collection id to the lookup table for edge construction
|
@@ -52,7 +52,7 @@ module Yarrow
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
55
|
+
def create_resource(source_node, parent_path, type, entity_const)
|
56
56
|
contents = Yarrow::Format.read(source_node.props[:path])
|
57
57
|
|
58
58
|
# Create an entity node with attached resource model
|
@@ -63,7 +63,7 @@ module Yarrow
|
|
63
63
|
body: contents.document.to_s
|
64
64
|
}.merge(contents.metadata)
|
65
65
|
|
66
|
-
entity_node.label = :
|
66
|
+
entity_node.label = :resource
|
67
67
|
entity_node.props[:type] = type
|
68
68
|
entity_node.props[:resource] = entity_const.new(attributes)
|
69
69
|
end
|
@@ -15,7 +15,7 @@ module Yarrow
|
|
15
15
|
def expand_file(entity, policy)
|
16
16
|
if policy.match_by_extension(entity.props[:ext])
|
17
17
|
parent_path = entity.incoming(:directory).first.props[:path]
|
18
|
-
|
18
|
+
create_resource(entity, parent_path, policy.entity, policy.entity_const)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,40 +1,53 @@
|
|
1
|
+
Yarrow::Schema::Definitions.register(:extension_list, Yarrow::Schema::Types::List.of(String))
|
2
|
+
|
1
3
|
module Yarrow
|
2
4
|
module Content
|
3
|
-
class Policy
|
5
|
+
class Policy < Yarrow::Schema::Entity
|
6
|
+
# TODO: document meaning and purpose of each attribute
|
7
|
+
attribute :container, :symbol
|
8
|
+
attribute :collection, :symbol
|
9
|
+
attribute :entity, :symbol
|
10
|
+
attribute :expansion, :symbol
|
11
|
+
attribute :extensions, :extension_list
|
12
|
+
attribute :source_path, :string
|
13
|
+
attribute :module_prefix, :string
|
14
|
+
|
4
15
|
DEFAULT_EXPANSION = :filename_map
|
5
16
|
|
6
17
|
DEFAULT_EXTENSIONS = [".md", ".yml", ".htm"]
|
7
18
|
|
8
19
|
DEFAULT_SOURCE_PATH = "."
|
9
20
|
|
21
|
+
DEFAULT_MODULE_PREFIX = ""
|
22
|
+
|
10
23
|
MODULE_SEPARATOR = "::"
|
11
24
|
|
12
25
|
# Construct a content policy from the given source specification.
|
13
|
-
def self.from_spec(policy_label, policy_props, module_prefix=
|
26
|
+
def self.from_spec(policy_label, policy_props=DEFAULT_SOURCE_PATH, module_prefix=DEFAULT_MODULE_PREFIX)
|
14
27
|
# TODO: validate length, structure etc
|
15
28
|
|
16
29
|
# If the spec holds a symbol value then treat it as an entity mapping
|
17
30
|
if policy_props.is_a?(Symbol)
|
18
|
-
new(
|
19
|
-
policy_label,
|
20
|
-
policy_label,
|
21
|
-
policy_props,
|
22
|
-
DEFAULT_EXPANSION,
|
23
|
-
DEFAULT_EXTENSIONS,
|
24
|
-
policy_label.to_s,
|
25
|
-
module_prefix
|
26
|
-
)
|
31
|
+
new({
|
32
|
+
container: policy_label,
|
33
|
+
collection: policy_label,
|
34
|
+
entity: policy_props,
|
35
|
+
expansion: DEFAULT_EXPANSION,
|
36
|
+
extensions: DEFAULT_EXTENSIONS,
|
37
|
+
source_path: policy_label.to_s,
|
38
|
+
module_prefix: module_prefix
|
39
|
+
})
|
27
40
|
|
28
41
|
# If the spec holds a string value then treat it as a source path mapping
|
29
42
|
elsif policy_props.is_a?(String)
|
30
43
|
new(
|
31
|
-
policy_label,
|
32
|
-
policy_label,
|
33
|
-
Yarrow::Symbols.to_singular(policy_label),
|
34
|
-
DEFAULT_EXPANSION,
|
35
|
-
DEFAULT_EXTENSIONS,
|
36
|
-
policy_props,
|
37
|
-
module_prefix
|
44
|
+
container: policy_label,
|
45
|
+
collection: policy_label,
|
46
|
+
entity: Yarrow::Symbols.to_singular(policy_label),
|
47
|
+
expansion: DEFAULT_EXPANSION,
|
48
|
+
extensions: DEFAULT_EXTENSIONS,
|
49
|
+
source_path: policy_props,
|
50
|
+
module_prefix: module_prefix
|
38
51
|
)
|
39
52
|
|
40
53
|
# Otherwise scan through the spec and fill in any gaps
|
@@ -43,7 +56,8 @@ module Yarrow
|
|
43
56
|
collection = if policy_props.key?(:collection)
|
44
57
|
policy_props[:collection]
|
45
58
|
else
|
46
|
-
# If an entity name is provided use its plural for the container name
|
59
|
+
# If an entity name is provided use its plural for the container name.
|
60
|
+
# Otherwise fall back to a container name or policy label.
|
47
61
|
if policy_props.key?(:entity)
|
48
62
|
Yarrow::Symbols.to_plural(policy_props[:entity])
|
49
63
|
else
|
@@ -51,7 +65,7 @@ module Yarrow
|
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
|
-
# Use explicit container name if provided
|
68
|
+
# Use explicit container name if provided. Otherwise fall back to the collection name.
|
55
69
|
container = if policy_props.key?(:container)
|
56
70
|
policy_props[:container]
|
57
71
|
else
|
@@ -91,44 +105,36 @@ module Yarrow
|
|
91
105
|
end
|
92
106
|
|
93
107
|
# Construct the new policy
|
94
|
-
new(
|
95
|
-
container,
|
96
|
-
collection,
|
97
|
-
entity,
|
98
|
-
expansion,
|
99
|
-
extensions,
|
100
|
-
source_path,
|
101
|
-
module_prefix
|
102
|
-
)
|
108
|
+
new({
|
109
|
+
container: container,
|
110
|
+
collection: collection,
|
111
|
+
entity: entity,
|
112
|
+
expansion: expansion,
|
113
|
+
extensions: extensions,
|
114
|
+
source_path: source_path,
|
115
|
+
module_prefix: module_prefix
|
116
|
+
})
|
103
117
|
end
|
104
118
|
end
|
105
119
|
|
106
|
-
|
107
|
-
|
108
|
-
def initialize(container, collection, entity, expansion, extensions, source_path, module_prefix)
|
109
|
-
@container = container
|
110
|
-
@collection = collection
|
111
|
-
@entity = entity
|
112
|
-
@expansion = expansion.to_sym
|
113
|
-
@extensions = extensions
|
114
|
-
@source_path = source_path
|
115
|
-
@module_prefix = module_prefix.split(MODULE_SEPARATOR)
|
120
|
+
def module_prefix_parts
|
121
|
+
module_prefix.split(MODULE_SEPARATOR)
|
116
122
|
end
|
117
123
|
|
118
124
|
def container_const
|
119
|
-
@container_const ||= Yarrow::Symbols.to_module_const([*
|
125
|
+
@container_const ||= Yarrow::Symbols.to_module_const([*module_prefix_parts, container])
|
120
126
|
end
|
121
127
|
|
122
128
|
def collection_const
|
123
129
|
begin
|
124
|
-
@collection_const ||= Yarrow::Symbols.to_module_const([*
|
130
|
+
@collection_const ||= Yarrow::Symbols.to_module_const([*module_prefix_parts, collection])
|
125
131
|
rescue NameError
|
126
132
|
raise NameError, "cannot map undefined entity `#{collection}`"
|
127
133
|
end
|
128
134
|
end
|
129
135
|
|
130
136
|
def entity_const
|
131
|
-
@entity_const ||= Yarrow::Symbols.to_module_const([*
|
137
|
+
@entity_const ||= Yarrow::Symbols.to_module_const([*module_prefix_parts, entity])
|
132
138
|
end
|
133
139
|
|
134
140
|
def aggregator_const
|
data/lib/yarrow/defaults.yml
CHANGED
@@ -11,8 +11,21 @@ content:
|
|
11
11
|
pages:
|
12
12
|
expansion: tree
|
13
13
|
output:
|
14
|
-
|
15
|
-
|
14
|
+
- target: web
|
15
|
+
generator:
|
16
|
+
engine: __PENDING_LIBRARY_DECISION__
|
17
|
+
template_dir: templates
|
18
|
+
options:
|
19
|
+
error_mode: strict
|
20
|
+
reconcile:
|
21
|
+
match: collection
|
22
|
+
manifest:
|
23
|
+
collection:
|
24
|
+
layout: collection
|
25
|
+
scheme: /{ancestor_path}
|
26
|
+
resource:
|
27
|
+
layout: resource
|
28
|
+
scheme: /{ancestor_path}/{name}
|
16
29
|
assets:
|
17
30
|
input_dir: assets
|
18
31
|
output_dir: public/assets
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Yarrow
|
2
|
+
module Output
|
3
|
+
class Build
|
4
|
+
attr_reader :graph, :output_config
|
5
|
+
|
6
|
+
def initialize(graph, output_config)
|
7
|
+
@graph = graph
|
8
|
+
@output_config = output_config
|
9
|
+
end
|
10
|
+
|
11
|
+
def reconcile
|
12
|
+
case output_config.reconcile.match
|
13
|
+
when "collection/resource" then traverse_by_path(:collection, :resource)
|
14
|
+
when "collection" then traverse_by_label(:collection)
|
15
|
+
when "resource" then traverse_by_label(:resource)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def traverse_by_label(label)
|
22
|
+
graph.n(label).each do |node|
|
23
|
+
puts "§ #{label} node #{node.label} #{node.props}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def traverse_by_path(parent_label, child_label)
|
28
|
+
graph.n(parent_label).each do |collection_node|
|
29
|
+
puts "§ #{parent_label} node #{collection_node.label} #{collection_node.props}"
|
30
|
+
collection_node.out(child_label).each do |resource_node|
|
31
|
+
puts "§ #{child_label} node #{resource_node.label} #{resource_node.props}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -7,7 +7,7 @@ module Yarrow
|
|
7
7
|
symbol: Types::Instance.of(Symbol).accept(String, :to_sym),
|
8
8
|
path: Types::Instance.of(Pathname).accept(String),
|
9
9
|
any: Types::Any.new,
|
10
|
-
array: Types::List.
|
10
|
+
array: Types::List.any,
|
11
11
|
hash: Types::Instance.of(Hash),
|
12
12
|
markdown: Types::Instance.of(Kramdown::Document).accept(String)
|
13
13
|
}
|
@@ -23,11 +23,12 @@ module Yarrow
|
|
23
23
|
@attrs_spec.keys
|
24
24
|
end
|
25
25
|
|
26
|
-
def cast(input)
|
26
|
+
def cast(input, context=nil)
|
27
27
|
missing_attrs = @attrs_spec.keys.difference(input.keys)
|
28
28
|
|
29
29
|
if missing_attrs.any?
|
30
30
|
missing_attrs.each do |name|
|
31
|
+
# TODO: add optional check
|
31
32
|
raise "#{missing_attrs} wrong number of attributes" unless @attrs_spec[name].is_a?(Types::Any)
|
32
33
|
end
|
33
34
|
end
|
@@ -37,7 +38,7 @@ module Yarrow
|
|
37
38
|
raise "attribute #{mismatching_attrs} does not exist" if mismatching_attrs.any?
|
38
39
|
|
39
40
|
input.reduce({}) do |converted, (name, value)|
|
40
|
-
converted[name] = @attrs_spec[name].cast(value)
|
41
|
+
converted[name] = @attrs_spec[name].cast(value, context)
|
41
42
|
converted
|
42
43
|
end
|
43
44
|
end
|
data/lib/yarrow/schema/entity.rb
CHANGED
@@ -20,26 +20,24 @@ module Yarrow
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def inherited(class_name)
|
23
|
+
class_type = Yarrow::Schema::Types::Instance.of(class_name).accept(Hash)
|
24
|
+
|
23
25
|
if @label
|
24
|
-
|
25
|
-
Yarrow::Schema::Definitions.register(@label, class_type)
|
26
|
+
label = @label
|
26
27
|
@label = nil
|
28
|
+
else
|
29
|
+
label = Yarrow::Symbols.from_const(class_name)
|
27
30
|
end
|
31
|
+
|
32
|
+
Yarrow::Schema::Definitions.register(label, class_type)
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
|
-
def initialize(config)
|
36
|
+
def initialize(config, context=nil)
|
32
37
|
converted = dictionary.cast(config)
|
33
38
|
|
34
39
|
converted.each_pair do |key, value|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# defined_type = dictionary[key]
|
38
|
-
#
|
39
|
-
# unless value.is_a?(defined_type)
|
40
|
-
# raise "#{key} accepts #{defined_type} but #{value.class} given"
|
41
|
-
# end
|
42
|
-
|
40
|
+
# TODO: should we represent this as an attribute set rather than instance vars?
|
43
41
|
instance_variable_set("@#{key}", value)
|
44
42
|
end
|
45
43
|
end
|
@@ -48,7 +46,15 @@ module Yarrow
|
|
48
46
|
dictionary.attr_names.reduce({}) do |attr_dict, name|
|
49
47
|
value = instance_variable_get("@#{name}")
|
50
48
|
|
51
|
-
attr_dict[name] =
|
49
|
+
attr_dict[name] =if value.is_a?(Array)
|
50
|
+
value.map do |entry|
|
51
|
+
if entry.respond_to?(:to_h)
|
52
|
+
entry.to_h
|
53
|
+
else
|
54
|
+
entry
|
55
|
+
end
|
56
|
+
end
|
57
|
+
elsif value.respond_to?(:to_h)
|
52
58
|
value.to_h
|
53
59
|
else
|
54
60
|
value
|