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
@@ -4,17 +4,24 @@ module Bridgetown
4
4
  module Site::Content
5
5
  # Construct a Hash of Posts indexed by the specified Post attribute.
6
6
  #
7
- # post_attr - The String name of the Post attribute.
7
+ # @param post_attr [String] The String name of the Post attribute.
8
8
  #
9
- # Examples
9
+ # @example
10
+ # Returns a hash like so: { attr => posts } where
11
+ #
12
+ # attr - One of the values for the requested attribute.
13
+ #
14
+ # posts - The Array of Posts with the given attr value.
15
+ #
16
+ # @example
10
17
  #
11
18
  # post_attr_hash('categories')
12
19
  # # => { 'tech' => [<Post A>, <Post B>],
13
20
  # # 'ruby' => [<Post B>] }
14
21
  #
15
- # Returns the Hash: { attr => posts } where
16
- # attr - One of the values for the requested attribute.
17
- # posts - The Array of Posts with the given attr value.
22
+ # @return [Hash{String, Symbol => Array<Post>}]
23
+ # Returns a hash of !{attr => posts}
24
+ #
18
25
  def post_attr_hash(post_attr)
19
26
  # Build a hash map based on the specified post attribute ( post attr =>
20
27
  # array of posts ) then sort each array in reverse order.
@@ -28,41 +35,85 @@ module Bridgetown
28
35
  end
29
36
  end
30
37
 
38
+ # Returns a hash of "tags" using {#post_attr_hash} where each tag is a key
39
+ # and each value is a post which contains the key.
40
+ # @example
41
+ # tags
42
+ # # => { 'tech': [<Post A>, <Post B>],
43
+ # # 'ruby': [<Post C> }
44
+ # @return [Hash{String, Array<Post>}] Returns a hash of all tags and their corresponding posts
45
+ # @see post_attr_hash
31
46
  def tags
32
47
  post_attr_hash("tags")
33
48
  end
34
49
 
50
+ # Returns a hash of "categories" using {#post_attr_hash} where each tag is
51
+ # a key and each value is a post which contains the key.
52
+ # @example
53
+ # categories
54
+ # # => { 'tech': [<Post A>, <Post B>],
55
+ # # 'ruby': [<Post C> }
56
+ # @return [Hash{String, Array<Post>}] Returns a hash of all categories and
57
+ # their corresponding posts
58
+ # @see post_attr_hash
35
59
  def categories
36
60
  post_attr_hash("categories")
37
61
  end
38
62
 
63
+ # Returns the value of +data+["site_metadata"] or creates a new instance of
64
+ # +ActiveSupport::HashWithIndifferentAccess+
65
+ # @return [Hash] Returns a hash of site metadata
39
66
  def metadata
40
67
  data["site_metadata"] ||= ActiveSupport::HashWithIndifferentAccess.new
41
68
  end
42
69
 
43
70
  # The Hash payload containing site-wide data.
44
71
  #
45
- # Returns the Hash: { "site" => data } where data is a Hash with keys:
46
- # "time" - The Time as specified in the configuration or the
47
- # current time if none was specified.
48
- # "posts" - The Array of Posts, sorted chronologically by post date
49
- # and then title.
50
- # "pages" - The Array of all Pages.
51
- # "html_pages" - The Array of HTML Pages.
52
- # "categories" - The Hash of category values and Posts.
53
- # See Site#post_attr_hash for type info.
54
- # "tags" - The Hash of tag values and Posts.
55
- # See Site#post_attr_hash for type info.
72
+ # @example
73
+ # site_payload
74
+ # # => { "site" => data } Where data is a Hash. See example below
75
+ #
76
+ # site = site_payload["site"]
77
+ # # => Returns a Hash with the following keys:
78
+ # #
79
+ # # site["time"] - The Time as specified in the configuration or the
80
+ # # current time if none was specified.
81
+ # #
82
+ # # site["posts"] - The Array of Posts, sorted chronologically by post date
83
+ # # and then title.
84
+ # #
85
+ # # site["pages"] - The Array of all Pages.
86
+ # #
87
+ # # site["html_pages"] - The Array of HTML Pages.
88
+ # #
89
+ # # site["categories"] - The Hash of category values and Posts.
90
+ # # See Site#post_attr_hash for type info.
91
+ # #
92
+ # # site["tags"] - The Hash of tag values and Posts.
93
+ # # See Site#post_attr_hash for type info.
94
+ #
95
+ # @return [Hash] Returns a hash in the structure of { "site" => data }
96
+ #
97
+ # See above example for usage.
98
+ #
99
+ # @see #post_attr_hash
56
100
  def site_payload
