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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +42 -0
  3. data/bridgetown-core.gemspec +46 -0
  4. data/lib/bridgetown-core.rb +202 -0
  5. data/lib/bridgetown-core/cache.rb +190 -0
  6. data/lib/bridgetown-core/cleaner.rb +111 -0
  7. data/lib/bridgetown-core/collection.rb +279 -0
  8. data/lib/bridgetown-core/command.rb +106 -0
  9. data/lib/bridgetown-core/commands/build.rb +96 -0
  10. data/lib/bridgetown-core/commands/clean.rb +43 -0
  11. data/lib/bridgetown-core/commands/console.rb +56 -0
  12. data/lib/bridgetown-core/commands/doctor.rb +172 -0
  13. data/lib/bridgetown-core/commands/help.rb +34 -0
  14. data/lib/bridgetown-core/commands/new.rb +148 -0
  15. data/lib/bridgetown-core/commands/serve.rb +273 -0
  16. data/lib/bridgetown-core/commands/serve/servlet.rb +68 -0
  17. data/lib/bridgetown-core/configuration.rb +323 -0
  18. data/lib/bridgetown-core/converter.rb +54 -0
  19. data/lib/bridgetown-core/converters/identity.rb +39 -0
  20. data/lib/bridgetown-core/converters/markdown.rb +108 -0
  21. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +132 -0
  22. data/lib/bridgetown-core/converters/smartypants.rb +69 -0
  23. data/lib/bridgetown-core/convertible.rb +237 -0
  24. data/lib/bridgetown-core/deprecator.rb +50 -0
  25. data/lib/bridgetown-core/document.rb +475 -0
  26. data/lib/bridgetown-core/drops/bridgetown_drop.rb +32 -0
  27. data/lib/bridgetown-core/drops/collection_drop.rb +20 -0
  28. data/lib/bridgetown-core/drops/document_drop.rb +69 -0
  29. data/lib/bridgetown-core/drops/drop.rb +215 -0
  30. data/lib/bridgetown-core/drops/excerpt_drop.rb +19 -0
  31. data/lib/bridgetown-core/drops/page_drop.rb +14 -0
  32. data/lib/bridgetown-core/drops/site_drop.rb +62 -0
  33. data/lib/bridgetown-core/drops/static_file_drop.rb +14 -0
  34. data/lib/bridgetown-core/drops/unified_payload_drop.rb +26 -0
  35. data/lib/bridgetown-core/drops/url_drop.rb +132 -0
  36. data/lib/bridgetown-core/entry_filter.rb +108 -0
  37. data/lib/bridgetown-core/errors.rb +20 -0
  38. data/lib/bridgetown-core/excerpt.rb +202 -0
  39. data/lib/bridgetown-core/external.rb +62 -0
  40. data/lib/bridgetown-core/filters.rb +467 -0
  41. data/lib/bridgetown-core/filters/date_filters.rb +110 -0
  42. data/lib/bridgetown-core/filters/grouping_filters.rb +64 -0
  43. data/lib/bridgetown-core/filters/url_filters.rb +79 -0
  44. data/lib/bridgetown-core/frontmatter_defaults.rb +238 -0
  45. data/lib/bridgetown-core/generator.rb +5 -0
  46. data/lib/bridgetown-core/hooks.rb +103 -0
  47. data/lib/bridgetown-core/layout.rb +57 -0
  48. data/lib/bridgetown-core/liquid_extensions.rb +22 -0
  49. data/lib/bridgetown-core/liquid_renderer.rb +71 -0
  50. data/lib/bridgetown-core/liquid_renderer/file.rb +67 -0
  51. data/lib/bridgetown-core/liquid_renderer/table.rb +75 -0
  52. data/lib/bridgetown-core/log_adapter.rb +151 -0
  53. data/lib/bridgetown-core/log_writer.rb +60 -0
  54. data/lib/bridgetown-core/mime.types +867 -0
  55. data/lib/bridgetown-core/page.rb +214 -0
  56. data/lib/bridgetown-core/page_without_a_file.rb +14 -0
  57. data/lib/bridgetown-core/path_manager.rb +31 -0
  58. data/lib/bridgetown-core/plugin.rb +80 -0
  59. data/lib/bridgetown-core/plugin_manager.rb +60 -0
  60. data/lib/bridgetown-core/publisher.rb +23 -0
  61. data/lib/bridgetown-core/reader.rb +185 -0
  62. data/lib/bridgetown-core/readers/collection_reader.rb +22 -0
  63. data/lib/bridgetown-core/readers/data_reader.rb +75 -0
  64. data/lib/bridgetown-core/readers/layout_reader.rb +48 -0
  65. data/lib/bridgetown-core/readers/page_reader.rb +24 -0
  66. data/lib/bridgetown-core/readers/post_reader.rb +74 -0
  67. data/lib/bridgetown-core/readers/static_file_reader.rb +24 -0
  68. data/lib/bridgetown-core/regenerator.rb +195 -0
  69. data/lib/bridgetown-core/related_posts.rb +52 -0
  70. data/lib/bridgetown-core/renderer.rb +261 -0
  71. data/lib/bridgetown-core/site.rb +469 -0
  72. data/lib/bridgetown-core/static_file.rb +205 -0
  73. data/lib/bridgetown-core/tags/component.rb +34 -0
  74. data/lib/bridgetown-core/tags/highlight.rb +111 -0
  75. data/lib/bridgetown-core/tags/include.rb +220 -0
  76. data/lib/bridgetown-core/tags/link.rb +41 -0
  77. data/lib/bridgetown-core/tags/post_url.rb +107 -0
  78. data/lib/bridgetown-core/url.rb +164 -0
  79. data/lib/bridgetown-core/utils.rb +367 -0
  80. data/lib/bridgetown-core/utils/ansi.rb +57 -0
  81. data/lib/bridgetown-core/utils/exec.rb +26 -0
  82. data/lib/bridgetown-core/utils/internet.rb +37 -0
  83. data/lib/bridgetown-core/utils/platforms.rb +80 -0
  84. data/lib/bridgetown-core/utils/thread_event.rb +31 -0
  85. data/lib/bridgetown-core/utils/win_tz.rb +75 -0
  86. data/lib/bridgetown-core/version.rb +5 -0
  87. data/lib/bridgetown-core/watcher.rb +139 -0
  88. data/lib/site_template/.gitignore +6 -0
  89. data/lib/site_template/bridgetown.config.yml +21 -0
  90. data/lib/site_template/frontend/javascript/index.js +3 -0
  91. data/lib/site_template/frontend/styles/index.scss +17 -0
  92. data/lib/site_template/package.json +23 -0
  93. data/lib/site_template/src/404.html +9 -0
  94. data/lib/site_template/src/_data/site_metadata.yml +11 -0
  95. data/lib/site_template/src/_includes/footer.html +3 -0
  96. data/lib/site_template/src/_includes/head.html +9 -0
  97. data/lib/site_template/src/_includes/navbar.html +4 -0
  98. data/lib/site_template/src/_layouts/default.html +15 -0
  99. data/lib/site_template/src/_layouts/home.html +7 -0
  100. data/lib/site_template/src/_layouts/page.html +7 -0
  101. data/lib/site_template/src/_layouts/post.html +7 -0
  102. data/lib/site_template/src/_posts/0000-00-00-welcome-to-bridgetown.md.erb +26 -0
  103. data/lib/site_template/src/about.md +11 -0
  104. data/lib/site_template/src/index.md +7 -0
  105. data/lib/site_template/webpack.config.js +60 -0
  106. data/rake/release.rake +30 -0
  107. metadata +106 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bdc825b903ba9de033edc8fcce7b94f871cd6c98b4c267856316a5f842f0c6d
