bridgetown-core 0.20.0 → 0.21.0.beta1

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bridgetown-core.rb +3 -0
  3. data/lib/bridgetown-core/collection.rb +13 -10
  4. data/lib/bridgetown-core/component.rb +178 -0
  5. data/lib/bridgetown-core/concerns/front_matter_importer.rb +52 -0
  6. data/lib/bridgetown-core/concerns/site/content.rb +2 -3
  7. data/lib/bridgetown-core/concerns/site/writable.rb +1 -1
  8. data/lib/bridgetown-core/concerns/validatable.rb +0 -4
  9. data/lib/bridgetown-core/configuration.rb +10 -9
  10. data/lib/bridgetown-core/converter.rb +9 -0
  11. data/lib/bridgetown-core/converters/erb_templates.rb +50 -34
  12. data/lib/bridgetown-core/converters/markdown.rb +1 -1
  13. data/lib/bridgetown-core/converters/ruby_templates.rb +17 -0
  14. data/lib/bridgetown-core/drops/relations_drop.rb +23 -0
  15. data/lib/bridgetown-core/drops/resource_drop.rb +3 -1
  16. data/lib/bridgetown-core/drops/unified_payload_drop.rb +1 -0
  17. data/lib/bridgetown-core/filters/from_liquid.rb +23 -0
  18. data/lib/bridgetown-core/helpers.rb +48 -9
  19. data/lib/bridgetown-core/layout.rb +27 -12
  20. data/lib/bridgetown-core/model/origin.rb +1 -1
  21. data/lib/bridgetown-core/model/{file_origin.rb → repo_origin.rb} +32 -25
  22. data/lib/bridgetown-core/reader.rb +2 -2
  23. data/lib/bridgetown-core/renderer.rb +1 -1
  24. data/lib/bridgetown-core/resource/base.rb +69 -27
  25. data/lib/bridgetown-core/resource/relations.rb +132 -0
  26. data/lib/bridgetown-core/resource/taxonomy_term.rb +10 -1
  27. data/lib/bridgetown-core/resource/taxonomy_type.rb +9 -0
  28. data/lib/bridgetown-core/resource/transformer.rb +14 -12
  29. data/lib/bridgetown-core/ruby_template_view.rb +7 -11
  30. data/lib/bridgetown-core/utils.rb +8 -1
  31. data/lib/bridgetown-core/utils/ruby_exec.rb +6 -9
  32. data/lib/bridgetown-core/utils/ruby_front_matter.rb +39 -0
  33. data/lib/bridgetown-core/version.rb +2 -2
  34. data/lib/bridgetown-core/watcher.rb +1 -1
  35. data/lib/site_template/package.json.erb +2 -2
  36. data/lib/site_template/src/_posts/0000-00-00-welcome-to-bridgetown.md.erb +1 -1
  37. data/lib/site_template/webpack.config.js.erb +3 -1
  38. metadata +10 -3
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Resource
5
+ class Relations
6
+ # @return [Bridgetown::Resource::Base]
7
+ attr_reader :resource
8
+
9
+ # @return [Bridgetown::Site]
10
+ attr_reader :site
11
+
12
+ # @param resource [Bridgetown::Resource::Base]
13
+ def initialize(resource)
14
+ @resource = resource
15
+ @site = resource.site
16
+ end
17
+
18
+ # @return [HashWithDotAccess::Hash]
19
+ def relation_schema
20
+ resource.collection.metadata.relations
21
+ end
22
+
23
+ # @return [Array<String>]
24
+ def relation_types
25
+ @relation_types ||= begin
26
+ types = []
27
+ relation_schema&.each do |_relation_type, collections|
28
+ types << collections
29
+ types << Array(collections).map { |item| ActiveSupport::Inflector.pluralize(item) }
30
+ end
31
+ types.flatten.uniq
32
+ end
33
+ end
34
+
35
+ # @param type [Symbol]
36
+ # @return [Bridgetown::Resource::Base, Array<Bridgetown::Resource::Base>]
37
+ def resources_for_type(type)
38
+ relation_kind = kind_of_relation_for_type(type)
39
+ return [] unless relation_kind
40
+
41
+ case relation_kind.to_sym
42
+ when :belongs_to
43
+ belongs_to_relation_for_type(type)
44
+ when :has_many
45
+ has_many_relation_for_type(type)
46
+ when :has_one
47
+ has_one_relation_for_type(type)
48
+ end
49
+ end
50
+
51
+ def method_missing(type, *args)
52
+ return super unless type.to_s.in?(relation_types)
53
+
54
+ resources_for_type(type)
55
+ end
56
+
57
+ def respond_to_missing?(type, *_args)
58
+ type.to_s.in?(relation_types)
59
+ end
60
+
61
+ def to_liquid
62
+ @to_liquid ||= Drops::RelationsDrop.new(self)
63
+ end
64
+
65
+ private
66
+
67
+ # @param type [Symbol]
68
+ # @return [String]
69
+ def kind_of_relation_for_type(type)
70
+ relation_schema&.each do |relation_type, collections|
71
+ collections = Array(collections).yield_self do |collections_arr|
72
+ collections_arr +
73
+ collections_arr.map { |item| ActiveSupport::Inflector.pluralize(item) }
74
+ end.flatten.uniq
75
+ return relation_type if collections.include?(type.to_s)
76
+ end
77
+ end
78
+
79
+ # @param type [Symbol]
80
+ # @return [Bridgetown::Collection]
81
+ def other_collection_for_type(type)
82
+ site.collections[type] || site.collections[ActiveSupport::Inflector.pluralize(type)]
83
+ end
84
+
85
+ # @return [Array<String>]
86
+ def collection_labels
87
+ [
88
+ resource.collection.label,
89
+ ActiveSupport::Inflector.singularize(resource.collection.label),
90
+ ]
91
+ end
92
+
93
+ # @param type [Symbol]
94
+ # @return [Bridgetown::Resource::Base, Array<Bridgetown::Resource::Base>]
95
+ def belongs_to_relation_for_type(type)
96
+ if resource.data[type].is_a?(Array)
97
+ other_collection_for_type(type).resources.select do |other_resource|
98
+ other_resource.data.slug.in?(resource.data[type])
99
+ end
100
+ else
101
+ other_collection_for_type(type).resources.find do |other_resource|
102
+ other_resource.data.slug == resource.data[type]
103
+ end
104
+ end
105
+ end
106
+
107
+ # @param type [Symbol]
108
+ # @return [Array<Bridgetown::Resource::Base>]
109
+ def has_many_relation_for_type(type) # rubocop:disable Naming/PredicateName
110
+ label, singular_label = collection_labels
111
+
112
+ other_collection_for_type(type).resources.select do |other_resource|
113
+ resource.data.slug.in?(
114
+ Array(other_resource.data[label] || other_resource.data[singular_label])
115
+ )
116
+ end
117
+ end
118
+
119
+ # @param type [Symbol]
120
+ # @return [Bridgetown::Resource::Base]
121
+ def has_one_relation_for_type(type) # rubocop:disable Naming/PredicateName
122
+ label, singular_label = collection_labels
123
+
124
+ other_collection_for_type(type).resources.find do |other_resource|
125
+ resource.data.slug.in?(
126
+ Array(other_resource.data[label] || other_resource.data[singular_label])
127
+ )
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -17,9 +17,18 @@ module Bridgetown
17
17
 
