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.
- checksums.yaml +4 -4
- data/Rakefile +14 -0
- data/bridgetown-core.gemspec +2 -0
- data/lib/bridgetown-core.rb +6 -1
- data/lib/bridgetown-core/commands/concerns/actions.rb +54 -21
- data/lib/bridgetown-core/commands/console.rb +12 -2
- data/lib/bridgetown-core/commands/serve.rb +5 -0
- data/lib/bridgetown-core/concerns/data_accessible.rb +19 -0
- data/lib/bridgetown-core/concerns/layout_placeable.rb +17 -0
- data/lib/bridgetown-core/concerns/liquid_renderable.rb +20 -0
- data/lib/bridgetown-core/concerns/publishable.rb +10 -0
- data/lib/bridgetown-core/concerns/site/configurable.rb +62 -31
- data/lib/bridgetown-core/concerns/site/content.rb +88 -29
- data/lib/bridgetown-core/concerns/site/extensible.rb +15 -12
- data/lib/bridgetown-core/concerns/site/processable.rb +12 -10
- data/lib/bridgetown-core/concerns/site/renderable.rb +23 -4
- data/lib/bridgetown-core/concerns/site/writable.rb +16 -2
- data/lib/bridgetown-core/concerns/validatable.rb +59 -0
- data/lib/bridgetown-core/configuration.rb +1 -0
- data/lib/bridgetown-core/converter.rb +34 -0
- data/lib/bridgetown-core/converters/erb_templates.rb +61 -0
- data/lib/bridgetown-core/converters/markdown.rb +6 -23
- data/lib/bridgetown-core/converters/smartypants.rb +0 -10
- data/lib/bridgetown-core/document.rb +8 -52
- data/lib/bridgetown-core/drops/document_drop.rb +9 -1
- data/lib/bridgetown-core/drops/page_drop.rb +1 -1
- data/lib/bridgetown-core/errors.rb +2 -0
- data/lib/bridgetown-core/excerpt.rb +5 -7
- data/lib/bridgetown-core/filters.rb +2 -0
- data/lib/bridgetown-core/layout.rb +24 -1
- data/lib/bridgetown-core/liquid_renderer/file.rb +1 -4
- data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -1
- data/lib/bridgetown-core/page.rb +36 -42
- data/lib/bridgetown-core/plugin_manager.rb +27 -13
- data/lib/bridgetown-core/regenerator.rb +1 -1
- data/lib/bridgetown-core/renderer.rb +41 -15
- data/lib/bridgetown-core/ruby_template_view.rb +84 -0
- data/lib/bridgetown-core/tags/class_map.rb +90 -0
- data/lib/bridgetown-core/tags/include.rb +2 -0
- data/lib/bridgetown-core/tags/render_content.rb +14 -2
- data/lib/bridgetown-core/tags/webpack_path.rb +48 -16
- data/lib/bridgetown-core/utils.rb +44 -0
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/site_template/bridgetown.config.yml +5 -3
- data/lib/site_template/package.json +1 -0
- data/lib/site_template/src/_components/{footer.html → footer.liquid} +0 -0
- data/lib/site_template/src/_components/{head.html → head.liquid} +0 -0
- data/lib/site_template/src/_components/{navbar.html → navbar.liquid} +0 -0
- data/lib/site_template/src/_layouts/default.html +1 -1
- data/lib/site_template/webpack.config.js +3 -3
- metadata +41 -6
- 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
|
7
|
+
# @param post_attr [String] The String name of the Post attribute.
|
8
8
|
#
|
9
|
-
#
|
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
|
-
#
|
16
|
-
#
|
17
|
-
#
|
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
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# "
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
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
|
-
#
|
63
|
-
#
|
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
|
-
#
|
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
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
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
|
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
|
151
|
+
# Get the documents to be written
|
101
152
|
#
|
102
|
-
#
|
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
|
-
#
|
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
|
15
|
-
#
|
16
|
-
#
|
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
|
-
#
|
36
|
-
#
|
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
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
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
|
-
#
|
6
|
-
#
|
7
|
-
#
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|