yarrow 0.9.1 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8f774a7c3013a183129ba27e6929cb1d9cb65f784121f61d3df2c1ffba8a4fb
4
- data.tar.gz: 7f94b3a971a5fb00d089b6bbad8c12cb724d35f3e00497091130c4731534b275
3
+ metadata.gz: 2a2ebdee5113cc218a9744d5da88b01cb0e7604b4ecfe0d133f776d48d2b4b97
4
+ data.tar.gz: 967ba36fec57253eea8069f903828b8529f43802578c8be009413e4a5373e1f1
5
5
  SHA512:
6
- metadata.gz: de66835c7de07c4c84802a8adf75e57d637c4865f7a7e2f1f42f06ac0a22adbadfd067c812a6ba8a5be7e8fa03f116173f1a47777c550d38004e0683c6395685
7
- data.tar.gz: a7aff55ba63ed7cc2b493b28dd27f415c985bd55730de71732411c2d3500ee0beb0dd21a599b7110599dfb80253bef6b4204a70276b4ed794cf0f2884d3149a1
6
+ metadata.gz: 982f7c783ed933419504e6722e9ffbacaf513468a16cdb07ca4ec7ffc859d5eaed1470948d8c1ca7ce5aa00f5e0fc05b9c29a38f0f0e2972aa6d2f348aec2c7b
7
+ data.tar.gz: 4debe486afb56d7f664a0dd730db05429b2d7256a5f2789f1987339b394f404ac0f59f67d9e2f25126ad946675a46b7f910a91881d447afed148cb56eb4b5317
@@ -10,10 +10,10 @@ jobs:
10
10
  fail-fast: false
11
11
  matrix:
12
12
  os: [ubuntu-latest, macos-latest]
13
- ruby: [2.7, 3.1, 3.2]
13
+ ruby: [3.1, 3.2, "3.3.0-preview1"]
14
14
  runs-on: ${{ matrix.os }}
15
15
  steps:
16
- - uses: actions/checkout@v2
16
+ - uses: actions/checkout@v4
17
17
  - name: Set up Ruby
18
18
  uses: ruby/setup-ruby@v1
19
19
  with:
data/lib/yarrow/config.rb CHANGED
@@ -53,13 +53,13 @@ module Yarrow
53
53
  # Yarrow::Schema::Types::Map.of(Symbol)
54
54
  # )
55
55
 
56
- class Content < Yarrow::Schema::Entity[:__config_content]
56
+ class Content < Yarrow::Schema::Entity
57
57
  attribute :module, :string
58
58
  #attribute :source_map, :__config_source_map
59
59
  attribute :source_map, :hash
60
60
  end
61
61
 
62
- class Output < Yarrow::Schema::Entity[:__config_output]
62
+ class Output < Yarrow::Schema::Entity
63
63
  attribute :generator, :string
64
64
  attribute :template_dir, :path
65
65
  #attribute :scripts, :array
@@ -71,8 +71,8 @@ module Yarrow
71
71
  attribute :output_dir, :path
72
72
  attribute :meta, :any
73
73
  attribute :server, :any
74
- attribute :content, :__config_content
75
- attribute :output, :__config_output
74
+ attribute :content, :yarrow_config_content
75
+ attribute :output, :yarrow_config_output
76
76
  end
77
77
  #
78
78
  # `content_dir` and `output_dir` are placeholders and should be overriden
@@ -60,7 +60,7 @@ module Yarrow
60
60
  end
61
61
 
62
62
  def parse_toml(raw)
63
- TOML::Parser.new(raw).parsed
63
+ TomlRB.parse(raw, symbolize_keys: true)
64
64
  end
65
65
 
66
66
  def parse_json(raw)
@@ -20,11 +20,16 @@ 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
- class_type = Yarrow::Schema::Types::Instance.of(class_name)
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
 
@@ -32,14 +37,7 @@ module Yarrow
32
37
  converted = dictionary.cast(config)
33
38
 
34
39
  converted.each_pair do |key, value|
35
- # raise "#{key} not a declared attribute" unless dictionary.key?(key)
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
@@ -1,15 +1,20 @@
1
1
  module Yarrow
2
2
  module Schema