18
18
  def to_liquid
19
19
  {
20
- label: label,
20
+ "label" => label,
21
21
  }
22
22
  end
23
+ alias_method :to_h, :to_liquid
24
+
25
+ def as_json(*)
26
+ to_h
27
+ end
28
+
29
+ ruby2_keywords def to_json(*options)
30
+ as_json(*options).to_json(*options)
31
+ end
23
32
  end
24
33
  end
25
34
  end
@@ -42,6 +42,15 @@ module Bridgetown
42
42
  "metadata" => metadata,
43
43
  }
44
44
  end
45
+ alias_method :to_h, :to_liquid
46
+
47
+ def as_json(*)
48
+ to_h
49
+ end
50
+
51
+ ruby2_keywords def to_json(*options)
52
+ as_json(*options).to_json(*options)
53
+ end
45
54
  end
46
55
  end
47
56
  end
@@ -12,18 +12,20 @@ module Bridgetown
12
12
  # @return [Bridgetown::Site]
13
13
  attr_reader :site
14
14
 
15
- # @return [String]
16
- attr_reader :output_ext
17
-
18
15
  def initialize(resource)
19
16
  @resource = resource
20
17
  @site = resource.site
21
- execute_inline_ruby
22
- @output_ext = output_ext_from_converters
18
+ end
19
+
20
+ # @return [String]
21
+ def output_ext
22
+ @output_ext ||= output_ext_from_converters
23
23
  end
24
24
 
25
25
  # @return [String]
26
26
  def final_ext
27
+ output_ext # we always need this to get run
28
+
27
29
  permalink_ext || output_ext
28
30
  end
29
31
 
@@ -35,6 +37,12 @@ module Bridgetown
35
37
  end
36
38
  end
37
39
 
40
+ def execute_inline_ruby!
41
+ return unless site.config.should_execute_inline_ruby?
42
+
43
+ Bridgetown::Utils::RubyExec.search_data_for_ruby_code(resource, self)
44
+ end
45
+
38
46
  def inspect
39
47
  "#<#{self.class} Conversion Steps: #{conversions.length}>"
40
48
  end
@@ -102,12 +110,6 @@ module Bridgetown
102
110
 
103
111
  ### Transformation Actions
104
112
 
105
- def execute_inline_ruby
106
- return unless site.config.should_execute_inline_ruby?
107
-
108
- Bridgetown::Utils::RubyExec.search_data_for_ruby_code(resource, self)
109
- end
110
-
111
113
  def run_conversions # rubocop:disable Metrics/AbcSize
112
114
  input = resource.content.to_s
113
115
 
@@ -125,7 +127,7 @@ module Bridgetown
125
127
  output: Bridgetown.env.production? ? nil : output,
126
128
  output_ext: conversions[index][:output_ext],
127
129
  }
128
- output
130
+ output.html_safe
129
131
  rescue StandardError => e
130
132
  Bridgetown.logger.error "Conversion error:",
131
133
  "#{converter.class} encountered an error while "\
@@ -7,6 +7,7 @@ module Bridgetown
7
7
  require "bridgetown-core/helpers"
8
8
 
9
9
  attr_reader :layout, :page, :paginator, :site, :content
10
+ alias_method :resource, :page
10
11
 
11
12
  def initialize(convertible)
12
13
  if convertible.is_a?(Layout)
@@ -27,17 +28,10 @@ module Bridgetown
27
28
 
28
29
  def render(item, options = {}, &block)
29
30
  if item.respond_to?(:render_in)
30
- previous_buffer_state = @_erbout
31
- @_erbout = Bridgetown::ERBBuffer.new
32
-
33
- @in_view_component ||= defined?(::ViewComponent::Base) && item.is_a?(::ViewComponent::Base)
34
31
  result = item.render_in(self, &block)
35
- @in_view_component = false
36
-
37
- @_erbout = previous_buffer_state
38
- result
32
+ result&.html_safe
39
33
  else
40
- partial(item, options, &block)
34
+ partial(item, options, &block)&.html_safe
41
35
  end
42
36
  end
43
37
 
@@ -60,14 +54,15 @@ module Bridgetown
60
54
  Bridgetown.logger.warn "Liquid Warning:",
61
55
  LiquidRenderer.format_error(e, path || document.relative_path)
62
56
  end
63
- template.render!(options.deep_stringify_keys, _liquid_context)
57
+ template.render!(options.deep_stringify_keys, _liquid_context).html_safe
64
58
  end
65
59
 
66
60
  def helpers
67
61
  @helpers ||= Helpers.new(self, site)
68
62
  end
69
63
 
70
- def method_missing(method, *args, &block)
64
+ # rubocop:disable Style/MissingRespondToMissing
65
+ ruby2_keywords def method_missing(method, *args, &block)
71
66
  if helpers.respond_to?(method.to_sym)
72
67
  helpers.send method.to_sym, *args, &block
73
68
  else
@@ -78,6 +73,7 @@ module Bridgetown
78
73
  def respond_to_missing?(method, include_private = false)
79
74
  helpers.respond_to?(method.to_sym, include_private) || super
80
75
  end
76
+ # rubocop:enable Style/MissingRespondToMissing
81
77
 
82
78
  private
83
79
 
@@ -5,6 +5,7 @@ module Bridgetown
5
5
  extend self
6
6
  autoload :Ansi, "bridgetown-core/utils/ansi"
7
7
  autoload :RubyExec, "bridgetown-core/utils/ruby_exec"
8
+ autoload :RubyFrontMatterDSL, "bridgetown-core/utils/ruby_front_matter"
8
9
  autoload :Platforms, "bridgetown-core/utils/platforms"
9
10
  autoload :ThreadEvent, "bridgetown-core/utils/thread_event"
10
11
 
@@ -118,7 +119,13 @@ module Bridgetown
118
119
  # @return [Boolean] if the YAML front matter is present.
119
120
  # rubocop: disable Naming/PredicateName
120
121
  def has_yaml_header?(file)
121
- File.open(file, "rb", &:readline).match? %r!\A---\s*\r?\n!
122
+ File.open(file, "rb", &:readline).match? Bridgetown::FrontMatterImporter::YAML_HEADER
123
+ rescue EOFError
124
+ false
125
+ end
126
+
127
+ def has_rbfm_header?(file)
128
+ File.open(file, "rb", &:readline).match? Bridgetown::FrontMatterImporter::RUBY_HEADER
122
129
  rescue EOFError
123
130
  false
124
131
  end
@@ -5,8 +5,8 @@ module Bridgetown
5
5
  module RubyExec
6
6
  extend self
7
7
 
8
- # rubocop:disable Metrics/AbcSize
9
- def search_data_for_ruby_code(convertible, renderer)
8
+ # TODO: Deprecate storing Ruby code in YAML, Rb, etc. and just use native Ruby Front Matter
9
+ def search_data_for_ruby_code(convertible, renderer) # rubocop:todo Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
10
10
  return if convertible.data.empty?
