bridgetown-core 0.15.0.beta3 → 0.16.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +14 -0
  3. data/bridgetown-core.gemspec +3 -0
  4. data/lib/bridgetown-core.rb +6 -1
  5. data/lib/bridgetown-core/commands/concerns/actions.rb +29 -23
  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 +22 -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 +1 -0
  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/document_drop.rb +9 -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 +2 -0
  29. data/lib/bridgetown-core/layout.rb +24 -1
  30. data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -1
  31. data/lib/bridgetown-core/page.rb +34 -25
  32. data/lib/bridgetown-core/plugin_manager.rb +14 -5
  33. data/lib/bridgetown-core/regenerator.rb +1 -1
  34. data/lib/bridgetown-core/renderer.rb +38 -12
  35. data/lib/bridgetown-core/ruby_template_view.rb +98 -0
  36. data/lib/bridgetown-core/tags/class_map.rb +90 -0
  37. data/lib/bridgetown-core/tags/include.rb +2 -0
  38. data/lib/bridgetown-core/tags/render_content.rb +11 -1
  39. data/lib/bridgetown-core/tags/webpack_path.rb +19 -22
  40. data/lib/bridgetown-core/utils.rb +53 -0
  41. data/lib/bridgetown-core/version.rb +2 -2
  42. data/lib/site_template/bridgetown.config.yml +5 -3
  43. data/lib/site_template/src/_components/{footer.html → footer.liquid} +0 -0
  44. data/lib/site_template/src/_components/{head.html → head.liquid} +0 -0
  45. data/lib/site_template/src/_components/{navbar.html → navbar.liquid} +0 -0
  46. data/lib/site_template/src/_layouts/{default.html → default.liquid} +1 -1
  47. data/lib/site_template/src/_layouts/{home.html → home.liquid} +0 -0
  48. data/lib/site_template/src/_layouts/{page.html → page.liquid} +0 -0
  49. data/lib/site_template/src/_layouts/{post.html → post.liquid} +0 -0
  50. metadata +59 -10
  51. data/lib/bridgetown-core/concerns/convertible.rb +0 -235
@@ -3,17 +3,19 @@
3
3
  module Bridgetown
4
4
  module Site::Extensible
5
5
  # Load necessary libraries, plugins, converters, and generators.
6
- #
7
- # Returns nothing.
6
+ # @see Bridgetown::Converter
7
+ # @see Bridgetown::Generator
8
+ # @see PluginManager
9
+ # @return [void]
8
10
  def setup
9
11
  plugin_manager.require_plugin_files
10
12
  self.converters = instantiate_subclasses(Bridgetown::Converter)
11
13
  self.generators = instantiate_subclasses(Bridgetown::Generator)
12
14
  end
13
15
 
14
- # Run each of the Generators.
15
- #
16
- # Returns nothing.
16
+ # Run all Generators.
17
+ # @see Bridgetown::Generator
18
+ # @return [void]
17
19
  def generate
18
20
  generators.each do |generator|
19
21
  start = Time.now
@@ -32,8 +34,9 @@ module Bridgetown
32
34
  end
33
35
 
34
36
  # Get the implementation class for the given Converter.
35
- # Returns the Converter instance implementing the given Converter.
36
- # klass - The Class of the Converter to fetch.
37
+ # @param klass [Object] The Class of the Converter to fetch.
38
+ # @return [Bridgetown::Converter] Returns the {Bridgetown::Converter}
39
+ # instance implementing the given +Converter+.
37
40
  def find_converter_instance(klass)
38
41
  @find_converter_instance ||= {}
39
42
  @find_converter_instance[klass] ||= begin
@@ -42,11 +45,11 @@ module Bridgetown
42
45
  end
43
46
  end
44
47
 
45
- # klass - class or module containing the subclasses.
46
- # Returns array of instances of subclasses of parameter.
47
- # Create array of instances of the subclasses of the class or module
48
- # passed in as argument.
49
-
48
+ # Create an array of instances of the subclasses of the class or module
49
+ # passed in as argument.
50
+ # @param klass [Class, Module] - class or module containing the subclasses.
51
+ # @return [Array<Object>] Returns an array of instances of subclasses of
52
+ # +klass+.
50
53
  def instantiate_subclasses(klass)
51
54
  klass.descendants.sort.map do |c|
52
55
  c.new(config)
@@ -2,9 +2,14 @@
2
2
 
3
3
  module Bridgetown
4
4
  module Site::Processable
5
- # Public: Read, process, and write this Site to output.
6
- #
7
- # Returns nothing.
5
+ # Reset, Read, Generate, Render, Cleanup, Process, and Write this Site to output.
6
+ # @return [void]
7
+ # @see #reset
8
+ # @see #read
9
+ # @see #generate
10
+ # @see #render
11
+ # @see #cleanup
12
+ # @see #write
8
13
  def process
9
14
  reset
10
15
  read
@@ -16,10 +21,9 @@ module Bridgetown
16
21
  end
17
22
 
