bridgetown-core 0.15.0.beta4 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +14 -0
  3. data/bridgetown-core.gemspec +3 -1
  4. data/lib/bridgetown-core.rb +7 -1
  5. data/lib/bridgetown-core/commands/concerns/actions.rb +2 -1
  6. data/lib/bridgetown-core/commands/console.rb +4 -4
  7. data/lib/bridgetown-core/concerns/data_accessible.rb +19 -0
  8. data/lib/bridgetown-core/concerns/layout_placeable.rb +17 -0
  9. data/lib/bridgetown-core/concerns/liquid_renderable.rb +20 -0
  10. data/lib/bridgetown-core/concerns/publishable.rb +10 -0
  11. data/lib/bridgetown-core/concerns/site/configurable.rb +66 -31
  12. data/lib/bridgetown-core/concerns/site/content.rb +88 -29
  13. data/lib/bridgetown-core/concerns/site/extensible.rb +15 -12
  14. data/lib/bridgetown-core/concerns/site/localizable.rb +20 -0
  15. data/lib/bridgetown-core/concerns/site/processable.rb +12 -10
  16. data/lib/bridgetown-core/concerns/site/renderable.rb +21 -2
  17. data/lib/bridgetown-core/concerns/site/writable.rb +16 -2
  18. data/lib/bridgetown-core/concerns/validatable.rb +59 -0
  19. data/lib/bridgetown-core/configuration.rb +5 -2
  20. data/lib/bridgetown-core/converter.rb +34 -0
  21. data/lib/bridgetown-core/converters/erb_templates.rb +78 -0
  22. data/lib/bridgetown-core/converters/markdown.rb +6 -23
  23. data/lib/bridgetown-core/converters/smartypants.rb +0 -10
  24. data/lib/bridgetown-core/document.rb +8 -52
  25. data/lib/bridgetown-core/drops/site_drop.rb +1 -1
  26. data/lib/bridgetown-core/errors.rb +2 -0
  27. data/lib/bridgetown-core/excerpt.rb +1 -6
  28. data/lib/bridgetown-core/filters.rb +3 -48
  29. data/lib/bridgetown-core/filters/condition_helpers.rb +56 -0
  30. data/lib/bridgetown-core/frontmatter_defaults.rb +17 -0
  31. data/lib/bridgetown-core/layout.rb +24 -1
  32. data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -1
  33. data/lib/bridgetown-core/page.rb +33 -24
  34. data/lib/bridgetown-core/plugin_manager.rb +10 -2
  35. data/lib/bridgetown-core/reader.rb +1 -0
  36. data/lib/bridgetown-core/readers/collection_reader.rb +1 -0
  37. data/lib/bridgetown-core/readers/data_reader.rb +1 -0
  38. data/lib/bridgetown-core/readers/defaults_reader.rb +27 -0
  39. data/lib/bridgetown-core/readers/layout_reader.rb +1 -0
  40. data/lib/bridgetown-core/readers/page_reader.rb +1 -0
  41. data/lib/bridgetown-core/readers/post_reader.rb +1 -0
  42. data/lib/bridgetown-core/readers/static_file_reader.rb +1 -0
  43. data/lib/bridgetown-core/regenerator.rb +1 -1
  44. data/lib/bridgetown-core/renderer.rb +38 -12
  45. data/lib/bridgetown-core/ruby_template_view.rb +102 -0
  46. data/lib/bridgetown-core/site.rb +2 -0
  47. data/lib/bridgetown-core/tags/class_map.rb +90 -0
  48. data/lib/bridgetown-core/tags/find.rb +86 -0
  49. data/lib/bridgetown-core/tags/t.rb +14 -0
  50. data/lib/bridgetown-core/tags/webpack_path.rb +19 -22
  51. data/lib/bridgetown-core/utils.rb +55 -2
  52. data/lib/bridgetown-core/version.rb +2 -2
  53. data/lib/site_template/src/_layouts/{default.html → default.liquid} +0 -0
  54. data/lib/site_template/src/_layouts/{home.html → home.liquid} +0 -0
  55. data/lib/site_template/src/_layouts/{page.html → page.liquid} +0 -0
  56. data/lib/site_template/src/_layouts/{post.html → post.liquid} +0 -0
  57. metadata +50 -10
  58. data/lib/bridgetown-core/concerns/convertible.rb +0 -235
