bridgetown-core 0.15.0.beta1 → 0.16.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +14 -0
  3. data/bridgetown-core.gemspec +2 -0
  4. data/lib/bridgetown-core.rb +6 -1
  5. data/lib/bridgetown-core/commands/concerns/actions.rb +54 -21
  6. data/lib/bridgetown-core/commands/console.rb +12 -2
  7. data/lib/bridgetown-core/commands/serve.rb +5 -0
  8. data/lib/bridgetown-core/concerns/data_accessible.rb +19 -0
  9. data/lib/bridgetown-core/concerns/layout_placeable.rb +17 -0
  10. data/lib/bridgetown-core/concerns/liquid_renderable.rb +20 -0
  11. data/lib/bridgetown-core/concerns/publishable.rb +10 -0
  12. data/lib/bridgetown-core/concerns/site/configurable.rb +62 -31
  13. data/lib/bridgetown-core/concerns/site/content.rb +88 -29
  14. data/lib/bridgetown-core/concerns/site/extensible.rb +15 -12
  15. data/lib/bridgetown-core/concerns/site/processable.rb +12 -10
  16. data/lib/bridgetown-core/concerns/site/renderable.rb +23 -4
  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 +1 -0
  20. data/lib/bridgetown-core/converter.rb +34 -0
  21. data/lib/bridgetown-core/converters/erb_templates.rb +61 -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/document_drop.rb +9 -1
  26. data/lib/bridgetown-core/drops/page_drop.rb +1 -1
  27. data/lib/bridgetown-core/errors.rb +2 -0
  28. data/lib/bridgetown-core/excerpt.rb +5 -7
  29. data/lib/bridgetown-core/filters.rb +2 -0
  30. data/lib/bridgetown-core/layout.rb +24 -1
  31. data/lib/bridgetown-core/liquid_renderer/file.rb +1 -4
  32. data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -1
  33. data/lib/bridgetown-core/page.rb +36 -42
  34. data/lib/bridgetown-core/plugin_manager.rb +27 -13
  35. data/lib/bridgetown-core/regenerator.rb +1 -1
  36. data/lib/bridgetown-core/renderer.rb +41 -15
  37. data/lib/bridgetown-core/ruby_template_view.rb +84 -0
  38. data/lib/bridgetown-core/tags/class_map.rb +90 -0
  39. data/lib/bridgetown-core/tags/include.rb +2 -0
  40. data/lib/bridgetown-core/tags/render_content.rb +14 -2
  41. data/lib/bridgetown-core/tags/webpack_path.rb +48 -16
  42. data/lib/bridgetown-core/utils.rb +44 -0
  43. data/lib/bridgetown-core/version.rb +2 -2
  44. data/lib/site_template/bridgetown.config.yml +5 -3
  45. data/lib/site_template/package.json +1 -0
  46. data/lib/site_template/src/_components/{footer.html → footer.liquid} +0 -0
  47. data/lib/site_template/src/_components/{head.html → head.liquid} +0 -0
  48. data/lib/site_template/src/_components/{navbar.html → navbar.liquid} +0 -0
  49. data/lib/site_template/src/_layouts/default.html +1 -1
  50. data/lib/site_template/webpack.config.js +3 -3
  51. metadata +41 -6
  52. data/lib/bridgetown-core/concerns/convertible.rb +0 -238
@@ -2,6 +2,20 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Converter < Plugin
5
+ class << self
6
+ attr_accessor :extname_list
7
+
8
+ # Converters can provide one or more extensions they accept. Examples:
9
+ #
10
+ # * `input :erb`
11
+ # * `input %i(xls xlsx)`
12
+ def input(extnames)
13
+ extnames = Array(extnames)
14
+ self.extname_list ||= []
15
+ self.extname_list += extnames.map { |e| ".#{e.to_s.downcase}" }
16
+ end
17
+ end
18
+
5
19
  # Public: Get or set the highlighter prefix. When an argument is specified,
6
20
  # the prefix will be set. If no argument is specified, the current prefix
7
21
  # will be returned.
@@ -37,6 +51,26 @@ module Bridgetown
37
51
  @config = config
38
52
  end
39
53
 
54
+ # Does the given extension match this converter's list of acceptable extensions?
55
+ #
56
+ # @param [String] ext
57
+ # The file's extension (including the dot)
58
+ #
59
+ # @return [Boolean] Whether the extension matches one in the list
60
+ def matches(ext)
61
+ (self.class.extname_list || []).include?(ext.downcase)
62
+ end
63
+
64
+ # You can override this in Converter subclasses as needed. Default is ".html"
65
+ #
66
+ # @param [String] ext
67
+ # The extension of the original file
68
+ #
69
+ # @return [String] The output file extension (including the dot)
70
+ def output_ext(_ext)
71
+ ".html"
72
+ end
73
+
40
74
  # Get the highlighter prefix.
