Including external files in the Jekyll template
Is it possible to include an html file from a different domain inside a Jekyll template? And if so, what would be the syntax?
I am not a Ruby or Jekyll developer, more or less asking on behalf of another, so please forgive me if the answer is obvious! At least I couldn't find an answer with some initial research.
Basically we are trying to pull the footer markup from another domain, this is how production will work, so we are just trying to simulate it in our original results.
Greetings
source to share
You cannot do this inside the template itself. However, you can define a custom Liquid tag that dumps the markup of the remote page and then puts that tag in the template. This will be in a file like eg.plugins/remote_footer.rb
require 'nokogiri'
require 'open-uri'
require 'uri'
module Jekyll
class RemoteFooterTag < Liquid::Tag
def initialize(tag_name, markup, tokens)
#markup is what is defined in the tag. Lets make it a URL so devs
#don't have to update code if the URL changes.
url = markup
#check if the URL is valid
if url =~ URI::regexp
#grab the remote document with nokogiri
doc = Nokogiri::HTML(open(url))
#search the document for the HTML element you want
@node = doc.at_xpath("//div[@id='footer']")
else
raise 'Invalid URL passed to RemoteFooterTag'
end
super
end
def render(context)
output = super
if @node
node.to_s
else
"Something went wrong in RemoteFooterTag"
end
end
end
end
Liquid::Template.register_tag('remote_footer', Jekyll::RemoteFooterTag)
And then in your template:
{% remote_footer http://google.com %}
I quickly threw this together and did not test if it works, but hopefully this is enough for it to work. Keep in mind that this will run once, when the liquid parser is running on the page, and if the deleted item changes, it won't be displayed until the Jekyll site is restored.
source to share
I just stumbled upon this problem and I couldn't find any working solution for all the use cases I had, so I wrote my own plugin.
NB This is the first piece of ruby that I have ever written.
require 'nokogiri'
require 'open-uri'
require 'uri'
class Jekyll::IncludeRemoteTag < Jekyll::Tags::IncludeTag
@@remote_cache = {}
def initialize(tag_name, markup, tokens)
super
@url = @file
end
def validate_url(url)
if url !~ URI::regexp
raise ArgumentError.new <<-eos
Invalid syntax for include_remote tag. URL contains invalid characters or sequences:
#{url}
Valid syntax:
#{syntax_example}
eos
end
end
def syntax_example
"{% #{@tag_name} http://domain.ltd css=\".menu\" xpath=\"//div[@class='.menu']\" param=\"value\" param2=\"value\" %}"
end
def render(context)
@url = render_variable(context) || @url
validate_url(@url)
if @params
validate_params
@params = parse_params(context)
end
xpath = @params['xpath']
css = @params['css']
if ! html = @@remote_cache["#{@url}_#{xpath}"]
# fetch remote file
page = Nokogiri::HTML(open(@url))
# parse extract xpath/css fragments if necessary
node = page.at_xpath(xpath) if xpath
node = page.css(css) if css
node = page if !node
raise IOError.new "Error while parsing remote file '#{@url}': '#{xpath||css}' not found" if !node
# cache result
html = @@remote_cache["#{@url}_#{xpath}"] = node.to_s
end
begin
partial = Liquid::Template.parse(html)
context.stack do
context['include'] = @params
partial.render!(context)
end
rescue => e
raise Jekyll::Tags::IncludeTagError.new e.message, @url
end
end
end
Liquid::Template.register_tag('include_remote', Jekyll::IncludeRemoteTag)
And you will use it like this:
<!-- fetch header.html -->
{% assign url = 'http://mything.me/_includes/header.html' %}
{% include_remote {{ url }} %}
<!-- fetch menu.html and extract div.menu -->
{% include_remote 'http://mything.me/_includes/menu.html' css="div.menu" links=site.data.menu %}
<!-- fetch menu.html and extract div.menu (xpath version) -->
{% include_remote 'http://mything.me/_includes/menu.html' xpath="div[@class='menu']" links=site.data.menu %}
It basically works exactly the same as a regular include file, but it has been removed.
Available for download here: https://gist.github.com/kilianc/a6d87879735d4a68b34f
MIT license.
source to share