bridgetown-core 0.7.0 → 0.7.1
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/Rakefile +42 -0
- data/bridgetown-core.gemspec +46 -0
- data/lib/bridgetown-core.rb +202 -0
- data/lib/bridgetown-core/cache.rb +190 -0
- data/lib/bridgetown-core/cleaner.rb +111 -0
- data/lib/bridgetown-core/collection.rb +279 -0
- data/lib/bridgetown-core/command.rb +106 -0
- data/lib/bridgetown-core/commands/build.rb +96 -0
- data/lib/bridgetown-core/commands/clean.rb +43 -0
- data/lib/bridgetown-core/commands/console.rb +56 -0
- data/lib/bridgetown-core/commands/doctor.rb +172 -0
- data/lib/bridgetown-core/commands/help.rb +34 -0
- data/lib/bridgetown-core/commands/new.rb +148 -0
- data/lib/bridgetown-core/commands/serve.rb +273 -0
- data/lib/bridgetown-core/commands/serve/servlet.rb +68 -0
- data/lib/bridgetown-core/configuration.rb +323 -0
- data/lib/bridgetown-core/converter.rb +54 -0
- data/lib/bridgetown-core/converters/identity.rb +39 -0
- data/lib/bridgetown-core/converters/markdown.rb +108 -0
- data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +132 -0
- data/lib/bridgetown-core/converters/smartypants.rb +69 -0
- data/lib/bridgetown-core/convertible.rb +237 -0
- data/lib/bridgetown-core/deprecator.rb +50 -0
- data/lib/bridgetown-core/document.rb +475 -0
- data/lib/bridgetown-core/drops/bridgetown_drop.rb +32 -0
- data/lib/bridgetown-core/drops/collection_drop.rb +20 -0
- data/lib/bridgetown-core/drops/document_drop.rb +69 -0
- data/lib/bridgetown-core/drops/drop.rb +215 -0
- data/lib/bridgetown-core/drops/excerpt_drop.rb +19 -0
- data/lib/bridgetown-core/drops/page_drop.rb +14 -0
- data/lib/bridgetown-core/drops/site_drop.rb +62 -0
- data/lib/bridgetown-core/drops/static_file_drop.rb +14 -0
- data/lib/bridgetown-core/drops/unified_payload_drop.rb +26 -0
- data/lib/bridgetown-core/drops/url_drop.rb +132 -0
- data/lib/bridgetown-core/entry_filter.rb +108 -0
- data/lib/bridgetown-core/errors.rb +20 -0
- data/lib/bridgetown-core/excerpt.rb +202 -0
- data/lib/bridgetown-core/external.rb +62 -0
- data/lib/bridgetown-core/filters.rb +467 -0
- data/lib/bridgetown-core/filters/date_filters.rb +110 -0
- data/lib/bridgetown-core/filters/grouping_filters.rb +64 -0
- data/lib/bridgetown-core/filters/url_filters.rb +79 -0
- data/lib/bridgetown-core/frontmatter_defaults.rb +238 -0
- data/lib/bridgetown-core/generator.rb +5 -0
- data/lib/bridgetown-core/hooks.rb +103 -0
- data/lib/bridgetown-core/layout.rb +57 -0
- data/lib/bridgetown-core/liquid_extensions.rb +22 -0
- data/lib/bridgetown-core/liquid_renderer.rb +71 -0
- data/lib/bridgetown-core/liquid_renderer/file.rb +67 -0
- data/lib/bridgetown-core/liquid_renderer/table.rb +75 -0
- data/lib/bridgetown-core/log_adapter.rb +151 -0
- data/lib/bridgetown-core/log_writer.rb +60 -0
- data/lib/bridgetown-core/mime.types +867 -0
- data/lib/bridgetown-core/page.rb +214 -0
- data/lib/bridgetown-core/page_without_a_file.rb +14 -0
- data/lib/bridgetown-core/path_manager.rb +31 -0
- data/lib/bridgetown-core/plugin.rb +80 -0
- data/lib/bridgetown-core/plugin_manager.rb +60 -0
- data/lib/bridgetown-core/publisher.rb +23 -0
- data/lib/bridgetown-core/reader.rb +185 -0
- data/lib/bridgetown-core/readers/collection_reader.rb +22 -0
- data/lib/bridgetown-core/readers/data_reader.rb +75 -0
- data/lib/bridgetown-core/readers/layout_reader.rb +48 -0
- data/lib/bridgetown-core/readers/page_reader.rb +24 -0
- data/lib/bridgetown-core/readers/post_reader.rb +74 -0
- data/lib/bridgetown-core/readers/static_file_reader.rb +24 -0
- data/lib/bridgetown-core/regenerator.rb +195 -0
- data/lib/bridgetown-core/related_posts.rb +52 -0
- data/lib/bridgetown-core/renderer.rb +261 -0
- data/lib/bridgetown-core/site.rb +469 -0
- data/lib/bridgetown-core/static_file.rb +205 -0
- data/lib/bridgetown-core/tags/component.rb +34 -0
- data/lib/bridgetown-core/tags/highlight.rb +111 -0
- data/lib/bridgetown-core/tags/include.rb +220 -0
- data/lib/bridgetown-core/tags/link.rb +41 -0
- data/lib/bridgetown-core/tags/post_url.rb +107 -0
- data/lib/bridgetown-core/url.rb +164 -0
- data/lib/bridgetown-core/utils.rb +367 -0
- data/lib/bridgetown-core/utils/ansi.rb +57 -0
- data/lib/bridgetown-core/utils/exec.rb +26 -0
- data/lib/bridgetown-core/utils/internet.rb +37 -0
- data/lib/bridgetown-core/utils/platforms.rb +80 -0
- data/lib/bridgetown-core/utils/thread_event.rb +31 -0
- data/lib/bridgetown-core/utils/win_tz.rb +75 -0
- data/lib/bridgetown-core/version.rb +5 -0
- data/lib/bridgetown-core/watcher.rb +139 -0
- data/lib/site_template/.gitignore +6 -0
- data/lib/site_template/bridgetown.config.yml +21 -0
- data/lib/site_template/frontend/javascript/index.js +3 -0
- data/lib/site_template/frontend/styles/index.scss +17 -0
- data/lib/site_template/package.json +23 -0
- data/lib/site_template/src/404.html +9 -0
- data/lib/site_template/src/_data/site_metadata.yml +11 -0
- data/lib/site_template/src/_includes/footer.html +3 -0
- data/lib/site_template/src/_includes/head.html +9 -0
- data/lib/site_template/src/_includes/navbar.html +4 -0
- data/lib/site_template/src/_layouts/default.html +15 -0
- data/lib/site_template/src/_layouts/home.html +7 -0
- data/lib/site_template/src/_layouts/page.html +7 -0
- data/lib/site_template/src/_layouts/post.html +7 -0
- data/lib/site_template/src/_posts/0000-00-00-welcome-to-bridgetown.md.erb +26 -0
- data/lib/site_template/src/about.md +11 -0
- data/lib/site_template/src/index.md +7 -0
- data/lib/site_template/webpack.config.js +60 -0
- data/rake/release.rake +30 -0
- metadata +106 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01abda216c9aa5c096d73906bd6b76e516f42286a37039a99d8894497b1896b4
|
|
4
|
+
data.tar.gz: 5dabe33f2ec5614a3637b2880c471e460699ed1f65399abf0b17ab6d92889ceb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 637885282a2398b8715aa05fbed070999a05a0256507a73110591f68eafa0d854acc9831078263e59213dd8b3e4eed11b9838b69620f71653af4d45b4f06555b
|
|
7
|
+
data.tar.gz: da314910ec05c60a3a70b960a5b4a27d45adb68ef019e54366d0c35304023545d4b4d046602b8dcdbdc9055ac00dcd94c96aa665c41bd4c555a08d9639c9875b
|
data/Rakefile
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path("lib", __dir__)
|
|
4
|
+
require "bridgetown-core/version"
|
|
5
|
+
|
|
6
|
+
Dir.glob("rake/**.rake").each { |f| import f }
|
|
7
|
+
|
|
8
|
+
#############################################################################
|
|
9
|
+
#
|
|
10
|
+
# Helper functions
|
|
11
|
+
#
|
|
12
|
+
#############################################################################
|
|
13
|
+
|
|
14
|
+
def name
|
|
15
|
+
"bridgetown-core"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def version
|
|
19
|
+
Bridgetown::VERSION
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def gemspec_file
|
|
23
|
+
"#{name}.gemspec"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def gem_file
|
|
27
|
+
"#{name}-#{Gem::Version.new(version)}.gem"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
#############################################################################
|
|
31
|
+
#
|
|
32
|
+
# Standard tasks
|
|
33
|
+
#
|
|
34
|
+
#############################################################################
|
|
35
|
+
|
|
36
|
+
task :spec => :test
|
|
37
|
+
require "rake/testtask"
|
|
38
|
+
Rake::TestTask.new(:test) do |test|
|
|
39
|
+
test.libs << "lib" << "test"
|
|
40
|
+
test.pattern = "test/**/test_*.rb"
|
|
41
|
+
test.verbose = true
|
|
42
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/bridgetown-core/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "bridgetown-core"
|
|
7
|
+
s.version = Bridgetown::VERSION
|
|
8
|
+
s.license = "MIT"
|
|
9
|
+
s.author = "Bridgetown Team"
|
|
10
|
+
s.email = "maintainers@bridgetownrb.com"
|
|
11
|
+
s.homepage = "https://bridgetownrb.com"
|
|
12
|
+
s.summary = "A Webpack-aware, Ruby-based static site generator for the modern Jamstack era"
|
|
13
|
+
s.description = "Bridgetown is a Webpack-aware, Ruby-powered static site generator for the modern Jamstack era"
|
|
14
|
+
|
|
15
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
16
|
+
f.match(%r{^(benchmark|features|script|test)/})
|
|
17
|
+
end
|
|
18
|
+
s.executables = ["bridgetown"]
|
|
19
|
+
s.bindir = "bin"
|
|
20
|
+
s.require_paths = ["lib"]
|
|
21
|
+
|
|
22
|
+
s.metadata = {
|
|
23
|
+
"source_code_uri" => "https://github.com/bridgetownrb/bridgetown",
|
|
24
|
+
"bug_tracker_uri" => "https://github.com/bridgetownrb/bridgetown/issues",
|
|
25
|
+
"changelog_uri" => "https://github.com/bridgetownrb/bridgetown/releases",
|
|
26
|
+
"homepage_uri" => s.homepage,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
30
|
+
|
|
31
|
+
s.required_ruby_version = ">= 2.4.0"
|
|
32
|
+
s.required_rubygems_version = ">= 2.7.0"
|
|
33
|
+
|
|
34
|
+
s.add_runtime_dependency("addressable", "~> 2.4")
|
|
35
|
+
s.add_runtime_dependency("colorator", "~> 1.0")
|
|
36
|
+
s.add_runtime_dependency("i18n", "~> 1.0")
|
|
37
|
+
s.add_runtime_dependency("kramdown", "~> 2.1")
|
|
38
|
+
s.add_runtime_dependency("kramdown-parser-gfm", "~> 1.0")
|
|
39
|
+
s.add_runtime_dependency("liquid", "~> 4.0")
|
|
40
|
+
s.add_runtime_dependency("listen", "~> 3.0")
|
|
41
|
+
s.add_runtime_dependency("mercenary", "~> 0.4.0")
|
|
42
|
+
s.add_runtime_dependency("pathutil", "~> 0.9")
|
|
43
|
+
s.add_runtime_dependency("rouge", "~> 3.0")
|
|
44
|
+
s.add_runtime_dependency("safe_yaml", "~> 1.0")
|
|
45
|
+
s.add_runtime_dependency("terminal-table", "~> 1.8")
|
|
46
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift __dir__ # For use/testing when no gem is installed
|
|
4
|
+
|
|
5
|
+
# Require all of the Ruby files in the given directory.
|
|
6
|
+
#
|
|
7
|
+
# path - The String relative path from here to the directory.
|
|
8
|
+
#
|
|
9
|
+
# Returns nothing.
|
|
10
|
+
def require_all(path)
|
|
11
|
+
glob = File.join(__dir__, path, "*.rb")
|
|
12
|
+
Dir[glob].sort.each do |f|
|
|
13
|
+
require f
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# rubygems
|
|
18
|
+
require "rubygems"
|
|
19
|
+
|
|
20
|
+
# stdlib
|
|
21
|
+
require "forwardable"
|
|
22
|
+
require "fileutils"
|
|
23
|
+
require "time"
|
|
24
|
+
require "English"
|
|
25
|
+
require "pathname"
|
|
26
|
+
require "logger"
|
|
27
|
+
require "set"
|
|
28
|
+
require "csv"
|
|
29
|
+
require "json"
|
|
30
|
+
|
|
31
|
+
# 3rd party
|
|
32
|
+
require "pathutil"
|
|
33
|
+
require "addressable/uri"
|
|
34
|
+
require "safe_yaml/load"
|
|
35
|
+
require "liquid"
|
|
36
|
+
require "kramdown"
|
|
37
|
+
require "colorator"
|
|
38
|
+
require "i18n"
|
|
39
|
+
|
|
40
|
+
SafeYAML::OPTIONS[:suppress_warnings] = true
|
|
41
|
+
|
|
42
|
+
module Bridgetown
|
|
43
|
+
# internal requires
|
|
44
|
+
autoload :Cleaner, "bridgetown-core/cleaner"
|
|
45
|
+
autoload :Collection, "bridgetown-core/collection"
|
|
46
|
+
autoload :Configuration, "bridgetown-core/configuration"
|
|
47
|
+
autoload :Convertible, "bridgetown-core/convertible"
|
|
48
|
+
autoload :Deprecator, "bridgetown-core/deprecator"
|
|
49
|
+
autoload :Document, "bridgetown-core/document"
|
|
50
|
+
autoload :EntryFilter, "bridgetown-core/entry_filter"
|
|
51
|
+
autoload :Errors, "bridgetown-core/errors"
|
|
52
|
+
autoload :Excerpt, "bridgetown-core/excerpt"
|
|
53
|
+
autoload :External, "bridgetown-core/external"
|
|
54
|
+
autoload :FrontmatterDefaults, "bridgetown-core/frontmatter_defaults"
|
|
55
|
+
autoload :Hooks, "bridgetown-core/hooks"
|
|
56
|
+
autoload :Layout, "bridgetown-core/layout"
|
|
57
|
+
autoload :Cache, "bridgetown-core/cache"
|
|
58
|
+
autoload :CollectionReader, "bridgetown-core/readers/collection_reader"
|
|
59
|
+
autoload :DataReader, "bridgetown-core/readers/data_reader"
|
|
60
|
+
autoload :LayoutReader, "bridgetown-core/readers/layout_reader"
|
|
61
|
+
autoload :PostReader, "bridgetown-core/readers/post_reader"
|
|
62
|
+
autoload :PageReader, "bridgetown-core/readers/page_reader"
|
|
63
|
+
autoload :StaticFileReader, "bridgetown-core/readers/static_file_reader"
|
|
64
|
+
autoload :LogAdapter, "bridgetown-core/log_adapter"
|
|
65
|
+
autoload :Page, "bridgetown-core/page"
|
|
66
|
+
autoload :PageWithoutAFile, "bridgetown-core/page_without_a_file"
|
|
67
|
+
autoload :PathManager, "bridgetown-core/path_manager"
|
|
68
|
+
autoload :PluginManager, "bridgetown-core/plugin_manager"
|
|
69
|
+
autoload :Publisher, "bridgetown-core/publisher"
|
|
70
|
+
autoload :Reader, "bridgetown-core/reader"
|
|
71
|
+
autoload :Regenerator, "bridgetown-core/regenerator"
|
|
72
|
+
autoload :RelatedPosts, "bridgetown-core/related_posts"
|
|
73
|
+
autoload :Renderer, "bridgetown-core/renderer"
|
|
74
|
+
autoload :LiquidRenderer, "bridgetown-core/liquid_renderer"
|
|
75
|
+
autoload :LogWriter, "bridgetown-core/log_writer"
|
|
76
|
+
autoload :Site, "bridgetown-core/site"
|
|
77
|
+
autoload :StaticFile, "bridgetown-core/static_file"
|
|
78
|
+
autoload :URL, "bridgetown-core/url"
|
|
79
|
+
autoload :Utils, "bridgetown-core/utils"
|
|
80
|
+
autoload :VERSION, "bridgetown-core/version"
|
|
81
|
+
autoload :Watcher, "bridgetown-core/watcher"
|
|
82
|
+
|
|
83
|
+
# extensions
|
|
84
|
+
require "bridgetown-core/plugin"
|
|
85
|
+
require "bridgetown-core/converter"
|
|
86
|
+
require "bridgetown-core/generator"
|
|
87
|
+
require "bridgetown-core/command"
|
|
88
|
+
require "bridgetown-core/liquid_extensions"
|
|
89
|
+
require "bridgetown-core/filters"
|
|
90
|
+
|
|
91
|
+
require "bridgetown-core/drops/drop"
|
|
92
|
+
require "bridgetown-core/drops/document_drop"
|
|
93
|
+
require_all "bridgetown-core/commands"
|
|
94
|
+
require_all "bridgetown-core/converters"
|
|
95
|
+
require_all "bridgetown-core/converters/markdown"
|
|
96
|
+
require_all "bridgetown-core/drops"
|
|
97
|
+
require_all "bridgetown-core/generators"
|
|
98
|
+
require_all "bridgetown-core/tags"
|
|
99
|
+
|
|
100
|
+
class << self
|
|
101
|
+
# Public: Tells you which Bridgetown environment you are building in so
|
|
102
|
+
# you can skip tasks if you need to.
|
|
103
|
+
|
|
104
|
+
def env
|
|
105
|
+
ENV["BRIDGETOWN_ENV"] || "development"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Public: Generate a Bridgetown configuration Hash by merging the default
|
|
109
|
+
# options with anything in bridgetown.config.yml, and adding the given
|
|
110
|
+
# options on top.
|
|
111
|
+
#
|
|
112
|
+
# override - A Hash of config directives that override any options in both
|
|
113
|
+
# the defaults and the config file.
|
|
114
|
+
# See Bridgetown::Configuration::DEFAULTS for a
|
|
115
|
+
# list of option names and their defaults.
|
|
116
|
+
#
|
|
117
|
+
# Returns the final configuration Hash.
|
|
118
|
+
def configuration(override = {})
|
|
119
|
+
config = Configuration.new
|
|
120
|
+
override = Configuration[override].stringify_keys
|
|
121
|
+
unless override.delete("skip_config_files")
|
|
122
|
+
config = config.read_config_files(config.config_files(override))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Merge DEFAULTS < bridgetown.config.yml < override
|
|
126
|
+
Configuration.from(Utils.deep_merge_hashes(config, override)).tap do |obj|
|
|
127
|
+
set_timezone(obj["timezone"]) if obj["timezone"]
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Public: Set the TZ environment variable to use the timezone specified
|
|
132
|
+
#
|
|
133
|
+
# timezone - the IANA Time Zone
|
|
134
|
+
#
|
|
135
|
+
# Returns nothing
|
|
136
|
+
# rubocop:disable Naming/AccessorMethodName
|
|
137
|
+
def set_timezone(timezone)
|
|
138
|
+
ENV["TZ"] = if Utils::Platforms.really_windows?
|
|
139
|
+
Utils::WinTZ.calculate(timezone)
|
|
140
|
+
else
|
|
141
|
+
timezone
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
# rubocop:enable Naming/AccessorMethodName
|
|
145
|
+
|
|
146
|
+
# Public: Fetch the logger instance for this Bridgetown process.
|
|
147
|
+
#
|
|
148
|
+
# Returns the LogAdapter instance.
|
|
149
|
+
def logger
|
|
150
|
+
@logger ||= LogAdapter.new(LogWriter.new, (ENV["BRIDGETOWN_LOG_LEVEL"] || :info).to_sym)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Public: Set the log writer.
|
|
154
|
+
# New log writer must respond to the same methods
|
|
155
|
+
# as Ruby's interal Logger.
|
|
156
|
+
#
|
|
157
|
+
# writer - the new Logger-compatible log transport
|
|
158
|
+
#
|
|
159
|
+
# Returns the new logger.
|
|
160
|
+
def logger=(writer)
|
|
161
|
+
@logger = LogAdapter.new(writer, (ENV["BRIDGETOWN_LOG_LEVEL"] || :info).to_sym)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Public: An array of sites
|
|
165
|
+
#
|
|
166
|
+
# Returns the Bridgetown sites created.
|
|
167
|
+
def sites
|
|
168
|
+
@sites ||= []
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Public: Ensures the questionable path is prefixed with the base directory
|
|
172
|
+
# and prepends the questionable path with the base directory if false.
|
|
173
|
+
#
|
|
174
|
+
# base_directory - the directory with which to prefix the questionable path
|
|
175
|
+
# questionable_path - the path we're unsure about, and want prefixed
|
|
176
|
+
#
|
|
177
|
+
# Returns the sanitized path.
|
|
178
|
+
def sanitized_path(base_directory, questionable_path)
|
|
179
|
+
return base_directory if base_directory.eql?(questionable_path)
|
|
180
|
+
|
|
181
|
+
clean_path = questionable_path.dup
|
|
182
|
+
clean_path.insert(0, "/") if clean_path.start_with?("~")
|
|
183
|
+
clean_path = File.expand_path(clean_path, "/")
|
|
184
|
+
|
|
185
|
+
return clean_path if clean_path.eql?(base_directory)
|
|
186
|
+
|
|
187
|
+
# remove any remaining extra leading slashes not stripped away by calling
|
|
188
|
+
# `File.expand_path` above.
|
|
189
|
+
clean_path.squeeze!("/")
|
|
190
|
+
|
|
191
|
+
if clean_path.start_with?(base_directory.sub(%r!\z!, "/"))
|
|
192
|
+
clean_path
|
|
193
|
+
else
|
|
194
|
+
clean_path.sub!(%r!\A\w:/!, "/")
|
|
195
|
+
File.join(base_directory, clean_path)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Conditional optimizations
|
|
200
|
+
Bridgetown::External.require_if_present("liquid/c")
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
module Bridgetown
|
|
6
|
+
class Cache
|
|
7
|
+
# class-wide base cache
|
|
8
|
+
@base_cache = {}
|
|
9
|
+
|
|
10
|
+
# class-wide directive to write cache to disk is enabled by default
|
|
11
|
+
@disk_cache_enabled = true
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# class-wide cache location
|
|
15
|
+
attr_accessor :cache_dir
|
|
16
|
+
|
|
17
|
+
# class-wide directive to write cache to disk
|
|
18
|
+
attr_reader :disk_cache_enabled
|
|
19
|
+
|
|
20
|
+
# class-wide base cache reader
|
|
21
|
+
attr_reader :base_cache
|
|
22
|
+
|
|
23
|
+
# Disable Marshaling cached items to disk
|
|
24
|
+
def disable_disk_cache!
|
|
25
|
+
@disk_cache_enabled = false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Clear all caches
|
|
29
|
+
def clear
|
|
30
|
+
delete_cache_files
|
|
31
|
+
base_cache.each_value(&:clear)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Compare the current config to the cached config
|
|
35
|
+
# If they are different, clear all caches
|
|
36
|
+
#
|
|
37
|
+
# Returns nothing.
|
|
38
|
+
def clear_if_config_changed(config)
|
|
39
|
+
config = config.inspect
|
|
40
|
+
cache = Bridgetown::Cache.new "Bridgetown::Cache"
|
|
41
|
+
return if cache.key?("config") && cache["config"] == config
|
|
42
|
+
|
|
43
|
+
clear
|
|
44
|
+
cache = Bridgetown::Cache.new "Bridgetown::Cache"
|
|
45
|
+
cache["config"] = config
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
# Delete all cached items from all caches
|
|
52
|
+
#
|
|
53
|
+
# Returns nothing.
|
|
54
|
+
def delete_cache_files
|
|
55
|
+
FileUtils.rm_rf(@cache_dir) if disk_cache_enabled
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#
|
|
60
|
+
|
|
61
|
+
# Get an existing named cache, or create a new one if none exists
|
|
62
|
+
#
|
|
63
|
+
# name - name of the cache
|
|
64
|
+
#
|
|
65
|
+
# Returns nothing.
|
|
66
|
+
def initialize(name)
|
|
67
|
+
@cache = Bridgetown::Cache.base_cache[name] ||= {}
|
|
68
|
+
@name = name.gsub(%r![^\w\s-]!, "-")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Clear this particular cache
|
|
72
|
+
def clear
|
|
73
|
+
delete_cache_files
|
|
74
|
+
@cache.clear
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Retrieve a cached item
|
|
78
|
+
# Raises if key does not exist in cache
|
|
79
|
+
#
|
|
80
|
+
# Returns cached value
|
|
81
|
+
def [](key)
|
|
82
|
+
return @cache[key] if @cache.key?(key)
|
|
83
|
+
|
|
84
|
+
path = path_to(hash(key))
|
|
85
|
+
if disk_cache_enabled? && File.file?(path) && File.readable?(path)
|
|
86
|
+
@cache[key] = load(path)
|
|
87
|
+
else
|
|
88
|
+
raise
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Add an item to cache
|
|
93
|
+
#
|
|
94
|
+
# Returns nothing.
|
|
95
|
+
def []=(key, value)
|
|
96
|
+
@cache[key] = value
|
|
97
|
+
return unless disk_cache_enabled?
|
|
98
|
+
|
|
99
|
+
path = path_to(hash(key))
|
|
100
|
+
value = new Hash(value) if value.is_a?(Hash) && !value.default.nil?
|
|
101
|
+
dump(path, value)
|
|
102
|
+
rescue TypeError
|
|
103
|
+
Bridgetown.logger.debug "Cache:", "Cannot dump object #{key}"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# If an item already exists in the cache, retrieve it.
|
|
107
|
+
# Else execute code block, and add the result to the cache, and return that result.
|
|
108
|
+
def getset(key)
|
|
109
|
+
self[key]
|
|
110
|
+
rescue StandardError
|
|
111
|
+
value = yield
|
|
112
|
+
self[key] = value
|
|
113
|
+
value
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Remove one particular item from the cache
|
|
117
|
+
#
|
|
118
|
+
# Returns nothing.
|
|
119
|
+
def delete(key)
|
|
120
|
+
@cache.delete(key)
|
|
121
|
+
File.delete(path_to(hash(key))) if disk_cache_enabled?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Check if `key` already exists in this cache
|
|
125
|
+
#
|
|
126
|
+
# Returns true if key exists in the cache, false otherwise
|
|
127
|
+
def key?(key)
|
|
128
|
+
# First, check if item is already cached in memory
|
|
129
|
+
return true if @cache.key?(key)
|
|
130
|
+
# Otherwise, it might be cached on disk
|
|
131
|
+
# but we should not consider the disk cache if it is disabled
|
|
132
|
+
return false unless disk_cache_enabled?
|
|
133
|
+
|
|
134
|
+
path = path_to(hash(key))
|
|
135
|
+
File.file?(path) && File.readable?(path)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def disk_cache_enabled?
|
|
139
|
+
!!Bridgetown::Cache.disk_cache_enabled
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
# Given a hashed key, return the path to where this item would be saved on disk.
|
|
145
|
+
def path_to(hash = nil)
|
|
146
|
+
@base_dir ||= File.join(Bridgetown::Cache.cache_dir, @name)
|
|
147
|
+
return @base_dir if hash.nil?
|
|
148
|
+
|
|
149
|
+
File.join(@base_dir, hash[0..1], hash[2..-1]).freeze
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Given a key, return a SHA2 hash that can be used for caching this item to disk.
|
|
153
|
+
def hash(key)
|
|
154
|
+
Digest::SHA2.hexdigest(key).freeze
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Remove all this caches items from disk
|
|
158
|
+
#
|
|
159
|
+
# Returns nothing.
|
|
160
|
+
def delete_cache_files
|
|
161
|
+
FileUtils.rm_rf(path_to) if disk_cache_enabled?
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Load `path` from disk and return the result.
|
|
165
|
+
# This MUST NEVER be called in Safe Mode
|
|
166
|
+
# rubocop:disable Security/MarshalLoad
|
|
167
|
+
def load(path)
|
|
168
|
+
raise unless disk_cache_enabled?
|
|
169
|
+
|
|
170
|
+
cached_file = File.open(path, "rb")
|
|
171
|
+
value = Marshal.load(cached_file)
|
|
172
|
+
cached_file.close
|
|
173
|
+
value
|
|
174
|
+
end
|
|
175
|
+
# rubocop:enable Security/MarshalLoad
|
|
176
|
+
|
|
177
|
+
# Given a path and a value, save value to disk at path.
|
|
178
|
+
# This should NEVER be called in Safe Mode
|
|
179
|
+
#
|
|
180
|
+
# Returns nothing.
|
|
181
|
+
def dump(path, value)
|
|
182
|
+
return unless disk_cache_enabled?
|
|
183
|
+
|
|
184
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
185
|
+
File.open(path, "wb") do |cached_file|
|
|
186
|
+
Marshal.dump(value, cached_file)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|