11
11
 
12
12
  # Iterate using `keys` here so inline Ruby script can add new data keys
@@ -14,24 +14,21 @@ module Bridgetown
14
14
  data_keys = convertible.data.keys
15
15
  data_keys.each do |k|
16
16
  v = convertible.data[k]
17
- next unless v.is_a?(Rb) || v.is_a?(Hash)
17
+ next unless v.is_a?(Rb) || v.is_a?(Hash) || v.is_a?(Proc)
18
18
 
19
- if v.is_a?(Hash)
19
+ if v.is_a?(Proc)
20
+ convertible.data[k] = convertible.instance_exec(&v)
21
+ elsif v.is_a?(Hash)
20
22
  v.each do |nested_k, nested_v|
21
23
  next unless nested_v.is_a?(Rb)
22
24
 
23
- Bridgetown.logger.debug("Executing inline Ruby…", convertible.relative_path)
24
25
  convertible.data[k][nested_k] = run(nested_v, convertible, renderer)
25
- Bridgetown.logger.debug("Inline Ruby completed!", convertible.relative_path)
26
26
  end
27
27
  else
28
- Bridgetown.logger.debug("Executing inline Ruby…", convertible.relative_path)
29
28
  convertible.data[k] = run(v, convertible, renderer)
30
- Bridgetown.logger.debug("Inline Ruby completed!", convertible.relative_path)
31
29
  end
32
30
  end
33
31
  end
34
- # rubocop:enable Metrics/AbcSize
35
32
 
36
33
  # Sets up a new context in which to eval Ruby coming from front matter.
37
34
  #
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Utils
5
+ module RubyFrontMatterDSL
6
+ def front_matter(&block)
7
+ RubyFrontMatter.new.tap { |fm| fm.instance_exec(&block) }
8
+ end
9
+ end
10
+
11
+ class RubyFrontMatter
12
+ def initialize
13
+ @data = {}
14
+ end
15
+
16
+ def method_missing(key, value) # rubocop:disable Style/MissingRespondToMissing
17
+ return super if respond_to?(key)
18
+
19
+ set(key, value)
20
+ end
21
+
22
+ def each(&block)
23
+ @data.each(&block)
24
+ end
25
+
26
+ def get(key)
27
+ @data[key]
28
+ end
29
+
30
+ def set(key, value)
31
+ @data[key] = value
32
+ end
33
+
34
+ def to_h
35
+ @data
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bridgetown
4
- VERSION = "0.20.0"
5
- CODE_NAME = "Healy Heights"
4
+ VERSION = "0.21.0.beta1"
5
+ CODE_NAME = "Broughton Beach"
6
6
  end
@@ -140,7 +140,7 @@ module Bridgetown
140
140
  if options[:trace]
141
141
  Bridgetown.logger.info e.backtrace.join("\n")
142
142
  else
143
- Bridgetown.logger.warn "Error:", "Use the --trace option for more information."
143
+ Bridgetown.logger.warn "Backtrace:", "Use the --trace option for more information."
144
144
  end
145
145
  end
146
146
  Bridgetown.logger.info ""
@@ -30,8 +30,8 @@
30
30
  "postcss-loader": "^4.1.0",
31
31
  "postcss-preset-env": "^6.7.0",
32
32
  <% else %>
33
- "node-sass": "^4.13.1",
34
- "sass-loader": "^8.0.2",
33
+ "sass": "^1.32.8",
34
+ "sass-loader": "^8.0.2",
35
35
  <% end %>
36
36
  "webpack": "^4.44.2",
37
37
  "webpack-cli": "^3.3.11",
@@ -21,6 +21,6 @@ def print_hi(name)
21
21
  end
22
22
  print_hi('Tom')
23
23
  #=> prints 'Hi, Tom' to STDOUT.
24
- ````
24
+ ```
25
25
 
26
26
  Check out the [Bridgetown docs](https://bridgetownrb.com/docs/) for more info on how to get the most out of Bridgetown. File all bugs/feature requests at [Bridgetown’s GitHub repo](https://github.com/bridgetownrb/bridgetown). If you have questions, you can ask them on [Bridgetown Discussions on GitHub](https://github.com/bridgetownrb/bridgetown/discussions).
@@ -72,7 +72,7 @@ module.exports = {
72
72
  },
73
73
  "postcss-loader"
74
74
  ],
75
- },
75
+ },
76
76
  <% else %>
77
77
  {
78
78
  test: /\.(s[ac]|c)ss$/,
@@ -87,7 +87,9 @@ module.exports = {
87
87
  {
88
88
  loader: "sass-loader",
89
89
  options: {
90
+ implementation: require("sass"),
90
91
  sassOptions: {
92
+ fiber: false,
91
93
  includePaths: [
92
94
  path.resolve(__dirname, "src/_components")
93
95
  ],