bridgetown-core 0.20.0 → 0.21.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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
  ],