3
- # class Structure < Struct
4
- # def self.inherited(subclass)
5
- # unless subclass.name
6
- # puts "CLASS"
7
- # p caller_locations[3]
8
- # else
9
- # p subclass.name.downcase.to_sym
10
- # end
11
- # end
12
- # end
3
+ class ValueType < Struct
4
+ def self.register(label)
5
+ class_type = Yarrow::Schema::Types::Instance.of(self).accept(Hash)
6
+ Yarrow::Schema::Definitions.register(label, class_type)
7
+ self
8
+ end
9
+
10
+ # Automatically register when struct is defined as a class extension
11
+ # rather than anonymous struct class.
12
+ def self.inherited(subclass)
13
+ if subclass.name
14
+ self.register(subclass.name.downcase.to_sym)
15
+ end
16
+ end
17
+ end
13
18
 
14
19
  # Value object (with comparison by value equality). This just chucks back a
15
20
  # Ruby struct but wraps the constructor with method advice that handles
@@ -33,12 +38,16 @@ module Yarrow
33
38
 
34
39
  validator = Dictionary.new(fields_spec)
35
40
 
36
- struct = Struct.new(*slots_spec, keyword_init: true, &block)
41
+ struct = ValueType.new(*slots_spec, keyword_init: true, &block)
37
42
 
38
43
  struct.define_method :initialize do |*args, **kwargs|
39
44
  attr_values = if args.any?
40
45
  raise ArgumentError.new("cannot mix slots and kwargs") if kwargs.any?
41
- Hash[slots.zip(args)]
46
+ if args.first.instance_of?(Hash) and args.count == 1
47
+ args.first
48
+ else
49
+ Hash[slots.zip(args)]
50
+ end
42
51
  else
43
52
  kwargs
44
53
  end
@@ -19,6 +19,20 @@ module Yarrow
19
19
  Object.const_get(Strings::Case.pascalcase(atom.to_s).to_sym)
20
20
  end
21
21
 
22
+ # Converts a string name of class const to a symbol atom
23
+ #
24
+ # @param [Class, String, #to_s] const_obj
25
+ # @return [Symbol]
26
+ def self.from_const(const_obj)
27
+ const_lookup = if const_obj.respond_to?(:name)
28
+ const_obj.name
29
+ else
30
+ const_obj.to_s
31
+ end
32
+
33
+ Strings::Case.underscore(const_lookup).to_sym
34
+ end
35
+
22
36
  # @param [Symbol, String] atom
23
37
  # @return [Symbol]
24
38
  def self.to_singular(atom)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Yarrow
3
3
  APP_NAME = "Yarrow"
4
- VERSION = "0.9.1"
4
+ VERSION = "0.9.3"
5
5
  end
data/lib/yarrow.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require "pathname"
2
2
  require "yaml"
3
3
  require "kramdown"
4
- require "toml"
4
+ require "toml-rb"
5
5
  require "mustache"
6
6
  require "parallel"
7
7
 
data/yarrow.gemspec CHANGED
@@ -24,8 +24,9 @@ Gem::Specification.new do |spec|
24
24
  spec.add_runtime_dependency 'parallel', '~> 1.22.1'
25
25
  spec.add_runtime_dependency 'strings-inflection', '~> 0.1'
26
26
  spec.add_runtime_dependency 'strings-case', '~> 0.3'
27
- spec.add_runtime_dependency 'toml', '~> 0.3.0'
28
- # https://github.com/joeldrapper/phlex
27
+ spec.add_runtime_dependency 'toml-rb', '~> 2.2.0'
28
+ spec.add_runtime_dependency 'shale', '~> 1.0.0'
29
+ spec.add_runtime_dependency 'phlex', '~> 1.8.1'
29
30
  spec.add_runtime_dependency 'kramdown', '~> 2.4.0'
30
31
  spec.add_development_dependency 'rake', '~> 13.0'
31
32
  spec.add_development_dependency 'rspec', '~> 3.11'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yarrow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rickerby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-03 00:00:00.000000000 Z
11
+ date: 2023-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -165,19 +165,47 @@ dependencies:
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0.3'
167
167
  - !ruby/object:Gem::Dependency
168
- name: toml
168
+ name: toml-rb
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 0.3.0
173
+ version: 2.2.0
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.3.0
180
+ version: 2.2.0
181
+ - !ruby/object:Gem::Dependency
182
+ name: shale
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 1.0.0
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 1.0.0
195
+ - !ruby/object:Gem::Dependency
196
+ name: phlex
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: 1.8.1
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: 1.8.1
181
209
  - !ruby/object:Gem::Dependency
182
210
  name: kramdown
