jekyll-jolt 0.21.0
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +175 -0
- data/Rakefile +16 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/jekyll-jolt.gemspec +34 -0
- data/lib/jekyll-jolt.rb +1 -0
- data/lib/jekyll/jolt.rb +354 -0
- data/lib/jekyll/jolt/version.rb +5 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: '0841de46d9f0b373b983cd1ff34c08c9fff6622a'
|
4
|
+
data.tar.gz: c0002e01455caa6ac4f6c840940b58255a08899c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb9cce40757afc656917b18df1a911ca42fe8985a431cea948b1fa452222010586af402d4752d243c5fccf99a48b4b089a699b5594c2db51a72465033b7fb192
|
7
|
+
data.tar.gz: 8a3a31142adc02f30ded919fafc5a102c0b4669ef5d887dae782f4802ecac0fe59b4d9cdcca69b3139880f310721a7916edc820de35eaadc541b3a93bfe5463b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Help Scout
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
# Jolt ⚡️ [](https://travis-ci.org/helpscout/jekyll-jolt) [](https://badge.fury.io/rb/jekyll-jolt)
|
2
|
+
|
3
|
+
Jekyll library for creating custom template blocks (with YAML front matter support)
|
4
|
+
|
5
|
+
Fun fact: Jolt is an acronym for (Jekyll Optimized Liquid Templates)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'jekyll-jolt'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
```
|
17
|
+
bundle
|
18
|
+
```
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
```
|
22
|
+
gem install jekyll-jolt
|
23
|
+
```
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
---
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
## Documentation
|
32
|
+
|
33
|
+
Templates (`{% template %}`) work similarly to Jekyll's `{% include %}` tag. It references an existing `.html` file for markup. However, the biggest difference (and most awesome feature) between `{% template %}` vs. `{% include %}` is that templates allow for content to be used inside the block.
|
34
|
+
|
35
|
+
### Setting up the template directory
|
36
|
+
|
37
|
+
The first thing you have to do to allow for template blocks to work is to create a new directory called `_templates` within your Jekyll site's source directory:
|
38
|
+
|
39
|
+
```
|
40
|
+
my-jekyll-site/
|
41
|
+
├── _data/
|
42
|
+
├── _includes/
|
43
|
+
├── _plugins/
|
44
|
+
├── _posts/
|
45
|
+
├── _templates/ <-- Right here!
|
46
|
+
└── index.md
|
47
|
+
```
|
48
|
+
|
49
|
+
Once you have your directory created, add template files as regular `.html` files (just like you would `_includes/` files).
|
50
|
+
|
51
|
+
|
52
|
+
### Creating a template file
|
53
|
+
|
54
|
+
Let's create a template file called `awesome.html`, which will be added to `_templates`.
|
55
|
+
(Full path is `_templates/awesome.html`)
|
56
|
+
|
57
|
+
```markdown
|
58
|
+
<div class="awesome">
|
59
|
+
{{ template.content }}
|
60
|
+
</div>
|
61
|
+
```
|
62
|
+
|
63
|
+
You can write whatever markup you would like inside a template file. The most important thing is to include a `{{ template.content }}` tag. This destinates where your content will be rendered.
|
64
|
+
|
65
|
+
|
66
|
+
### Using a template block
|
67
|
+
|
68
|
+
After creating our `awesome.html` template, we can use it in any of our Jekyll pages (or posts… heck even in `_include` files).
|
69
|
+
|
70
|
+
For this example, let's add it to our `index.md` file:
|
71
|
+
|
72
|
+
```markdown
|
73
|
+
# Hello
|
74
|
+
{% template awesome.html %}
|
75
|
+
I am content!
|
76
|
+
{% endtemplate %}
|
77
|
+
```
|
78
|
+
|
79
|
+
Your template content needs to begin with `{% template %}` and end with `{% endtemplate %}`. Be sure to include the path/name of the template file you wish to use.
|
80
|
+
|
81
|
+
The final rendered `.html` will look like this:
|
82
|
+
|
83
|
+
```html
|
84
|
+
<h1 id="hello">Hello</h1>
|
85
|
+
<div class="awesome"> <p>I am content!</p> </div>
|
86
|
+
```
|
87
|
+
|
88
|
+
|
89
|
+
## Rendering template content as HTML
|
90
|
+
|
91
|
+
By default, templates parse and render content as **markdown**. To force templates to render content as HTML, all the `parse: "html"` attribute to your `{% template %}` tag.
|
92
|
+
|
93
|
+
```markdown
|
94
|
+
{% template awesome.html parse: "html" %}
|
95
|
+
# Title
|
96
|
+
I am content! As HTML!
|
97
|
+
{% endtemplate %}
|
98
|
+
```
|
99
|
+
|
100
|
+
The final rendered `.html` will look like this:
|
101
|
+
|
102
|
+
```html
|
103
|
+
<div class="awesome"> # Title I am content! As HTML! </div>
|
104
|
+
```
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
## Using YAML front matter
|
109
|
+
|
110
|
+
You can add YAML front matter to both your template files, just like Jekyll pages and posts.
|
111
|
+
|
112
|
+
```
|
113
|
+
---
|
114
|
+
title: Awesome title
|
115
|
+
---
|
116
|
+
<div class="awesome">
|
117
|
+
<h1>{{ template.title</h1>
|
118
|
+
|
119
|
+
{{ template.content }}
|
120
|
+
</div>
|
121
|
+
```
|
122
|
+
|
123
|
+
Front matter can also be defined in your `{% template %}` block. Any front matter data defined here will override the data defined in your original template.
|
124
|
+
|
125
|
+
```
|
126
|
+
{% template awesome.html %}
|
127
|
+
---
|
128
|
+
title: Best title
|
129
|
+
---
|
130
|
+
I am content!
|
131
|
+
{% endtemplate %}
|
132
|
+
```
|
133
|
+
|
134
|
+
```html
|
135
|
+
<div class="awesome">
|
136
|
+
<h1>Best title</h1>
|
137
|
+
<p>I am content!</p>
|
138
|
+
</div>
|
139
|
+
```
|
140
|
+
|
141
|
+
|
142
|
+
## Using templates within templates
|
143
|
+
|
144
|
+
Yo dawg. I heard you liked templates! The template block supports nesting 👏
|
145
|
+
|
146
|
+
```markdown
|
147
|
+
{% template outer.html %}
|
148
|
+
{% template inner.html %}
|
149
|
+
Hi!
|
150
|
+
{% endtemplate %}
|
151
|
+
{% endtemplate %}
|
152
|
+
```
|
153
|
+
|
154
|
+
|
155
|
+
---
|
156
|
+
|
157
|
+
|
158
|
+
More documentation coming soon!
|
159
|
+
|
160
|
+
|
161
|
+
---
|
162
|
+
|
163
|
+
|
164
|
+
## Note
|
165
|
+
|
166
|
+
I am **not** a Ruby developer. (My background is mostly with Javascript). I wrote this plugin based on experimentation and combing through [Jekyll's](https://github.com/jekyll/jekyll) and [Liquid's](https://github.com/Shopify/liquid) source code + documentation. I'm sure there's probably code in there somewhere that's offensive to Ruby devs.
|
167
|
+
|
168
|
+
We've been using `{% template %}` for many months now on the [Help Scout website](https://www.helpscout.net/), and it's been working great! We haven't noticed any slowdowns in build times (and we use **a lot** of templates).
|
169
|
+
|
170
|
+
|
171
|
+
---
|
172
|
+
|
173
|
+
|
174
|
+
## Thanks ❤️
|
175
|
+
Many thanks to [@alisdair](https://github.com/alisdair) for his help with code review/testing + [@hownowstephen](https://github.com/hownowstephen) for his help with Ruby things.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'rdoc'
|
5
|
+
require 'date'
|
6
|
+
require 'yaml'
|
7
|
+
require 'rake/testtask'
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[lib]))
|
10
|
+
require 'jekyll/version'
|
11
|
+
|
12
|
+
Rake::TestTask.new(:test) do |test|
|
13
|
+
test.libs << 'lib' << 'test'
|
14
|
+
test.pattern = 'test/**/test_*.rb'
|
15
|
+
test.verbose = true
|
16
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "jekyll/template"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/jekyll-jolt.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jekyll/jolt/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "jekyll-jolt"
|
8
|
+
spec.version = Jekyll::Jolt::VERSION
|
9
|
+
spec.authors = ["ItsJonQ"]
|
10
|
+
spec.email = ["itsjonq@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Jekyll library for creating custom template blocks"
|
13
|
+
spec.homepage = "https://github.com/helpscout/jekyll-jolt"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency("jekyll", ">= 3.1.2")
|
24
|
+
spec.add_runtime_dependency("htmlcompressor", "~> 0.3.1")
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "minitest-reporters"
|
29
|
+
spec.add_development_dependency "minitest-profile"
|
30
|
+
spec.add_development_dependency "minitest", "~> 5.8"
|
31
|
+
spec.add_development_dependency "rspec-mocks"
|
32
|
+
spec.add_development_dependency "shoulda"
|
33
|
+
spec.add_development_dependency "kramdown"
|
34
|
+
end
|
data/lib/jekyll-jolt.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "jekyll/jolt"
|
data/lib/jekyll/jolt.rb
ADDED
@@ -0,0 +1,354 @@
|
|
1
|
+
require "htmlcompressor"
|
2
|
+
require "jekyll"
|
3
|
+
require "jekyll/jolt/version"
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module Tags
|
7
|
+
class TemplateBlock < Liquid::Block
|
8
|
+
include Liquid::StandardFilters
|
9
|
+
|
10
|
+
CONTEXT_NAME = "template"
|
11
|
+
CONTEXT_CACHE_NAME = :cached_templates
|
12
|
+
CONTEXT_DATA_NAME = :template_data
|
13
|
+
CONTEXT_SCOPE_NAME = :template_data_scope
|
14
|
+
CONTEXT_STORE_NAME = :template_data_store
|
15
|
+
|
16
|
+
PROPS_NAME = "props"
|
17
|
+
TEMPLATE_DIR = "_templates"
|
18
|
+
|
19
|
+
LIQUID_SYNTAX_REGEXP = /(#{Liquid::QuotedFragment}+)?/
|
20
|
+
PROPS_REGEXP = /#{PROPS_NAME}\./
|
21
|
+
WHITESPACE_REGEXP = %r!^\s*!m
|
22
|
+
# Source
|
23
|
+
# https://github.com/jekyll/jekyll/blob/35c5e073625100b0f8f8eab6f7da6cb6d5734930/lib/jekyll/document.rb
|
24
|
+
YAML_FRONT_MATTER_REGEXP = %r!(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
|
25
|
+
|
26
|
+
# initialize
|
27
|
+
# Description: Extends Liquid's default initialize method.
|
28
|
+
def initialize(tag_name, markup, tokens)
|
29
|
+
super
|
30
|
+
|
31
|
+
if markup =~ LIQUID_SYNTAX_REGEXP
|
32
|
+
@attributes = {}
|
33
|
+
@context = false
|
34
|
+
@id = rand(36**8).to_s(36).freeze
|
35
|
+
@props = {}
|
36
|
+
@sanitize = false
|
37
|
+
@site = false
|
38
|
+
@template_name = $1.freeze
|
39
|
+
|
40
|
+
@compressor = HtmlCompressor::Compressor.new({
|
41
|
+
:remove_comments => true
|
42
|
+
}).freeze
|
43
|
+
|
44
|
+
# Parse parameters
|
45
|
+
# Source: https://gist.github.com/jgatjens/8925165
|
46
|
+
markup.scan(Liquid::TagAttributes) do |key, value|
|
47
|
+
if (value =~ PROPS_REGEXP) != nil
|
48
|
+
@attributes[key] = value
|
49
|
+
else
|
50
|
+
@attributes[key] = Liquid::Expression.parse(value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
raise SyntaxError.new(options[:locale].t("errors.syntax.include".freeze))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# blank?
|
59
|
+
# Description: Override's Liquid's default blank checker. This allows
|
60
|
+
# for templates to be used without passing inner content.
|
61
|
+
def blank?
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
# template_store_data(data = Array)
|
66
|
+
# Description: Stores/updates the template data in cache
|
67
|
+
# Returns: Hash of the template store data
|
68
|
+
def template_store_data(data = {})
|
69
|
+
@context.registers[CONTEXT_STORE_NAME] ||= {}
|
70
|
+
unless @context.registers[CONTEXT_STORE_NAME].key?(@id)
|
71
|
+
@context.registers[CONTEXT_STORE_NAME][@id] = {
|
72
|
+
"id": @id,
|
73
|
+
"index": @context.registers[CONTEXT_STORE_NAME].length,
|
74
|
+
"template_name": @template_name
|
75
|
+
}
|
76
|
+
end
|
77
|
+
@context.registers[CONTEXT_STORE_NAME][@id] = @context.registers[CONTEXT_STORE_NAME][@id].merge(data)
|
78
|
+
end
|
79
|
+
|
80
|
+
# prop?
|
81
|
+
# Description: Determines if the variable is a template.props key
|
82
|
+
# Return: Boolean
|
83
|
+
def prop?(variable = "")
|
84
|
+
(variable =~ PROPS_REGEXP) != nil
|
85
|
+
end
|
86
|
+
|
87
|
+
# prop(data = Hash, value = String)
|
88
|
+
# Description: Returns the props value
|
89
|
+
def prop(data, value = "")
|
90
|
+
index = data[:index]
|
91
|
+
value = data[value.gsub(PROPS_REGEXP, "")]
|
92
|
+
if value and prop?(value) and index > 0
|
93
|
+
store = @context.registers[CONTEXT_STORE_NAME]
|
94
|
+
previous_scope = store[store.keys[index - 1]]
|
95
|
+
prop(previous_scope, value)
|
96
|
+
else
|
97
|
+
value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# evaluate_props
|
102
|
+
# Description: Evaluates props that are being passed into the template.
|
103
|
+
def evaluate_props()
|
104
|
+
store = @context.registers[CONTEXT_STORE_NAME]
|
105
|
+
data = store[@id]
|
106
|
+
index = data[:index]
|
107
|
+
|
108
|
+
if (index > 0)
|
109
|
+
parent = store[store.keys[index - 1]]
|
110
|
+
# Update the data scope
|
111
|
+
@context[CONTEXT_SCOPE_NAME] = parent
|
112
|
+
data.each do |key, value|
|
113
|
+
if prop?(value)
|
114
|
+
value = prop(parent, value)
|
115
|
+
if value
|
116
|
+
@props[key] = value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# render
|
124
|
+
# Description: Extends Liquid's default render method. This method also
|
125
|
+
# adds additional features:
|
126
|
+
# - YAML front-matter parsing and handling
|
127
|
+
# - properly handles indentation and whitespace (resolves rendering issues)
|
128
|
+
# - ability to parse content as markdown vs. html
|
129
|
+
# - supports custom attributes to be used in template
|
130
|
+
def render(context)
|
131
|
+
@context = context
|
132
|
+
@site = @context.registers[:site]
|
133
|
+
|
134
|
+
template_store_data(@attributes)
|
135
|
+
|
136
|
+
# This allows for Jekyll intelligently re-render markup during
|
137
|
+
# incremental builds.
|
138
|
+
add_template_to_dependency(@template_name)
|
139
|
+
# Loading the template from cache/template directory
|
140
|
+
template = load_cached_template(@template_name)
|
141
|
+
|
142
|
+
# Props must be evaluated before super is initialized.
|
143
|
+
# This allows for props to be evaluated before they're parsed by Liquid.
|
144
|
+
evaluate_props()
|
145
|
+
|
146
|
+
content = super
|
147
|
+
|
148
|
+
# Return the parsed/normalized content
|
149
|
+
render_template(template, content)
|
150
|
+
end
|
151
|
+
|
152
|
+
# render_template(template = Liquid::Template, content = String)
|
153
|
+
# Description: Serializes the context to be rendered by Liquid. Also
|
154
|
+
# resets the context to ensure template data doesn't leak from
|
155
|
+
# the scope.
|
156
|
+
# Returns: String
|
157
|
+
def render_template(template, content)
|
158
|
+
# Define the default template attributes
|
159
|
+
# Source:
|
160
|
+
# https://github.com/Shopify/liquid/blob/9a7778e52c37965f7b47673da09cfb82856a6791/lib/liquid/tags/include.rb
|
161
|
+
@context[CONTEXT_NAME] = Hash.new
|
162
|
+
|
163
|
+
# Parse and extend template's front-matter with content front-matter
|
164
|
+
update_attributes(get_front_matter(content))
|
165
|
+
# Add props
|
166
|
+
update_attributes(@props)
|
167
|
+
# Update the template's store data
|
168
|
+
template_store_data(@attributes)
|
169
|
+
|
170
|
+
# Setting context's template attributes from @attributes
|
171
|
+
# This allows for @attributes to be used within the template as
|
172
|
+
# {{ template.atttribute_name }}
|
173
|
+
if @attributes.length
|
174
|
+
@attributes.each do |key, value|
|
175
|
+
val = @context.evaluate(value)
|
176
|
+
@context[CONTEXT_NAME][key] = val
|
177
|
+
|
178
|
+
# Adjust sanitize if parse: html
|
179
|
+
if (key == "parse") && (val == "html")
|
180
|
+
@sanitize = true
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# puts @attributes
|
186
|
+
@context[CONTEXT_NAME]["content"] = sanitize(strip_front_matter(content))
|
187
|
+
store_template_data()
|
188
|
+
content = @compressor.compress(template.render(@context))
|
189
|
+
reset_template_data()
|
190
|
+
|
191
|
+
content
|
192
|
+
end
|
193
|
+
|
194
|
+
# update_attributes(data = Hash)
|
195
|
+
# Description: Merges data with @attributes.
|
196
|
+
def update_attributes(data)
|
197
|
+
if data
|
198
|
+
@attributes.merge!(data)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# store_template_data()
|
203
|
+
# Description: Works with reset_template_data. This is a work-around
|
204
|
+
# to ensure data stays in scope and isn't leaked from child->parent
|
205
|
+
# template.
|
206
|
+
def store_template_data()
|
207
|
+
@context.registers[CONTEXT_DATA_NAME] ||= {}
|
208
|
+
unless @context.registers[CONTEXT_DATA_NAME].key?(@id)
|
209
|
+
@context.registers[CONTEXT_DATA_NAME][@id] = @context[CONTEXT_NAME]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# reset_template_data()
|
214
|
+
# Description: Works with store_template_data. This is a work-around
|
215
|
+
# to ensure data stays in scope and isn't leaked from child->parent
|
216
|
+
# template.
|
217
|
+
def reset_template_data()
|
218
|
+
@context.registers[CONTEXT_DATA_NAME] ||= {}
|
219
|
+
store = @context.registers[CONTEXT_DATA_NAME]
|
220
|
+
if store.keys.length
|
221
|
+
if store.keys[0] == @id
|
222
|
+
# Resets template data
|
223
|
+
@context.registers[CONTEXT_DATA_NAME] = false
|
224
|
+
@context.registers[CONTEXT_SCOPE_NAME] = false
|
225
|
+
else
|
226
|
+
@context[CONTEXT_NAME] = store[store.keys[0]]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# add_template_to_dependency(path = String)
|
232
|
+
# source: https://github.com/jekyll/jekyll/blob/e509cf2139d1a7ee11090b09721344608ecf48f6/lib/jekyll/tags/include.rb
|
233
|
+
def add_template_to_dependency(path)
|
234
|
+
if @context.registers[:page] && @context.registers[:page].key?("path")
|
235
|
+
@site.regenerator.add_dependency(
|
236
|
+
@site.in_source_dir(@context.registers[:page]["path"]),
|
237
|
+
template_path(path)
|
238
|
+
)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# load_cached_template(path = String)
|
243
|
+
# source: https://github.com/jekyll/jekyll/blob/e509cf2139d1a7ee11090b09721344608ecf48f6/lib/jekyll/tags/include.rb
|
244
|
+
# Returns: Liquid template from Jekyll's cache.
|
245
|
+
def load_cached_template(path)
|
246
|
+
@context.registers[CONTEXT_CACHE_NAME] ||= {}
|
247
|
+
cached_templates = @context.registers[CONTEXT_CACHE_NAME]
|
248
|
+
|
249
|
+
unless cached_templates.key?(path)
|
250
|
+
cached_templates[path] = load_template()
|
251
|
+
end
|
252
|
+
template = cached_templates[path]
|
253
|
+
|
254
|
+
update_attributes(template["data"])
|
255
|
+
template["template"]
|
256
|
+
end
|
257
|
+
|
258
|
+
# template_path(path = String)
|
259
|
+
# Returns: A full file path of the template
|
260
|
+
def template_path(path)
|
261
|
+
File.join(@site.source.to_s, TEMPLATE_DIR, path.to_s)
|
262
|
+
end
|
263
|
+
|
264
|
+
# template_content(template_name = String)
|
265
|
+
# Description: Opens, reads, and returns template content as string.
|
266
|
+
# Returns: Template content
|
267
|
+
def template_content(template_name)
|
268
|
+
File.read(template_path(template_name).strip)
|
269
|
+
end
|
270
|
+
|
271
|
+
# load_template()
|
272
|
+
# Description: Extends Liquid's default load_template method. Also provides
|
273
|
+
# extra enhancements:
|
274
|
+
# - parses and sets template front-matter content
|
275
|
+
# Returns: Template class
|
276
|
+
def load_template()
|
277
|
+
file = @site
|
278
|
+
.liquid_renderer
|
279
|
+
.file(template_path(@template_name))
|
280
|
+
|
281
|
+
content = template_content(@template_name)
|
282
|
+
|
283
|
+
template = Hash.new
|
284
|
+
data = get_front_matter(content)
|
285
|
+
markup = strip_front_matter(content)
|
286
|
+
|
287
|
+
if content
|
288
|
+
template["data"] = data
|
289
|
+
template["template"] = file.parse(markup)
|
290
|
+
template
|
291
|
+
else
|
292
|
+
raise Liquid::SyntaxError, "Could not find #{file_path} in your templates"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# sanitize(content = String)
|
297
|
+
# Description: Renders the content as markdown or HTML based on the
|
298
|
+
# "parse" attribute.
|
299
|
+
# Returns: Content (string).
|
300
|
+
def sanitize(content)
|
301
|
+
unless @sanitize
|
302
|
+
converter = @site.find_converter_instance(::Jekyll::Converters::Markdown)
|
303
|
+
converter.convert(unindent(content))
|
304
|
+
else
|
305
|
+
unindent(content)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# unindent(content = String)
|
310
|
+
# Description: Removes initial indentation.
|
311
|
+
# Returns: Content (string).
|
312
|
+
def unindent(content)
|
313
|
+
# Remove initial whitespace
|
314
|
+
content.gsub!(/\A^\s*\n/, "")
|
315
|
+
# Remove indentations
|
316
|
+
if content =~ WHITESPACE_REGEXP
|
317
|
+
indentation = Regexp.last_match(0).length
|
318
|
+
content.gsub!(/^\ {#{indentation}}/, "")
|
319
|
+
end
|
320
|
+
content
|
321
|
+
end
|
322
|
+
|
323
|
+
# get_front_matter(content = String)
|
324
|
+
# Returns: A hash of data parsed from the content's YAML
|
325
|
+
def get_front_matter(content)
|
326
|
+
# Strip leading white-spaces
|
327
|
+
content = unindent(content)
|
328
|
+
if content =~ YAML_FRONT_MATTER_REGEXP
|
329
|
+
front_matter = Regexp.last_match(0)
|
330
|
+
values = SafeYAML.load(front_matter)
|
331
|
+
else
|
332
|
+
Hash.new
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# strip_front_matter(content = String)
|
337
|
+
# Description: Removes the YAML front-matter content.
|
338
|
+
# Returns: Template content, with front-matter removed.
|
339
|
+
def strip_front_matter(content)
|
340
|
+
# Strip leading white-spaces
|
341
|
+
content = unindent(content)
|
342
|
+
if content =~ YAML_FRONT_MATTER_REGEXP
|
343
|
+
front_matter = Regexp.last_match(0)
|
344
|
+
# Returns content with stripped front-matter
|
345
|
+
content.gsub!(front_matter, "")
|
346
|
+
end
|
347
|
+
content
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
Liquid::Template.register_tag("template", Jekyll::Tags::TemplateBlock)
|
metadata
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-jolt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.21.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ItsJonQ
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jekyll
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: htmlcompressor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.3.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.13'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.13'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-reporters
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest-profile
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.8'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5.8'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec-mocks
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: shoulda
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: kramdown
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description:
|
154
|
+
email:
|
155
|
+
- itsjonq@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gitignore"
|
161
|
+
- ".rspec"
|
162
|
+
- ".travis.yml"
|
163
|
+
- Gemfile
|
164
|
+
- LICENSE.txt
|
165
|
+
- README.md
|
166
|
+
- Rakefile
|
167
|
+
- bin/console
|
168
|
+
- bin/setup
|
169
|
+
- jekyll-jolt.gemspec
|
170
|
+
- lib/jekyll-jolt.rb
|
171
|
+
- lib/jekyll/jolt.rb
|
172
|
+
- lib/jekyll/jolt/version.rb
|
173
|
+
homepage: https://github.com/helpscout/jekyll-jolt
|
174
|
+
licenses:
|
175
|
+
- MIT
|
176
|
+
metadata: {}
|
177
|
+
post_install_message:
|
178
|
+
rdoc_options: []
|
179
|
+
require_paths:
|
180
|
+
- lib
|
181
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - ">="
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
191
|
+
requirements: []
|
192
|
+
rubyforge_project:
|
193
|
+
rubygems_version: 2.5.2
|
194
|
+
signing_key:
|
195
|
+
specification_version: 4
|
196
|
+
summary: Jekyll library for creating custom template blocks
|
197
|
+
test_files: []
|