@@ -30,16 +30,6 @@ module Bridgetown
30
30
  @config[:input] = :SmartyPants
31
31
  end
32
32
 
33
- # Does the given extension match this converter's list of acceptable extensions?
34
- # Takes one argument: the file's extension (including the dot).
35
- #
36
- # ext - The String extension to check.
37
- #
38
- # Returns true if it matches, false otherwise.
39
- def matches(_ext)
40
- false
41
- end
42
-
43
33
  # Public: The extension to be given to the output file (including the dot).
44
34
  #
45
35
  # ext - The String extension or original file.
@@ -2,8 +2,12 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Document
5
- include Comparable
6
5
  extend Forwardable
6
+ include DataAccessible
7
+ include Comparable
8
+ include LayoutPlaceable
9
+ include LiquidRenderable
10
+ include Publishable
7
11
 
8
12
  attr_reader :path, :site, :extname, :collection, :type
9
13
  attr_accessor :content, :output
@@ -95,6 +99,9 @@ module Bridgetown
95
99
  @relative_path ||= path.sub("#{site.collections_path}/", "")
96
100
  end
97
101
 
102
+ # FIXME: spinning up a new Renderer object just to get an extension
103
+ # seems excessive
104
+ #
98
105
  # The output extension of the document.
99
106
  #
100
107
  # Returns the output extension
@@ -143,38 +150,6 @@ module Bridgetown
143
150
  YAML_FILE_EXTS.include?(extname)
144
151
  end
145
152
 
146
- # TODO: Depricated
147
- # Used to determine CoffeeScript and Sass/SCSS files.
148
- def asset_file?
149
- false
150
- end
151
-
152
- # Determine whether the file should be rendered with Liquid.
153
- #
154
- # Returns false if the document is either an asset file or a yaml file,
155
- # or if the document doesn't contain any Liquid Tags or Variables,
156
- # true otherwise.
157
- def render_with_liquid?
158
- return false if data["render_with_liquid"] == false
159
-
160
- !(yaml_file? || !Utils.has_liquid_construct?(content))
161
- end
162
-
163
- # Determine whether the file should be rendered with a layout.
164
- #
165
- # Returns true if the Front Matter specifies that `layout` is set to `none`.
166
- def no_layout?
167
- data["layout"] == "none"
168
- end
169
-
170
- # Determine whether the file should be placed into layouts.
171
- #
172
- # Returns false if the document is set to `layouts: none`, or is either an
173
- # asset file or a yaml file. Returns true otherwise.
174
- def place_in_layout?
175
- !(asset_file? || yaml_file? || no_layout?)
176
- end
177
-
178
153
  # The URL template where the document would be accessible.
179
154
  #
180
155
  # Returns the URL template for the document.
@@ -209,10 +184,6 @@ module Bridgetown
209
184
  ).to_s
210
185
  end
211
186
 
212
- def [](key)
213
- data[key]
214
- end
215
-
216
187
  # The full path to the output file.
217
188
  #
218
189
  # base_directory - the base path of the output directory
@@ -243,14 +214,6 @@ module Bridgetown
243
214
  trigger_hooks(:post_write)
244
215
  end
245
216
 
246
- # Whether the file is published or not, as indicated in YAML front-matter
247
- #
248
- # Returns 'false' if the 'published' key is specified in the
249
- # YAML front-matter and is 'false'. Otherwise returns 'true'.
250
- def published?
251
- !(data.key?("published") && data["published"] == false)
252
- end
253
-
254
217
  # Read in the file and assign the content and data based on the file contents.
255
218
  # Merge the frontmatter of the file with the frontmatter default
256
219
  # values
@@ -287,13 +250,6 @@ module Bridgetown
287
250
  "#<#{self.class} #{relative_path} collection=#{collection.label}>"
288
251
  end
289
252
 
290
- # The string representation for this document.
291
- #
292
- # Returns the content of the document
293
- def to_s
294
- output || content || "NO CONTENT"
295
- end
296
-
297
253
  # Compare this document against another document.
298
254
  # Comparison is a comparison between the 2 paths of the documents.
299
255
  #
@@ -8,7 +8,7 @@ module Bridgetown
8
8
  mutable false
9
9
 
10
10
  def_delegator :@obj, :data
11
- def_delegators :@obj, :time, :pages, :static_files, :tags, :categories
11
+ def_delegators :@obj, :locale, :time, :pages, :static_files, :tags, :categories
12
12
 
