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