183
211
  requirement: !ruby/object:Gem::Requirement
@@ -277,13 +305,9 @@ files:
277
305
  - lib/yarrow/console_runner.rb
278
306
  - lib/yarrow/content/expansion/aggregator.rb
279
307
  - lib/yarrow/content/expansion/basename_merge.rb
280
- - lib/yarrow/content/expansion/directory_map.rb
281
308
  - lib/yarrow/content/expansion/directory_merge.rb
282
- - lib/yarrow/content/expansion/file_list.rb
283
309
  - lib/yarrow/content/expansion/filename_map.rb
284
- - lib/yarrow/content/expansion/strategy.rb
285
310
  - lib/yarrow/content/expansion/traversal.rb
286
- - lib/yarrow/content/expansion/tree.rb
287
311
  - lib/yarrow/content/graph.rb
288
312
  - lib/yarrow/content/model.rb
289
313
  - lib/yarrow/content/policy.rb
@@ -1,21 +0,0 @@
1
- module Yarrow
2
- module Content
3
- module Expansion
4
- class DirectoryMap < Aggregator
5
- def expand_source(container, policy)
6
- puts "create_node label=:collection type=:#{policy.container} name='#{container.props[:basename]}'"
7
- @current_collection = container.props[:basename]
8
- end
9
-
10
- def expand_directory(collection, policy)
11
- puts "create_node label=:collection type=:#{policy.collection} name='#{collection.props[:basename]}' collection=#{@current_collection}"
12
- @current_collection = collection.props[:basename]
13
- end
14
-
15
- def expand_file(entity, policy)
16
- puts "create_node label=:entity type=:#{policy.entity} name='#{entity.props[:basename]}' collection='#{@current_collection}"
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,15 +0,0 @@
1
- module Yarrow
2
- module Content
3
- module Expansion
4
- class FileList < Strategy
5
- def expand(policy)
6
- start_node = graph.n(:root).out(name: policy.container.to_s)
7
-
8
- start_node.out(:files).each do |file_node|
9
-
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,118 +0,0 @@
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
- @subcollections = {}
12
- @entity_links = []
13
- @index_links = []
14
- @index = nil
15
- end
16
-
17
- # Expand a directory to a collection node representing a collection of entities
18
- def expand_directory(policy, node)
19
- index = graph.create_node do |collection_node|
20
-
21
- collection_attrs = {
22
- name: node.props[:name],
23
- title: node.props[:name].capitalize,
24
- body: ""
25
- }
26
-
27
- populate_collection(collection_node, policy, collection_attrs)
28
- end
29
-
30
- # Add this collection id to the lookup table for edge construction
31
- @subcollections[node.props[:path]] = index
32
-
33
- # Join the collection to its parent
34
- unless node.props[:slug] == policy.collection.to_s || !@subcollections.key?(node.props[:entry].parent.to_s)
35
- graph.create_edge do |edge|
36
- edge.label = :child
37
- edge.from = @subcollections[node.props[:entry].parent.to_s].id
38
- edge.to = index.id
39
- end
40
- end
41
- end
42
-
43
- # Extract collection level configuration/metadata from the root node for
44
- # this content type.
45
- def extract_metadata(node, type)
46
- # TODO: support _index or _slug convention as well
47
- meta_file = node.out(slug: type.to_s).first
48
-
49
- if meta_file
50
- # Process metadata and add it to the collection node
51
- # TODO: pass in content converter object
52
- # TODO: index/body content by default if extracted from frontmatter
53
- body, data = process_content(meta_file.props[:entry])
54
- else
55
- # Otherwise, assume default collection behaviour
56
- data = {}
57
- end
58
-
59
- # Generate a default title if not provided in metadata
60
- unless data.key?(:title)
61
- data[:title] = type.to_s.capitalize
62
- end
63
-
64
- data
65
- end
66
-
67
- def populate_collection(node, policy, meta_attrs)
68
- node.label = :collection
69
- node.props[:type] = policy.collection
70
- node.props[:resource] = policy.collection_const.new(meta_attrs)
71
- end
72
-
73
- def populate_entity(node, policy, meta_attrs)
74
- node.label = :item
75
- node.props[:type] = policy.entity
76
- node.props[:resource] = policy.entity_const.new(meta_attrs)
77
- end
78
-
79
- def merge_collection_index(node, policy, meta_attrs)
80
- props = { resource: node.props[:resource].merge(meta_attrs) }
81
- node.merge_props(props)
82
- end
83
-
84
- # Workaround for handling meta and content source in multiple files or a single
85
- # file with front matter.
86
- def process_content(path)
87
- case path.extname
88
- when '.htm', '.md'
89
- read_split_content(path.to_s, symbolize_keys: true)
90
- # when '.md'
91
- # body, data = read_split_content(path.to_s, symbolize_keys: true)
92
- # [Kramdown::Document.new(body).to_html, data]
93
- when '.yml'
94
- [nil, YAML.load(File.read(path.to_s), symbolize_names: true)]
95
- end
96
- # TODO: Raise error if unsupported extname reaches here
97
- end
98
-
99
- def connect_expanded_entities
100
- # Once all files and directories have been expanded, connect all the child
101
- # edges between collections and entities
102
- @entity_links.each do |entity_link|
103
- graph.create_edge do |edge|
104
- edge.label = :child
105
- edge.from = entity_link[:parent_id].id
106
- edge.to = entity_link[:child_id].id
107
- end
108
- end
109
-
110
- # Merge index page body and metadata with their parent collections
111
- @index_links.each do |index_link|
112
- merge_collection_index(index_link[:parent_id], policy, index_link[:index_attrs])
113
- end
114
- end
115
- end
116
- end
117
- end
118
- end
@@ -1,93 +0,0 @@
1
- module Yarrow
2
- module Content
3
- module Expansion
4
- class Tree < Strategy
5
- def expand(policy)
6
- # If match path represents entire content dir, then include the entire
7
- # content dir instead of scanning from a subfolder matching the name of
8
- # the collection.
9
- #start_node = if policy.match_path == "."
10
- start_node = if policy.match_path == "."
11
- # TODO: match against source_dir
12
- graph.n(:root).out(:directory)
13
- else
14
- graph.n(name: policy.match_path)
15
- end
16
-
17
- # Collect all nested collections in the subgraph for this content type
18
- @subcollections = {}
19
- @entity_links = []
20
- @index_links = []
21
- @index = nil
22
-
23
- # Scan and collect all nested files from the root
24
- start_node.depth_first.each do |node|
25
- if node.label == :directory
26
- expand_directory(policy, node)
27
- elsif node.label == :file
28
- expand_file_by_extension(policy, node)
29
- end
30
- end
31
-
32
- # Once all files and directories have been expanded, connect all the child
33
- # edges between collections and entities
34
- @entity_links.each do |entity_link|
35
- graph.create_edge do |edge|
36
- edge.label = :child
37
- edge.from = entity_link[:parent_id].id
38
- edge.to = entity_link[:child_id].id
39
- end
40
- end
41
-
42
- # Merge index page body and metadata with their parent collections
43
- @index_links.each do |index_link|
44
- merge_collection_index(index_link[:parent_id], policy, index_link[:index_attrs])
45
- end
46
- end
47
-
48
- def expand_file_by_basename(policy, node)
49
- body, meta = process_content(node.props[:entry])
50
- meta = {} if !meta
51
-
52
-
53
- end
54
-
55
- def expand_file_by_extension(policy, node)
56
- body, meta = process_content(node.props[:entry])
57
- meta = {} if !meta
58
-
59
- # TODO: document mapping convention for index pages and collection metadata
60
- # TODO: underscore _index pattern?
61
- bare_basename = node.props[:entry].basename(node.props[:entry].extname)
62
- if bare_basename.to_s == "index"
63
- @index_links << {
64
- parent_id: @subcollections[node.props[:entry].parent.to_s],
65
- index_attrs: meta.merge({ body: body})
66
- }
67
- else
68
- # Create an entity node representing a file mapped to a unique content object
69
- entity = graph.create_node do |entity_node|
70
-
71
- entity_slug = node.props[:entry].basename(node.props[:entry].extname).to_s
72
-
73
- entity_attrs = {
74
- name: entity_slug,
75
- title: entity_slug.gsub("-", " ").capitalize,
76
- body: body
77
- }
78
-
79
- populate_entity(entity_node, policy, entity_attrs.merge(meta || {}))
80
- end
81
-
82
- # We may not have an expanded node for the parent collection if this is a
83
- # preorder traversal so save it for later
84
- @entity_links << {
85
- parent_id: @subcollections[node.props[:entry].parent.to_s],
86
- child_id: entity
87
- }
88
- end
89
- end
90
- end
91
- end
92
- end
93
- end