Compare commits

...

8 Commits

Author SHA1 Message Date
Pat Hawks
67e34f7453 Cache highlights 2018-08-07 16:24:53 -05:00
Pat Hawks
214c4cbfdd Cache converted Markdown 2018-08-07 12:57:10 -05:00
Pat Hawks
ef6917254f Abstract out Marshal operations 2018-08-07 11:45:54 -05:00
Pat Hawks
95690cf253 Store cached files in subdirs 2018-08-07 10:02:14 -05:00
Pat Hawks
0110527e4d Fix stupid test in a stupid way.
TODO: Fix this.
2018-08-06 20:35:52 -05:00
Pat Hawks
5afb0b95f2 Use files on disk to add persistence to cache 2018-08-06 20:35:34 -05:00
Pat Hawks
8cb7725b65 Fix errors 2018-08-04 15:02:56 -05:00
Pat Hawks
65beddfdd9 Cache parsed Liquid templates
This adapts @ashmaroli's work in #7136 to use this caching mechanism.
2018-08-04 14:27:11 -05:00
7 changed files with 137 additions and 41 deletions

View File

@@ -1,11 +1,13 @@
# frozen_string_literal: true
require "digest"
require "fileutils"
require "pstore"
module Jekyll
class Cache
extend Forwardable
def_delegators :@cache, :[], :[]=, :clear, :delete, :key?
# Get an existing named cache, or create a new one if none exists
#
# name - name of the cache
@@ -13,31 +15,113 @@ module Jekyll
# Returns nothing.
# rubocop:disable Style/ClassVars
def initialize(name)
@@base_dir ||= File.expand_path(".jekyll-cache/Jekyll/Cache")
@@caches ||= {}
@@caches[name] ||= {}
@cache = @@caches[name]
@cache = @@caches[name] ||= {}
@name = name
FileUtils.mkdir_p(path_to)
end
def self.clear
@@caches ||= {}
@@caches.clear
delete_cache_files
@@caches.each_value(&:clear)
end
# rubocop:enable Style/ClassVars
# rubocop:disable Lint/UselessSetterCall
def self.clear_if_config_changed(config)
cache = Jekyll::Cache.new "Jekyll::Cache"
clear unless cache["config"] == config
cache["config"] = config
def clear
delete_cache_files
@cache.clear
end
# rubocop:enable Lint/UselessSetterCall
def getset(key)
if key?(key)
@cache[key]
def [](key)
return @cache[key] if @cache.key?(key)
path = path_to(hash(key))
if File.file?(path) && File.readable?(path)
@cache[key] = load(path)
else
@cache[key] = yield
raise
end
end
def getset(key)
return @cache[key] if @cache.key?(key)
path = path_to(hash(key))
if File.file?(path) && File.readable?(path)
value = load(path)
else
value = yield
dump(path, value)
end
@cache[key] = value
end
def []=(key, value)
@cache[key] = value
path = path_to(hash(key))
dump(path, value)
end
def delete(key)
@cache.delete(key)
path = path_to(hash(key))
File.delete(path)
end
def key?(key)
return true if @cache.key?(key)
path = path_to(hash(key))
File.file?(path) && File.readable?(path)
end
# rubocop:disable Style/ClassVars
def self.clear_if_config_changed(config)
config = config.inspect
cache = Jekyll::Cache.new "Jekyll::Cache"
unless cache.key?("config") && cache["config"] == config
delete_cache_files
@@caches = {}
cache = Jekyll::Cache.new "Jekyll::Cache"
cache["config"] = config
end
end
# rubocop:enable Style/ClassVars
private
def path_to(hash = nil)
@base_dir ||= File.join(@@base_dir, @name)
return @base_dir if hash.nil?
File.join(@base_dir, hash[0..1], hash[2..-1]).freeze
end
def hash(key)
Digest::SHA2.hexdigest(key).freeze
end
def delete_cache_files
FileUtils.rm_rf(path_to)
end
# rubocop:disable Security/MarshalLoad
def load(path)
cached_file = File.open(path, "rb")
value = Marshal.load(cached_file)
cached_file.close
value
end
# rubocop:enable Security/MarshalLoad
def dump(path, value)
dir, _file = File.split(path)
FileUtils.mkdir_p(dir)
cached_file = File.open(path, "wb")
Marshal.dump(value, cached_file)
cached_file.close
end
def self.delete_cache_files
FileUtils.rm_rf(@@base_dir)
end
private_class_method :delete_cache_files
end
end

