Skip to content

Commit

Permalink
Bypass rendering via Liquid unless required (jekyll#6735)
Browse files Browse the repository at this point in the history
Merge pull request 6735
  • Loading branch information
ashmaroli authored and jekyllbot committed Feb 28, 2018
1 parent 767db94 commit 23bb50c
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 4 deletions.
101 changes: 101 additions & 0 deletions benchmark/conditional_liquid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "liquid"
require "benchmark/ips"

# Test if processing content string without any Liquid constructs, via Liquid,
# is slower than checking whether constructs exist ( using `String#include?` )
# and return-ing the "plaintext" content string as is..
#
# Ref: https://github.com/jekyll/jekyll/pull/6735

# Sample contents
WITHOUT_LIQUID = <<-TEXT.freeze
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor libero at
pharetra tempus. Etiam bibendum magna et metus fermentum, eu cursus lorem
mattis. Curabitur vel dui et lacus rutrum suscipit et eget neque.
Nullam luctus fermentum est id blandit. Phasellus consectetur ullamcorper
ligula, at finibus eros laoreet id. Etiam sit amet est in libero efficitur
tristique. Ut nec magna augue. Quisque ut fringilla lacus, ac dictum enim.
Aliquam vel ornare mauris. Suspendisse ornare diam tempor nulla facilisis
aliquet. Sed ultrices placerat ultricies.
TEXT

WITH_LIQUID = <<-LIQUID.freeze
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor libero at
pharetra tempus. {{ author }} et metus fermentum, eu cursus lorem
mattis. Curabitur vel dui et lacus rutrum suscipit et eget neque.
Nullam luctus fermentum est id blandit. Phasellus consectetur ullamcorper
ligula, {% if author == "Jane Doe" %} at finibus eros laoreet id. {% else %}
Etiam sit amet est in libero efficitur.{% endif %}
tristique. Ut nec magna augue. Quisque ut fringilla lacus, ac dictum enim.
Aliquam vel ornare mauris. Suspendisse ornare diam tempor nulla facilisis
aliquet. Sed ultrices placerat ultricies.
LIQUID

WITH_JUST_LIQUID_VAR = <<-LIQUID.freeze
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor libero at
pharetra tempus. et metus fermentum, eu cursus lorem, ac dictum enim.
mattis. Curabitur vel dui et lacus rutrum suscipit et {{ title }} neque.
Nullam luctus fermentum est id blandit. Phasellus consectetur ullamcorper
ligula, at finibus eros laoreet id. Etiam sit amet est in libero efficitur.
tristique. Ut nec magna augue. {{ author }} Quisque ut fringilla lacus
Aliquam vel ornare mauris. Suspendisse ornare diam tempor nulla facilisis
aliquet. Sed ultrices placerat ultricies.
LIQUID

SUITE = {
:"plain text" => WITHOUT_LIQUID,
:"tags n vars" => WITH_LIQUID,
:"just vars" => WITH_JUST_LIQUID_VAR,
}.freeze

# Mimic how Jekyll's LiquidRenderer would process a non-static file, with
# some dummy payload
def always_liquid(content)
Liquid::Template.error_mode = :warn
Liquid::Template.parse(content, :line_numbers => true).render(
"author" => "John Doe",
"title" => "FooBar"
)
end

# Mimic how the proposed change would first execute a couple of checks and
# proceed to process with Liquid if necessary
def conditional_liquid(content)
return content if content.nil? || content.empty?
return content unless content.include?("{%") || content.include?("{{")
always_liquid(content)
end

# Test https://github.com/jekyll/jekyll/pull/6735#discussion_r165499868
# ------------------------------------------------------------------------
def check_with_regex(content)
!content.to_s.match?(%r!{[{%]!)
end

def check_with_builtin(content)
content.include?("{%") || content.include?("{{")
end

SUITE.each do |key, text|
Benchmark.ips do |x|
x.report("regex-check - #{key}") { check_with_regex(text) }
x.report("builtin-check - #{key}") { check_with_builtin(text) }
x.compare!
end
end
# ------------------------------------------------------------------------

# Let's roll!
SUITE.each do |key, text|
Benchmark.ips do |x|
x.report("always thru liquid - #{key}") { always_liquid(text) }
x.report("conditional liquid - #{key}") { conditional_liquid(text) }
x.compare!
end
end
4 changes: 2 additions & 2 deletions lib/jekyll/convertible.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ def coffeescript_file?

# Determine whether the file should be rendered with Liquid.
#
# Always returns true.
# Returns true if the file has Liquid Tags or Variables, false otherwise.
def render_with_liquid?
true
Jekyll::Utils.has_liquid_construct?(content)
end

# Determine whether the file should be placed into layouts.
Expand Down
3 changes: 2 additions & 1 deletion lib/jekyll/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ def coffeescript_file?
# Determine whether the file should be rendered with Liquid.
#
# Returns false if the document is either an asset file or a yaml file,
# or if the document doesn't contain any Liquid Tags or Variables,
# true otherwise.
def render_with_liquid?
!(coffeescript_file? || yaml_file?)
!(coffeescript_file? || yaml_file? || !Utils.has_liquid_construct?(content))
end

# Determine whether the file should be rendered with a layout.
Expand Down
2 changes: 1 addition & 1 deletion lib/jekyll/renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def render_document
end

Jekyll.logger.debug "Rendering Markup:", document.relative_path
output = convert(output)
output = convert(output.to_s)
document.content = output

if document.place_in_layout?
Expand Down
8 changes: 8 additions & 0 deletions lib/jekyll/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ def has_yaml_header?(file)
rescue EOFError
false
end

# Determine whether the given content string contains Liquid Tags or Vaiables
#
# Returns true is the string contains sequences of `{%` or `{{`
def has_liquid_construct?(content)
return false if content.nil? || content.empty?
content.include?("{%") || content.include?("{{")
end
# rubocop: enable PredicateName

# Slugify a filename or title.
Expand Down

0 comments on commit 23bb50c

Please sign in to comment.