18
23
  # rubocop:disable Metrics/AbcSize
19
- #
24
+
20
25
  # Reset Site details.
21
- #
22
- # Returns nothing
26
+ # @return [void]
23
27
  def reset
24
28
  self.time = if config["time"]
25
29
  Utils.parse_date(config["time"].to_s, "Invalid time in bridgetown.config.yml.")
@@ -43,11 +47,11 @@ module Bridgetown
43
47
  Bridgetown::Cache.clear_if_config_changed config
44
48
  Bridgetown::Hooks.trigger :site, :after_reset, self
45
49
  end
50
+
46
51
  # rubocop:enable Metrics/AbcSize
47
52
 
48
53
  # Read Site data from disk and load it into internal data structures.
49
- #
50
- # Returns nothing.
54
+ # @return [void]
51
55
  def read
52
56
  Bridgetown::Hooks.trigger :site, :pre_read, self
53
57
  reader.read
@@ -58,8 +62,6 @@ module Bridgetown
58
62
  private
59
63
 
60
64
  # Limits the current posts; removes the posts which exceed the limit_posts
61
- #
62
- # Returns nothing
63
65
  def limit_posts!
64
66
  if limit_posts.positive?
65
67
  limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
@@ -3,8 +3,7 @@
3
3
  module Bridgetown
4
4
  module Site::Renderable
5
5
  # Render the site to the destination.
6
- #
7
- # Returns nothing.
6
+ # @return [void]
8
7
  def render
9
8
  payload = site_payload
10
9
 
@@ -18,6 +17,14 @@ module Bridgetown
18
17
  Bridgetown::Hooks.trigger :site, :post_render, self, payload
19
18
  end
20
19
 
20
+ # Executes inline Ruby frontmatter if
21
+ # +ENV+["BRIDGETOWN_RUBY_IN_FRONTMATTER"] equals "true"
22
+ #
23
+ # @example
24
+ # calculation: !ruby/string:Rb |
25
+ # [2 * 4, 5 + 2].min
26
+ # @return [void]
27
+ # @see https://www.bridgetownrb.com/docs/front-matter#ruby-front-matter
21
28
  def execute_inline_ruby_for_layouts!
22
29
  return unless config.should_execute_inline_ruby?
23
30
 
@@ -26,6 +33,10 @@ module Bridgetown
26
33
  end
27
34
  end
28
35
 
36
+ # Renders all documents
37
+ # @param payload [Hash] A hash of site data.
38
+ # @return [void]
39
+ # @see Bridgetown::Site::Content#site_payload
29
40
  def render_docs(payload)
30
41
  collections.each_value do |collection|
31
42
  collection.docs.each do |document|
@@ -34,12 +45,21 @@ module Bridgetown
34
45
  end
35
46
  end
36
47
 
48
+ # Renders all pages
49
+ # @param payload [Hash] A hash of site data.
50
+ # @return [void]
51
+ # @see Bridgetown::Site::Content#site_payload
37
52
  def render_pages(payload)
38
53
  pages.each do |page|
39
54
  render_regenerated(page, payload)
40
55
  end
41
56
  end
42
57
 
58
+ # Regenerates a site using {Bridgetown::Renderer}
59
+ # @param document [Post] The document to regenerate.
60
+ # @param payload [Hash] A hash of site data.
61
+ # @return [void]
62
+ # @see Bridgetown::Renderer
43
63
  def render_regenerated(document, payload)
44
64
  return unless regenerator.regenerate?(document)
45
65
 
@@ -4,14 +4,14 @@ module Bridgetown
4
4
  module Site::Writable
5
5
  # Remove orphaned files and empty directories in destination.
6
6
  #
7
- # Returns nothing.
7
+ # @return [void]
8
8
  def cleanup
9
9
  @cleaner.cleanup!
10
10
  end
11
11
 
12
12
  # Write static files, pages, and posts.
13
13
  #
14
- # Returns nothing.
14
+ # @return [void]
15
15
  def write
16
16
  each_site_file do |item|
17
17
  item.write(dest) if regenerator.regenerate?(item)
@@ -20,6 +20,20 @@ module Bridgetown
20
20
  Bridgetown::Hooks.trigger :site, :post_write, self
21
21
  end
22
22
 
23
+ # Yields the pages from {#pages}, {#static_files}, and {#docs_to_write}.
24
+ #
25
+ # @yieldparam item [Document, Page, StaticFile] Yields a
26
+ # {#Bridgetown::Page}, {#Bridgetown::StaticFile}, or
27
+ # {#Bridgetown::Document} object.
28
+ #
29
+ # @return [void]
30
+ #
31
+ # @see #pages
32
+ # @see #static_files
33
+ # @see #docs_to_write
34
+ # @see Page
35
+ # @see StaticFile
36
+ # @see Document
23
37
  def each_site_file
24
38
  %w(pages static_files docs_to_write).each do |type|