View File

@@ -19,6 +19,8 @@ module Jekyll
raise Errors::FatalException, "Bailing out; invalid Markdown processor."
end
@cache = Jekyll::Cache.new("Jekyll::Converters::Markdown")
@setup = true
end
@@ -70,7 +72,9 @@ module Jekyll
def convert(content)
setup
@parser.convert(content)
@cache.getset(content) do
@parser.convert(content)
end
end
private

View File

@@ -10,7 +10,9 @@ module Jekyll
def parse(content)
measure_time do
@template = Liquid::Template.parse(content, :line_numbers => true)
@template = cache.getset(content) do
Liquid::Template.parse(content, :line_numbers => true)
end
end
self
@@ -38,6 +40,10 @@ module Jekyll
private
def cache
Jekyll::Cache.new("Jekyll::LiquidRenderer::File")
end
def measure_bytes
yield.tap do |str|
@renderer.increment_bytes(@filename, str.bytesize)

View File

@@ -31,22 +31,25 @@ module Jekyll
def render(context)
prefix = context["highlighter_prefix"] || ""
suffix = context["highlighter_suffix"] || ""
code = super.to_s.gsub(%r!\A(\n|\r)+|(\n|\r)+\z!, "")
key = super.to_s
cache.getset(key) do
code = key.gsub(%r!\A(\n|\r)+|(\n|\r)+\z!, "")
is_safe = !!context.registers[:site].safe
is_safe = !!context.registers[:site].safe
output =
case context.registers[:site].highlighter
when "pygments"
render_pygments(code, is_safe)
when "rouge"
render_rouge(code)
else
render_codehighlighter(code)
end
output =
case context.registers[:site].highlighter
when "pygments"
render_pygments(code, is_safe)
when "rouge"
render_rouge(code)
else
render_codehighlighter(code)
end
rendered_output = add_code_tag(output)
prefix + rendered_output + suffix
rendered_output = add_code_tag(output)
prefix + rendered_output + suffix
end
end
def sanitized_opts(opts, is_safe)
@@ -67,6 +70,10 @@ module Jekyll
OPTIONS_REGEX = %r!(?:\w="[^"]*"|\w=\w|\w)+!
def cache
Jekyll::Cache.new("Jekyll::Tags::HighlightBlock")
end
def parse_options(input)
options = {}
return options if input.empty?

View File

@@ -90,13 +90,7 @@ module Jekyll
# Render the variable if required
def render_variable(context)
if @file =~ VARIABLE_SYNTAX
partial = context.registers[:site]
.liquid_renderer
.file("(variable)")
.parse(@file)
partial.render!(context)
end
Liquid::Template.parse(@file).render(context) if @file =~ VARIABLE_SYNTAX
end
def tag_includes_dirs(context)

View File

@@ -17,9 +17,7 @@ module Jekyll
def render(context)
site = context.registers[:site]
liquid = site.liquid_renderer.file("(jekyll:link)")
relative_path = liquid.parse(@relative_path).render(context)
relative_path = Liquid::Template.parse(@relative_path).render(context)
site.each_site_file do |item|
return item.url if item.relative_path == relative_path

View File

@@ -76,6 +76,9 @@ class TestSite < JekyllUnitTest
allow(File).to receive(:directory?).with(theme_dir("_sass")).and_return(true)
allow(File).to receive(:directory?).with(theme_dir("_layouts")).and_return(true)
allow(File).to receive(:directory?).with(theme_dir("_includes")).and_return(false)
allow(File).to receive(:directory?).with(
File.expand_path(".jekyll-cache/Jekyll/Cache/Jekyll::Cache")
).and_return(true)
site = fixture_site("theme" => "test-theme")
assert_equal [source_dir("_includes")], site.includes_load_paths
end