57
101
  Drops::UnifiedPayloadDrop.new self
58
102
  end
59
103
  alias_method :to_liquid, :site_payload
60
104
 
61
- # The list of collections and their corresponding Bridgetown::Collection instances.
62
- # If config['collections'] is set, a new instance is created
63
- # for each item in the collection, a new hash is returned otherwise.
105
+ # The list of {#collections} and their corresponding {Bridgetown::Collection} instances.
106
+ #
107
+ # If +config+['collections'] is set, a new instance of {Bridgetown::Collection} is created
108
+ # for each entry in the collections configuration.
109
+ #
110
+ # If +config+["collections"] is not specified, a blank hash is returned.
64
111
  #
65
- # Returns a Hash containing collection name-to-instance pairs.
112
+ # @return [Hash{String, Symbol => Bridgetown::Collection}] A Hash
113
+ # containing a collection name-to-instance pairs.
114
+ #
115
+ # @return [Hash] Returns a blank hash if no items found
116
+ # @see Collection
66
117
  def collections
67
118
  @collections ||= collection_names.each_with_object(
68
119
  ActiveSupport::HashWithIndifferentAccess.new
@@ -71,10 +122,11 @@ module Bridgetown
71
122
  end
72
123
  end
73
124
 
74
- # The list of collection names.
75
- #
76
- # Returns an array of collection names from the configuration,
77
- # or an empty array if the `collections` key is not set.
125
+ # An array of collection names.
126
+ # @return [Array<Collection>] an array of collection names from the configuration,
127
+ # or an empty array if the +config+["collections"] key is not set.
128
+ # @raise ArgumentError Raise an error if +config+["collections"] is not
129
+ # an Array or a Hash
78
130
  def collection_names
79
131
  case config["collections"]
80
132
  when Hash
@@ -88,22 +140,29 @@ module Bridgetown
88
140
  end
89
141
  end
90
142
 
91
- # Get all the documents
92
- #
93
- # Returns an Array of all Documents
143
+ # Get all documents.
144
+ # @return [Array<String>] an array of documents from the configuration
94
145
  def documents
95
146
  collections.each_with_object(Set.new) do |(_, collection), set|
96
147
  set.merge(collection.docs).merge(collection.files)
97
148
  end.to_a
98
149
  end
99
150
 
100
- # Get the to be written documents
151
+ # Get the documents to be written
101
152
  #
102
- # Returns an Array of Documents which should be written
153
+ # @return [Array<String, File>] an Array of Documents which should be written and
154
+ # that +respond_to :write?+
155
+ # @see #documents
156
+ # @see Collection
103
157
  def docs_to_write
104
158
  documents.select(&:write?)
105
159
  end
106
160
 
161
+ # Get all posts.
162
+ #
163
+ # @return [Collection] A #Collection of posts. Returns +#collections+["posts"]
164
+ # @return [Collection] Return a new #Collection if +#collections+["posts"] is nil
165
+ # @see Collection
107
166
  def posts
108
167
  collections["posts"] ||= Collection.new(self, "posts")
109
168
  end
@@ -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,17 +45,25 @@ 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
 
46
- document.output = Bridgetown::Renderer.new(self, document, payload).run
47
- document.trigger_hooks(:post_render)
66
+ Bridgetown::Renderer.new(self, document, payload).run
48
67
  end
49
68
  end
50
69
  end
@@ -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