13
13
  private def_delegator :@obj, :config, :fallback_data
14
14
 
@@ -16,5 +16,7 @@ module Bridgetown
16
16
  PostURLError = Class.new(FatalException)
17
17
  InvalidURLError = Class.new(FatalException)
18
18
  InvalidConfigurationError = Class.new(FatalException)
19
+
20
+ WebpackAssetError = Class.new(FatalException)
19
21
  end
20
22
  end
@@ -3,6 +3,7 @@
3
3
  module Bridgetown
4
4
  class Excerpt
5
5
  extend Forwardable
6
+ include LiquidRenderable
6
7
 
7
8
  attr_accessor :doc
8
9
  attr_accessor :content, :ext
@@ -91,12 +92,6 @@ module Bridgetown
91
92
  false
92
93
  end
93
94
 
94
- def render_with_liquid?
95
- return false if data["render_with_liquid"] == false
96
-
97
- !(yaml_file? || !Utils.has_liquid_construct?(content))
98
- end
99
-
100
95
  protected
101
96
 
102
97
  # Internal: Extract excerpt from the content
@@ -7,6 +7,7 @@ module Bridgetown
7
7
  include URLFilters
8
8
  include GroupingFilters
9
9
  include DateFilters
10
+ include ConditionHelpers
10
11
 
11
12
  # Convert a Markdown string into HTML output.
12
13
  #
@@ -30,6 +31,7 @@ module Bridgetown
30
31
  ).convert(input.to_s)
31
32
  end
32
33
 
34
+ # TODO: This should be removed, there is no Sass converter
33
35
  # Convert a Sass string into CSS output.
34
36
  #
35
37
  # input - The Sass String to convert.
@@ -41,6 +43,7 @@ module Bridgetown
41
43
  ).convert(input)
42
44
  end
43
45
 
46
+ # TODO: This should be removed, there is no Scss converter
44
47
  # Convert a Scss string into CSS output.
45
48
  #
46
49
  # input - The Scss String to convert.
@@ -421,54 +424,6 @@ module Bridgetown
421
424
  end
422
425
  end
423
426
  end
424
-
425
- # ----------- The following set of code was *adapted* from Liquid::If
426
- # ----------- ref: https://git.io/vp6K6
427
-
428
- # Parse a string to a Liquid Condition
429
- def parse_condition(exp)
430
- parser = Liquid::Parser.new(exp)
431
- condition = parse_binary_comparison(parser)
432
-
433
- parser.consume(:end_of_string)
434
- condition
435
- end
436
-
437
- # Generate a Liquid::Condition object from a Liquid::Parser object additionally processing
438
- # the parsed expression based on whether the expression consists of binary operations with
439
- # Liquid operators `and` or `or`
440
- #
441
- # - parser: an instance of Liquid::Parser
442
- #
443
- # Returns an instance of Liquid::Condition
444
- def parse_binary_comparison(parser)
445
- condition = parse_comparison(parser)
446
- first_condition = condition
447
- while (binary_operator = parser.id?("and") || parser.id?("or"))
448
- child_condition = parse_comparison(parser)
449
- condition.send(binary_operator, child_condition)
450
- condition = child_condition
451
- end
452
- first_condition
453
- end
454
-
455
- # Generates a Liquid::Condition object from a Liquid::Parser object based on whether the parsed
456
- # expression involves a "comparison" operator (e.g. <, ==, >, !=, etc)
457
- #
458
- # - parser: an instance of Liquid::Parser
459
- #
460
- # Returns an instance of Liquid::Condition
461
- def parse_comparison(parser)
462
- left_operand = Liquid::Expression.parse(parser.expression)
463
- operator = parser.consume?(:comparison)
464
-
465
- # No comparison-operator detected. Initialize a Liquid::Condition using only left operand
466
- return Liquid::Condition.new(left_operand) unless operator
467
-
468
- # Parse what remained after extracting the left operand and the `:comparison` operator
469
- # and initialize a Liquid::Condition object using the operands and the comparison-operator
470
- Liquid::Condition.new(left_operand, operator, Liquid::Expression.parse(parser.expression))
471
- end
472
427
  end
473
428
  end
