Skip to content

Instantly share code, notes, and snippets.

@dgopstein
Created March 10, 2017 07:33
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dgopstein/7fcb514d163f7b090edd5a98b9f3f9a7 to your computer and use it in GitHub Desktop.
Save dgopstein/7fcb514d163f7b090edd5a98b9f3f9a7 to your computer and use it in GitHub Desktop.
Jekyll Plugin for Textual Inclusion in Data Files
# Treat every _data file as liquid.
# This allows us to include YAML files in other YAML files.
module Jekyll
# Monkey patch Jekyll::DataReader::read_data_file with our own implementation
class DataReader
def read_data_file_with_liquid(path)
begin
dir = File.dirname(path)
filename = File.basename(path)
# If there are multiple sites assume we're
# the most recent since we're just starting up
site = Jekyll.sites.last
content = File.read(site.in_source_dir(dir, filename))
template = Liquid::Template.parse(content)
context = Liquid::Context.new({}, {}, { :site => site })
rendered = template.render(context)
# Write the post-liquid-rendered file to a temporary file.
# read_data_file parses the name of the file to use as its
# variable name in site.data so it's important to make the
# temp file name match the original file name.
Dir.mktmpdir do |tmp_dir|
tmp_path = File.join(tmp_dir, filename)
File.write(tmp_path, rendered)
read_data_file_without_liquid(tmp_path)
end
rescue => e
Jekyll.logger.warn(
"[Liquid Data] Error parsing data files " +
"for Liquid content at file #{path}: #{e.message}")
end
end
# Make our function overwrite the existing read_data_file function
# but keep the ability to still call back to the original
alias_method :read_data_file_without_liquid, :read_data_file
alias_method :read_data_file, :read_data_file_with_liquid
end
end
# Only include the given file one time (in this call tree)
# Useful for files that include files that include the original file
module Jekyll
module Tags
class IncludeRelativeOnceTag < IncludeRelativeTag
# Create a flag that indicates we're already 1 level
# deep in the inclusion, and don't go any farther down
SENTINEL = 'included_relative_once'
def render(context)
context.stack do
unless context[SENTINEL]
context[SENTINEL] = true
super(context)
end
end
end
end
end
end
Liquid::Template.register_tag("include_relative_once", Jekyll::Tags::IncludeRelativeOnceTag)
@erinkcochran87
Copy link

@dgopstein - Hey! I've been looking for a solution to this problem for ages and so far, this is the closest and best thing I've found. Thanks for putting this together and sharing it :)

I'm not a developer at all - I use Jekyll to write and manage my company's documentation. So while I dabble in Ruby, calling myself proficient would be generous. That being said, I hope you don't mind answering a few questions:

  1. I see that this treats every file in _data as a Liquid file - is there a way to exclude files from being read this way? In my setup, I have a lot of data files that don't need this functionality, which is throwing a ton of errors when I start up the server.
  2. Is there a way to read YAML that isn't in _data? In my case, I set up a collection that contains files with data about database schemas. This is the only place in my site that I'd like to use this.

Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment