bridgetown-core 0.15.0.beta1 → 0.16.0.beta1

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