bridgetown-core 0.13.0 → 0.14.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.
- checksums.yaml +4 -4
- data/bin/bridgetown +0 -25
- data/bridgetown-core.gemspec +4 -1
- data/lib/bridgetown-core.rb +4 -1
- data/lib/bridgetown-core/cleaner.rb +1 -0
- data/lib/bridgetown-core/command.rb +10 -4
- data/lib/bridgetown-core/commands/console.rb +1 -2
- data/lib/bridgetown-core/commands/doctor.rb +1 -2
- data/lib/bridgetown-core/commands/new.rb +0 -3
- data/lib/bridgetown-core/commands/plugins.rb +169 -0
- data/lib/bridgetown-core/{convertible.rb → concerns/convertible.rb} +2 -2
- data/lib/bridgetown-core/concerns/site/configurable.rb +153 -0
- data/lib/bridgetown-core/concerns/site/content.rb +111 -0
- data/lib/bridgetown-core/concerns/site/extensible.rb +56 -0
- data/lib/bridgetown-core/concerns/site/processable.rb +74 -0
- data/lib/bridgetown-core/concerns/site/renderable.rb +50 -0
- data/lib/bridgetown-core/concerns/site/writable.rb +31 -0
- data/lib/bridgetown-core/configuration.rb +2 -9
- data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +0 -3
- data/lib/bridgetown-core/document.rb +1 -1
- data/lib/bridgetown-core/drops/site_drop.rb +1 -1
- data/lib/bridgetown-core/external.rb +17 -21
- data/lib/bridgetown-core/filters.rb +10 -0
- data/lib/bridgetown-core/generators/prototype_generator.rb +1 -1
- data/lib/bridgetown-core/hooks.rb +62 -62
- data/lib/bridgetown-core/layout.rb +10 -4
- data/lib/bridgetown-core/page.rb +9 -2
- data/lib/bridgetown-core/plugin.rb +2 -0
- data/lib/bridgetown-core/plugin_manager.rb +62 -12
- data/lib/bridgetown-core/reader.rb +5 -0
- data/lib/bridgetown-core/readers/data_reader.rb +5 -2
- data/lib/bridgetown-core/readers/layout_reader.rb +9 -2
- data/lib/bridgetown-core/readers/plugin_content_reader.rb +48 -0
- data/lib/bridgetown-core/renderer.rb +7 -10
- data/lib/bridgetown-core/site.rb +20 -463
- data/lib/bridgetown-core/utils.rb +1 -27
- data/lib/bridgetown-core/utils/ruby_exec.rb +1 -4
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/bridgetown-core/watcher.rb +5 -1
- data/lib/site_template/plugins/{.keep → builders/.keep} +0 -0
- data/lib/site_template/plugins/site_builder.rb +4 -0
- data/lib/site_template/src/_includes/navbar.html +1 -0
- data/lib/site_template/src/posts.md +15 -0
- data/lib/site_template/start.js +1 -1
- metadata +58 -6
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
module Site::Content
|
5
|
+
# Construct a Hash of Posts indexed by the specified Post attribute.
|
6
|
+
#
|
7
|
+
# post_attr - The String name of the Post attribute.
|
8
|
+
#
|
9
|
+
# Examples
|
10
|
+
#
|
11
|
+
# post_attr_hash('categories')
|
12
|
+
# # => { 'tech' => [<Post A>, <Post B>],
|
13
|
+
# # 'ruby' => [<Post B>] }
|
14
|
+
#
|
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.
|
18
|
+
def post_attr_hash(post_attr)
|
19
|
+
# Build a hash map based on the specified post attribute ( post attr =>
|
20
|
+
# array of posts ) then sort each array in reverse order.
|
21
|
+
@post_attr_hash[post_attr] ||= begin
|
22
|
+
hash = Hash.new { |h, key| h[key] = [] }
|
23
|
+
posts.docs.each do |p|
|
24
|
+
p.data[post_attr]&.each { |t| hash[t] << p }
|
25
|
+
end
|
26
|
+
hash.each_value { |posts| posts.sort!.reverse! }
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def tags
|
32
|
+
post_attr_hash("tags")
|
33
|
+
end
|
34
|
+
|
35
|
+
def categories
|
36
|
+
post_attr_hash("categories")
|
37
|
+
end
|
38
|
+
|
39
|
+
def metadata
|
40
|
+
data["site_metadata"] ||= ActiveSupport::HashWithIndifferentAccess.new
|
41
|
+
end
|
42
|
+
|
43
|
+
# The Hash payload containing site-wide data.
|
44
|
+
#
|
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.
|
56
|
+
def site_payload
|
57
|
+
Drops::UnifiedPayloadDrop.new self
|
58
|
+
end
|
59
|
+
alias_method :to_liquid, :site_payload
|
60
|
+
|
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.
|
64
|
+
#
|
65
|
+
# Returns a Hash containing collection name-to-instance pairs.
|
66
|
+
def collections
|
67
|
+
@collections ||= collection_names.each_with_object(
|
68
|
+
ActiveSupport::HashWithIndifferentAccess.new
|
69
|
+
) do |name, hsh|
|
70
|
+
hsh[name] = Bridgetown::Collection.new(self, name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
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.
|
78
|
+
def collection_names
|
79
|
+
case config["collections"]
|
80
|
+
when Hash
|
81
|
+
config["collections"].keys
|
82
|
+
when Array
|
83
|
+
config["collections"]
|
84
|
+
when nil
|
85
|
+
[]
|
86
|
+
else
|
87
|
+
raise ArgumentError, "Your `collections` key must be a hash or an array."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Get all the documents
|
92
|
+
#
|
93
|
+
# Returns an Array of all Documents
|
94
|
+
def documents
|
95
|
+
collections.each_with_object(Set.new) do |(_, collection), set|
|
96
|
+
set.merge(collection.docs).merge(collection.files)
|
97
|
+
end.to_a
|
98
|
+
end
|
99
|
+
|
100
|
+
# Get the to be written documents
|
101
|
+
#
|
102
|
+
# Returns an Array of Documents which should be written
|
103
|
+
def docs_to_write
|
104
|
+
documents.select(&:write?)
|
105
|
+
end
|
106
|
+
|
107
|
+
def posts
|
108
|
+
collections["posts"] ||= Collection.new(self, "posts")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
module Site::Extensible
|
5
|
+
# Load necessary libraries, plugins, converters, and generators.
|
6
|
+
#
|
7
|
+
# Returns nothing.
|
8
|
+
def setup
|
9
|
+
plugin_manager.require_plugin_files
|
10
|
+
self.converters = instantiate_subclasses(Bridgetown::Converter)
|
11
|
+
self.generators = instantiate_subclasses(Bridgetown::Generator)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Run each of the Generators.
|
15
|
+
#
|
16
|
+
# Returns nothing.
|
17
|
+
def generate
|
18
|
+
generators.each do |generator|
|
19
|
+
start = Time.now
|
20
|
+
generator.generate(self)
|
21
|
+
|
22
|
+
next unless ENV["BRIDGETOWN_LOG_LEVEL"] == "debug"
|
23
|
+
|
24
|
+
generator_name = if generator.class.respond_to?(:custom_name)
|
25
|
+
generator.class.custom_name
|
26
|
+
else
|
27
|
+
generator.class.name
|
28
|
+
end
|
29
|
+
Bridgetown.logger.debug "Generating:",
|
30
|
+
"#{generator_name} finished in #{Time.now - start} seconds."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# 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
|
+
def find_converter_instance(klass)
|
38
|
+
@find_converter_instance ||= {}
|
39
|
+
@find_converter_instance[klass] ||= begin
|
40
|
+
converters.find { |converter| converter.instance_of?(klass) } || \
|
41
|
+
raise("No Converters found for #{klass}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
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
|
+
|
50
|
+
def instantiate_subclasses(klass)
|
51
|
+
klass.descendants.sort.map do |c|
|
52
|
+
c.new(config)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
module Site::Processable
|
5
|
+
# Public: Read, process, and write this Site to output.
|
6
|
+
#
|
7
|
+
# Returns nothing.
|
8
|
+
def process
|
9
|
+
reset
|
10
|
+
read
|
11
|
+
generate # Extensible
|
12
|
+
render # Renderable
|
13
|
+
cleanup # Writable
|
14
|
+
write # Writable
|
15
|
+
print_stats if config["profile"]
|
16
|
+
end
|
17
|
+
|
18
|
+
# rubocop:disable Metrics/AbcSize
|
19
|
+
#
|
20
|
+
# Reset Site details.
|
21
|
+
#
|
22
|
+
# Returns nothing
|
23
|
+
def reset
|
24
|
+
self.time = if config["time"]
|
25
|
+
Utils.parse_date(config["time"].to_s, "Invalid time in bridgetown.config.yml.")
|
26
|
+
else
|
27
|
+
Time.now
|
28
|
+
end
|
29
|
+
self.layouts = ActiveSupport::HashWithIndifferentAccess.new
|
30
|
+
self.pages = []
|
31
|
+
self.static_files = []
|
32
|
+
self.data = ActiveSupport::HashWithIndifferentAccess.new
|
33
|
+
@post_attr_hash = {}
|
34
|
+
@collections = nil
|
35
|
+
@documents = nil
|
36
|
+
@docs_to_write = nil
|
37
|
+
@regenerator.clear_cache
|
38
|
+
@liquid_renderer.reset
|
39
|
+
frontmatter_defaults.reset
|
40
|
+
|
41
|
+
raise ArgumentError, "limit_posts must be a non-negative number" if limit_posts.negative?
|
42
|
+
|
43
|
+
Bridgetown::Cache.clear_if_config_changed config
|
44
|
+
Bridgetown::Hooks.trigger :site, :after_reset, self
|
45
|
+
end
|
46
|
+
# rubocop:enable Metrics/AbcSize
|
47
|
+
|
48
|
+
# Read Site data from disk and load it into internal data structures.
|
49
|
+
#
|
50
|
+
# Returns nothing.
|
51
|
+
def read
|
52
|
+
Bridgetown::Hooks.trigger :site, :pre_read, self
|
53
|
+
reader.read
|
54
|
+
limit_posts!
|
55
|
+
Bridgetown::Hooks.trigger :site, :post_read, self
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Limits the current posts; removes the posts which exceed the limit_posts
|
61
|
+
#
|
62
|
+
# Returns nothing
|
63
|
+
def limit_posts!
|
64
|
+
if limit_posts.positive?
|
65
|
+
limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
|
66
|
+
posts.docs = posts.docs[-limit, limit]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def print_stats
|
71
|
+
Bridgetown.logger.info @liquid_renderer.stats_table
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
module Site::Renderable
|
5
|
+
# Render the site to the destination.
|
6
|
+
#
|
7
|
+
# Returns nothing.
|
8
|
+
def render
|
9
|
+
payload = site_payload
|
10
|
+
|
11
|
+
Bridgetown::Hooks.trigger :site, :pre_render, self, payload
|
12
|
+
|
13
|
+
execute_inline_ruby_for_layouts!
|
14
|
+
|
15
|
+
render_docs(payload)
|
16
|
+
render_pages(payload)
|
17
|
+
|
18
|
+
Bridgetown::Hooks.trigger :site, :post_render, self, payload
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute_inline_ruby_for_layouts!
|
22
|
+
return unless config.should_execute_inline_ruby?
|
23
|
+
|
24
|
+
layouts.each_value do |layout|
|
25
|
+
Bridgetown::Utils::RubyExec.search_data_for_ruby_code(layout, self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_docs(payload)
|
30
|
+
collections.each_value do |collection|
|
31
|
+
collection.docs.each do |document|
|
32
|
+
render_regenerated(document, payload)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def render_pages(payload)
|
38
|
+
pages.each do |page|
|
39
|
+
render_regenerated(page, payload)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def render_regenerated(document, payload)
|
44
|
+
return unless regenerator.regenerate?(document)
|
45
|
+
|
46
|
+
document.output = Bridgetown::Renderer.new(self, document, payload).run
|
47
|
+
document.trigger_hooks(:post_render)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
module Site::Writable
|
5
|
+
# Remove orphaned files and empty directories in destination.
|
6
|
+
#
|
7
|
+
# Returns nothing.
|
8
|
+
def cleanup
|
9
|
+
@cleaner.cleanup!
|
10
|
+
end
|
11
|
+
|
12
|
+
# Write static files, pages, and posts.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
def write
|
16
|
+
each_site_file do |item|
|
17
|
+
item.write(dest) if regenerator.regenerate?(item)
|
18
|
+
end
|
19
|
+
regenerator.write_metadata
|
20
|
+
Bridgetown::Hooks.trigger :site, :post_write, self
|
21
|
+
end
|
22
|
+
|
23
|
+
def each_site_file
|
24
|
+
%w(pages static_files docs_to_write).each do |type|
|
25
|
+
send(type).each do |item|
|
26
|
+
yield item
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -4,7 +4,7 @@ module Bridgetown
|
|
4
4
|
# TODO: refactor this whole object! Already had to fix obscure
|
5
5
|
# bugs just making minor changes, and all the indirection is
|
6
6
|
# quite hard to decipher. -JW
|
7
|
-
class Configuration <
|
7
|
+
class Configuration < ActiveSupport::HashWithIndifferentAccess
|
8
8
|
# Default options. Overridden by values in bridgetown.config.yml.
|
9
9
|
# Strings rather than symbols are used for compatibility with YAML.
|
10
10
|
DEFAULTS = {
|
@@ -91,7 +91,7 @@ module Bridgetown
|
|
91
91
|
#
|
92
92
|
# Returns a Configuration filled with defaults.
|
93
93
|
def from(user_config)
|
94
|
-
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config]
|
94
|
+
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config])
|
95
95
|
.merge_environment_specific_options!
|
96
96
|
.add_default_collections
|
97
97
|
.add_default_excludes
|
@@ -99,13 +99,6 @@ module Bridgetown
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
# Public: Turn all keys into string
|
103
|
-
#
|
104
|
-
# Return a copy of the hash where all its keys are strings
|
105
|
-
def stringify_keys
|
106
|
-
each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v }
|
107
|
-
end
|
108
|
-
|
109
102
|
def get_config_value_with_override(config_key, override)
|
110
103
|
override[config_key] || self[config_key] || DEFAULTS[config_key]
|
111
104
|
end
|
@@ -11,8 +11,6 @@ module Kramdown
|
|
11
11
|
attr_reader :options, :parser
|
12
12
|
|
13
13
|
# The implementation is basically the core logic in +Kramdown::Document#initialize+
|
14
|
-
#
|
15
|
-
# rubocop:disable Naming/MemoizedInstanceVariableName
|
16
14
|
def setup(options)
|
17
15
|
@cache ||= {}
|
18
16
|
|
@@ -36,7 +34,6 @@ module Kramdown
|
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
39
|
-
# rubocop:enable Naming/MemoizedInstanceVariableName
|
40
37
|
|
41
38
|
private
|
42
39
|
|
@@ -10,13 +10,11 @@ module Bridgetown
|
|
10
10
|
#
|
11
11
|
def require_if_present(names)
|
12
12
|
Array(names).each do |name|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
false
|
19
|
-
end
|
13
|
+
require name
|
14
|
+
rescue LoadError
|
15
|
+
Bridgetown.logger.debug "Couldn't load #{name}. Skipping."
|
16
|
+
yield(name, version_constraint(name)) if block_given?
|
17
|
+
false
|
20
18
|
end
|
21
19
|
end
|
22
20
|
|
@@ -38,23 +36,21 @@ module Bridgetown
|
|
38
36
|
#
|
39
37
|
def require_with_graceful_fail(names)
|
40
38
|
Array(names).each do |name|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
In order to use Bridgetown as currently configured, you'll need to install this gem.
|
39
|
+
Bridgetown.logger.debug "Requiring:", name.to_s
|
40
|
+
require name
|
41
|
+
rescue LoadError => e
|
42
|
+
Bridgetown.logger.error "Dependency Error:", <<~MSG
|
43
|
+
Yikes! It looks like you don't have #{name} or one of its dependencies installed.
|
44
|
+
In order to use Bridgetown as currently configured, you'll need to install this gem.
|
48
45
|
|
49
|
-
|
50
|
-
|
46
|
+
If you've run Bridgetown with `bundle exec`, ensure that you have included the #{name}
|
47
|
+
gem in your Gemfile as well.
|
51
48
|
|
52
|
-
|
49
|
+
The full error message from Ruby is: '#{e.message}'
|
53
50
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
51
|
+
If you run into trouble, you can find helpful resources at https://www.bridgetownrb.com/docs/community/
|
52
|
+
MSG
|
53
|
+
raise Bridgetown::Errors::MissingDependencyException, name
|
58
54
|
end
|
59
55
|
end
|
60
56
|
end
|