25
39
  send(type).each do |item|
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Validatable
5
+ # FIXME: there should be ONE TRUE METHOD to read the YAML frontmatter
6
+ # in the entire project. Both this and the equivalent Document method
7
+ # should be extracted and generalized.
8
+ #
9
+ # Read the YAML frontmatter.
10
+ #
11
+ # base - The String path to the dir containing the file.
12
+ # name - The String filename of the file.
13
+ # opts - optional parameter to File.read, default at site configs
14
+ #
15
+ # Returns nothing.
16
+ # rubocop:disable Metrics/AbcSize
17
+ def read_yaml(base, name, opts = {})
18
+ filename = File.join(base, name)
19
+
20
+ begin
21
+ self.content = File.read(@path || site.in_source_dir(base, name),
22
+ **Utils.merged_file_read_opts(site, opts))
23
+ if content =~ Document::YAML_FRONT_MATTER_REGEXP
24
+ self.content = $POSTMATCH
25
+ self.data = SafeYAML.load(Regexp.last_match(1))&.with_indifferent_access
26
+ end
27
+ rescue Psych::SyntaxError => e
28
+ Bridgetown.logger.warn "YAML Exception reading #{filename}: #{e.message}"
29
+ raise e if site.config["strict_front_matter"]
30
+ rescue StandardError => e
31
+ Bridgetown.logger.warn "Error reading file #{filename}: #{e.message}"
32
+ raise e if site.config["strict_front_matter"]
33
+ end
34
+
35
+ self.data ||= ActiveSupport::HashWithIndifferentAccess.new
36
+
37
+ validate_data! filename
38
+ validate_permalink! filename
39
+
40
+ self.data
41
+ end
42
+ # rubocop:enable Metrics/AbcSize
43
+
44
+ # FIXME: why doesn't Document validate data too?
45
+ def validate_data!(filename)
46
+ unless self.data.is_a?(Hash)
47
+ raise Errors::InvalidYAMLFrontMatterError,
48
+ "Invalid YAML front matter in #{filename}"
49
+ end
50
+ end
51
+
52
+ # FIXME: Layouts don't have permalinks...d'oh
53
+ def validate_permalink!(filename)
54
+ if self.data["permalink"]&.to_s&.empty?
55
+ raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -19,6 +19,7 @@ module Bridgetown
19
19
  "data_dir" => "_data",
20
20
  "components_dir" => "_components",
21
21
  "includes_dir" => "_includes",
22
+ "partials_dir" => "_partials",
22
23
  "collections" => {},
23
24
 
24
25
  # Handling Reading
@@ -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,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tilt/erubi"
4
+ require "erubi/capture_end"
5
+
6
+ module Bridgetown
7
+ class ERBView < RubyTemplateView
8
+ def h(input)
9
+ Erubi.h(input)
10
+ end
11
+
12
+ def partial(partial_name, options = {})
13
+ options.merge!(options[:locals]) if options[:locals]
14
+
15
+ partial_segments = partial_name.split("/")
16
+ partial_segments.last.sub!(%r!^!, "_")
17
+ partial_name = partial_segments.join("/")
18
+
19
+ Tilt::ErubiTemplate.new(
20
+ site.in_source_dir(site.config[:partials_dir], "#{partial_name}.erb"),
21
+ outvar: "@_erbout",
22
+ engine_class: Erubi::CaptureEndEngine
23
+ ).render(self, options)
24
+ end
25
+
26
+ def markdownify
27
+ previous_buffer_state = @_erbout
28
+ @_erbout = +""
29
+ result = yield
30
+ @_erbout = previous_buffer_state
31
+
32
+ content = Bridgetown::Utils.reindent_for_markdown(result)
33
+ converter = site.find_converter_instance(Bridgetown::Converters::Markdown)
34
+ md_output = converter.convert(content).strip
35
+ @_erbout << md_output
36
+ end
37
+
38
+ def capture
39
+ previous_buffer_state = @_erbout
40
+ @_erbout = +""
41
+ result = yield
42
+ @_erbout = previous_buffer_state
43
+
44
+ result
45
+ end
46
+ end
47
+
48
+ module Converters
49
+ class ERBTemplates < Converter
50
+ input :erb
51
+
52
+ # Logic to do the ERB content conversion.
53
+ #
54
+ # @param content [String] Content of the file (without front matter).
55
+ # @params convertible [Bridgetown::Page, Bridgetown::Document, Bridgetown::Layout]
56
+ # The instantiated object which is processing the file.
57
+ #
58
+ # @return [String] The converted content.
59
+ def convert(content, convertible)
60
+ erb_view = Bridgetown::ERBView.new(convertible)
61
+
62
+ erb_renderer = Tilt::ErubiTemplate.new(
63
+ convertible.relative_path,
64
+ outvar: "@_erbout",
65
+ engine_class: Erubi::CaptureEndEngine
66
+ ) { content }
67
+
68
+ if convertible.is_a?(Bridgetown::Layout)
69
+ erb_renderer.render(erb_view) do
70
+ convertible.current_document_output
71
+ end
72
+ else
73
+ erb_renderer.render(erb_view)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ 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.