41
75
  #
42
76
  # Returns the String prefix.
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tilt/erb"
4
+ require "active_support/core_ext/hash/keys"
5
+
6
+ module Bridgetown
7
+ class ERBView < RubyTemplateView
8
+ include ERB::Util
9
+
10
+ def partial(partial_name, options = {})
11
+ options.merge!(options[:locals]) if options[:locals]
12
+
13
+ partial_segments = partial_name.split("/")
14
+ partial_segments.last.sub!(%r!^!, "_")
15
+ partial_name = partial_segments.join("/")
16
+
17
+ Tilt::ERBTemplate.new(
18
+ site.in_source_dir(site.config[:partials_dir], "#{partial_name}.erb"),
19
+ trim: "<>-",
20
+ outvar: "@_erbout"
21
+ ).render(self, options)
22
+ end
23
+
24
+ def markdownify
25
+ previous_buffer_state = @_erbout
26
+ @_erbout = +""
27
+ result = yield
28
+ @_erbout = previous_buffer_state
29
+
30
+ content = Bridgetown::Utils.reindent_for_markdown(result)
31
+ converter = site.find_converter_instance(Bridgetown::Converters::Markdown)
32
+ md_output = converter.convert(content).strip
33
+ @_erbout << md_output
34
+ end
35
+ end
36
+
37
+ module Converters
38
+ class ERBTemplates < Converter
39
+ input :erb
40
+
41
+ # Logic to do the content conversion.
42
+ #
43
+ # content - String content of file (without front matter).
44
+ #
45
+ # Returns a String of the converted content.
46
+ def convert(content, convertible)
47
+ erb_view = Bridgetown::ERBView.new(convertible)
48
+
49
+ erb_renderer = Tilt::ERBTemplate.new(trim: "<>-", outvar: "@_erbout") { content }
50
+
51
+ if convertible.is_a?(Bridgetown::Layout)
52
+ erb_renderer.render(erb_view) do
53
+ convertible.current_document_output
54
+ end
55
+ else
56
+ erb_renderer.render(erb_view)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -8,6 +8,12 @@ module Bridgetown
8
8
  highlighter_prefix "\n"
9
9
  highlighter_suffix "\n"
10
10
 
11
+ def initialize(config = {})
12
+ super
13
+
14
+ self.class.input @config["markdown_ext"].split(",")
15
+ end
16
+
11
17
  def setup
12
18
  return if @setup ||= false
13
19
 
@@ -51,25 +57,6 @@ module Bridgetown
51
57
  self.class.constants - [:KramdownParser, :PRIORITIES]
52
58
  end
53
59
 
54
- # Does the given extension match this converter's list of acceptable extensions?
55
- # Takes one argument: the file's extension (including the dot).
56
- #
57
- # ext - The String extension to check.
58
- #
59
- # Returns true if it matches, false otherwise.
60
- def matches(ext)
61
- extname_list.include?(ext.downcase)
62
- end
63
-
64
- # Public: The extension to be given to the output file (including the dot).
65
- #
66
- # ext - The String extension or original file.
67
- #
68
- # Returns The String output file extension.
69
- def output_ext(_ext)
70
- ".html"
71
- end
72
-
73
60
  # Logic to do the content conversion.
74
61
  #
75
62
  # content - String content of file (without front matter).
@@ -82,10 +69,6 @@ module Bridgetown
82
69
  end
83
70
  end
84
71
 
85
- def extname_list
86
- @extname_list ||= @config["markdown_ext"].split(",").map! { |e| ".#{e.downcase}" }
87
- end
88
-
89
72
  private
90
73
 
91
74
  def custom_processor
@@ -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
  #
@@ -12,7 +12,15 @@ module Bridgetown
12
12
  mutable false
13
13
 
14
14
  def_delegator :@obj, :relative_path, :path
15
- def_delegators :@obj, :id, :output, :content, :to_s, :relative_path, :url, :date
15
+ def_delegators :@obj,
16
+ :id,
17
+ :output,
18
+ :content,
19
+ :to_s,
20
+ :relative_path,
21
+ :url,
22
+ :date,
23
+ :related_posts
16
24
 
17
25
  private def_delegator :@obj, :data, :fallback_data
18
26
 
@@ -7,7 +7,7 @@ module Bridgetown
7
7
 
8
8
  mutable false
9
9
 
10
- def_delegators :@obj, :content, :dir, :name, :path, :url
10
+ def_delegators :@obj, :content, :dir, :name, :path, :url, :pager
11
11
  private def_delegator :@obj, :data, :fallback_data
12
12
  end
13
13
  end
@@ -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
@@ -81,19 +82,16 @@ module Bridgetown
81
82
  end
82
83
 
83
84
  def output
84
- @output ||= Renderer.new(doc.site, self, site.site_payload).run
85
+ @output || (
86
+ Renderer.new(doc.site, self, site.site_payload).run
87
+ @output
88
+ )
85
89
  end