474
429
 
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Filters
5
+ module ConditionHelpers
6
+ # ----------- The following set of code was *adapted* from Liquid::If
7
+ # ----------- ref: https://git.io/vp6K6
8
+
9
+ # Parse a string to a Liquid Condition
10
+ def parse_condition(exp)
11
+ parser = Liquid::Parser.new(exp)
12
+ condition = parse_binary_comparison(parser)
13
+
14
+ parser.consume(:end_of_string)
15
+ condition
16
+ end
17
+
18
+ # Generate a Liquid::Condition object from a Liquid::Parser object additionally processing
19
+ # the parsed expression based on whether the expression consists of binary operations with
20
+ # Liquid operators `and` or `or`
21
+ #
22
+ # - parser: an instance of Liquid::Parser
23
+ #
24
+ # Returns an instance of Liquid::Condition
25
+ def parse_binary_comparison(parser)
26
+ condition = parse_comparison(parser)
27
+ first_condition = condition
28
+ while (binary_operator = parser.id?("and") || parser.id?("or"))
29
+ child_condition = parse_comparison(parser)
30
+ condition.send(binary_operator, child_condition)
31
+ condition = child_condition
32
+ end
33
+ first_condition
34
+ end
35
+
36
+ # Generates a Liquid::Condition object from a Liquid::Parser object based
37
+ # on whether the parsed expression involves a "comparison" operator
38
+ # (e.g. <, ==, >, !=, etc)
39
+ #
40
+ # - parser: an instance of Liquid::Parser
41
+ #
42
+ # Returns an instance of Liquid::Condition
43
+ def parse_comparison(parser)
44
+ left_operand = Liquid::Expression.parse(parser.expression)
45
+ operator = parser.consume?(:comparison)
46
+
47
+ # No comparison-operator detected. Initialize a Liquid::Condition using only left operand
48
+ return Liquid::Condition.new(left_operand) unless operator
49
+
50
+ # Parse what remained after extracting the left operand and the `:comparison` operator
51
+ # and initialize a Liquid::Condition object using the operands and the comparison-operator
52
+ Liquid::Condition.new(left_operand, operator, Liquid::Expression.parse(parser.expression))
53
+ end
54
+ end
55
+ end
56
+ end
@@ -54,6 +54,10 @@ module Bridgetown
54
54
  #
55
55
  # Returns the default value or nil if none was found
56
56
  def find(path, type, setting)
57
+ merged_data = {}
58
+ merge_data_cascade_for_path(path, merged_data)
59
+ return merged_data[setting] if merged_data.key?(setting)
60
+
57
61
  value = nil
58
62
  old_scope = nil
59
63
 
@@ -74,6 +78,9 @@ module Bridgetown
74
78
  # Returns a hash with all default values (an empty hash if there are none)
75
79
  def all(path, type)
76
80
  defaults = {}
81
+
82
+ merge_data_cascade_for_path(path, defaults)
83
+
77
84
  old_scope = nil
78
85
  matching_sets(path, type).each do |set|
79
86
  if has_precedence?(old_scope, set["scope"])
@@ -88,6 +95,16 @@ module Bridgetown
88
95
 
89
96
  private
90
97
 
98
+ def merge_data_cascade_for_path(path, merged_data)
99
+ absolute_path = @site.in_source_dir(path)
100
+ @site.defaults_reader.path_defaults
101
+ .select { |k, _v| absolute_path.include? k }
102
+ .sort_by { |k, _v| k.length }
103
+ .each do |defaults|
104
+ merged_data.merge!(defaults[1])
105
+ end
106
+ end
107
+
91
108
  # Checks if a given default setting scope matches the given path and type
92
109
  #
93
110
  # scope - the hash indicating the scope, as defined in bridgetown.config.yml
@@ -2,7 +2,9 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Layout
5
- include Convertible
5
+ include DataAccessible
6
+ include LiquidRenderable
7
+ include Validatable
6
8
 
7
9
  # Gets the Site object.
8
10
  attr_reader :site
@@ -25,6 +27,12 @@ module Bridgetown
25
27
  # Gets/Sets the content of this layout.
26
28
  attr_accessor :content
27
29
 
30
+ # Gets/Sets the current document (for layout-compatible converters)
31
+ attr_accessor :current_document
32
+
33
+ # Gets/Sets the document output (for layout-compatible converters)
34
+ attr_accessor :current_document_output
35
+
28
36
  # Initialize a new Layout.
29
37
  #
30
38
  # site - The Site.
@@ -51,6 +59,14 @@ module Bridgetown
51
59
  read_yaml(base, name)
52
60
  end
53
61
 