4
- data.tar.gz: d8aa948572f48e2450059cd47ac3d6766d6cc43494ebe771f9859a01bcb9bb9c
3
+ metadata.gz: 01abda216c9aa5c096d73906bd6b76e516f42286a37039a99d8894497b1896b4
4
+ data.tar.gz: 5dabe33f2ec5614a3637b2880c471e460699ed1f65399abf0b17ab6d92889ceb
5
5
  SHA512:
6
- metadata.gz: 3d2fd4b262ca60a39b3b3799caddb655c48808c336e5c266c55a06886a3e64e2bc54dbd54cc5f338b08bb089d10bfa9a7fec0c95bddbaded541d60b56615461e
7
- data.tar.gz: 2c5b6899c86c1a48662b0d7229ac65bfacf487a88444f6b2b0bc3481ad668e3ccf11fcb7bef14b37ec375c07d92dcc1e1120067104b575fda9945349e811e6c0
6
+ metadata.gz: 637885282a2398b8715aa05fbed070999a05a0256507a73110591f68eafa0d854acc9831078263e59213dd8b3e4eed11b9838b69620f71653af4d45b4f06555b
7
+ data.tar.gz: da314910ec05c60a3a70b960a5b4a27d45adb68ef019e54366d0c35304023545d4b4d046602b8dcdbdc9055ac00dcd94c96aa665c41bd4c555a08d9639c9875b
@@ -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