86
90
 
87
91
  def place_in_layout?
88
92
  false
89
93
  end
90
94
 
91
- def render_with_liquid?
92
- return false if data["render_with_liquid"] == false
93
-
94
- !(yaml_file? || !Utils.has_liquid_construct?(content))
95
- end
96
-
97
95
  protected
98
96
 
99
97
  # Internal: Extract excerpt from the content
@@ -30,6 +30,7 @@ module Bridgetown
30
30
  ).convert(input.to_s)
31
31
  end
32
32
 
33
+ # TODO: This should be removed, there is no Sass converter
33
34
  # Convert a Sass string into CSS output.
34
35
  #
35
36
  # input - The Sass String to convert.
@@ -41,6 +42,7 @@ module Bridgetown
41
42
  ).convert(input)
42
43
  end
43
44
 
45
+ # TODO: This should be removed, there is no Scss converter
44
46
  # Convert a Scss string into CSS output.
45
47
  #
46
48
  # input - The Scss String to convert.
@@ -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
@@ -10,11 +10,8 @@ module Bridgetown
10
10
 
11
11
  def parse(content)
12
12
  measure_time do
13
- # Remove extraneous indentation for rendercontent tags
14
- processed_content = content.gsub(%r!^[ \t]+{%-? rendercontent!, "{% rendercontent")
15
-
16
13
  @renderer.cache[@filename] ||= Liquid::Template.parse(
17
- processed_content, line_numbers: true
14
+ content, line_numbers: true
18
15
  )
19
16
  end
20
17
  @template = @renderer.cache[@filename]
@@ -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
 
@@ -73,18 +68,6 @@ module Bridgetown
73
68
  end
74
69
  end
75
70
 
76
- # For backwards-compatibility in subclasses that do not redefine
77
- # the `:to_liquid` method, stash existing definition under a new name
78
- #
79
- # TODO: Remove in Bridgetown 5.0
80
- alias_method :legacy_to_liquid, :to_liquid
81
- private :legacy_to_liquid
82
-
83
- # Private
84
- # Subclasses can choose to optimize their `:to_liquid` method by wrapping
85
- # it around this definition.
86
- #
87
- # TODO: Remove in Bridgetown 5.0
88
71
  def liquid_drop
89
72
  @liquid_drop ||= begin
90
73
  defaults = site.frontmatter_defaults.all(relative_path, type)
@@ -94,15 +77,12 @@ module Bridgetown
94
77
  Drops::PageDrop.new(self)
95
78
  end
96
79
  end
97
- private :liquid_drop
98
80
 
99
81
  # Public
100
82
  #
101
83
  # Liquid representation of current page
102
- #
103
- # TODO: Remove optional parameter in Bridgetown 5.0
104
- def to_liquid(attrs = nil)
105
- self.class == Bridgetown::Page ? liquid_drop : legacy_to_liquid(attrs)
84
+ def to_liquid
85
+ liquid_drop
106
86
  end
107
87
 
108
88
  # The full path and filename of the post. Defined in the YAML of the post
@@ -158,19 +138,6 @@ module Bridgetown
158
138
  self.basename = name[0..-ext.length - 1].gsub(%r!\.*\z!, "")
159
139
  end
160
140
 
161
- # Add any necessary layouts to this post
162
- #
163
- # layouts - The Hash of {"name" => "layout"}.
164
- # site_payload - The site payload Hash.
165
- #
166
- # Returns String rendered page.
167
- def render(layouts, site_payload)
168
- site_payload["page"] = to_liquid
169
- site_payload["paginator"] = pager.to_liquid
170
-
171
- do_layout(site_payload, layouts)
172
- end
173
-
174
141
  # The path to the source file
175
142
  #
176
143
  # Returns the path to the source file
@@ -180,7 +147,17 @@ module Bridgetown
180
147
 
181
148
  # The path to the page source file, relative to the site source
182
149
  def relative_path
183
- @relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).sub(%r!\A\/!, "")
150
+ @relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).delete_prefix("/")
151
+ end
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
184
161
  end
185
162
 
186
163
  # Obtain destination path.
@@ -195,9 +172,22 @@ module Bridgetown
195
172
  path
196
173
  end
197
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
+
198
188
  # Returns the object as a debug String.
199
189
  def inspect
200
- "#<#{self.class} @relative_path=#{relative_path.inspect}>"
190
+ "#<#{self.class} #{relative_path}>"
201
191
  end
202
192
 
203
193
  # Returns the Boolean of whether this Page is HTML or not.
@@ -214,6 +204,10 @@ module Bridgetown
214
204
  Bridgetown::Hooks.trigger :pages, hook_name, self, *args
215
205
  end
216
206
 
207
+ def type
208
+ :pages
209
+ end
210
+
217
211
  def write?
218
212
  true
219
213
  end