62
+ # The inspect string for this document.
63
+ # Includes the relative path and the collection label.
64
+ #
65
+ # Returns the inspect string for this document.
66
+ def inspect
67
+ "#<#{self.class} #{@path}>"
68
+ end
69
+
54
70
  # Extract information from the layout filename.
55
71
  #
56
72
  # name - The String filename of the layout file.
@@ -59,5 +75,12 @@ module Bridgetown
59
75
  def process(name)
60
76
  self.ext = File.extname(name)
61
77
  end
78
+
79
+ # Provide this Layout's data to a Hash suitable for use by Liquid.
80
+ #
81
+ # Returns the Hash representation of this Layout.
82
+ def to_liquid
83
+ data
84
+ end
62
85
  end
63
86
  end
@@ -32,7 +32,7 @@ module Bridgetown
32
32
 
33
33
  # Last path in the list wins
34
34
  LiquidComponent.parse(
35
- ::File.read(found_paths.last, site.file_read_opts)
35
+ ::File.read(found_paths.last, **site.file_read_opts)
36
36
  ).content
37
37
  end
38
38
  end
@@ -2,7 +2,11 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Page
5
- include Convertible
5
+ include DataAccessible
6
+ include LayoutPlaceable
7
+ include LiquidRenderable
8
+ include Publishable
9
+ include Validatable
6
10
 
7
11
  attr_writer :dir
8
12
  attr_accessor :site, :pager
@@ -11,15 +15,6 @@ module Bridgetown
11
15
 
12
16
  alias_method :extname, :ext
13
17
 
14
- # Attributes for Liquid templates
15
- ATTRIBUTES_FOR_LIQUID = %w(
16
- content
17
- dir
18
- name
19
- path
20
- url
21
- ).freeze
22
-
23
18
  # A set of extensions that are considered HTML or HTML-like so we
24
19
  # should not alter them, this includes .xhtml through XHTM5.
25
20
 
@@ -143,19 +138,6 @@ module Bridgetown
143
138
  self.basename = name[0..-ext.length - 1].gsub(%r!\.*\z!, "")
144
139
  end
145
140
 
146
- # Add any necessary layouts to this post
147
- #
148
- # layouts - The Hash of {"name" => "layout"}.
149
- # site_payload - The site payload Hash.
150
- #
151
- # Returns String rendered page.
152
- def render(layouts, site_payload)
153
- site_payload["page"] = to_liquid
154
- site_payload["paginator"] = pager.to_liquid
155
-
156
- do_layout(site_payload, layouts)
157
- end
158
-
159
141
  # The path to the source file
160
142
  #
161
143
  # Returns the path to the source file
@@ -168,6 +150,16 @@ module Bridgetown
168
150
  @relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).delete_prefix("/")
169
151
  end
170
152
 
153
+ # FIXME: spinning up a new Renderer object just to get an extension
154
+ # seems excessive
155
+ #
156
+ # The output extension of the page.
157
+ #
158
+ # Returns the output extension
159
+ def output_ext
160
+ @output_ext ||= Bridgetown::Renderer.new(site, self).output_ext
161
+ end
162
+
171
163
  # Obtain destination path.
172
164
  #
173
165
  # dest - The String path to the destination dir.
@@ -180,9 +172,22 @@ module Bridgetown
180
172
  path
181
173
  end
182
174
 
175
+ # Write the generated page file to the destination directory.
176
+ #
177
+ # dest - The String path to the destination dir.
178
+ #
179
+ # Returns nothing.
180
+ def write(dest)
181
+ path = destination(dest)
182
+ FileUtils.mkdir_p(File.dirname(path))
183
+ Bridgetown.logger.debug "Writing:", path
184
+ File.write(path, output, mode: "wb")
185
+ Bridgetown::Hooks.trigger :pages, :post_write, self
186
+ end
187
+
183
188
  # Returns the object as a debug String.
184
189
  def inspect
185
- "#<#{self.class} @relative_path=#{relative_path.inspect}>"
190
+ "#<#{self.class} #{relative_path}>"
186
191
  end
187
192
 
188
193
  # Returns the Boolean of whether this Page is HTML or not.
@@ -199,6 +204,10 @@ module Bridgetown
199
204
  Bridgetown::Hooks.trigger :pages, hook_name, self, *args
200
205
  end
201
206
 
207
+ def type
208
+ :pages
209
+ end
210
+
202
211
  def write?
203
212
  true
204
213
  end