jekyll-conrefifier 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -0
- data/lib/jekyll-conrefifier.rb +83 -50
- data/lib/version.rb +1 -1
- data/spec/conrefifier_spec.rb +14 -3
- data/spec/fixtures/_config.yml +5 -0
- data/spec/fixtures/_data/categories.yml +1 -1
- data/spec/fixtures/_data/conrefs.yml +2 -1
- data/spec/fixtures/_data/enterprise_filtered_categories.yml +1 -1
- data/spec/fixtures/_data/filtered_categories.yml +1 -1
- data/spec/fixtures/_layouts/filtering_layout.html +20 -0
- data/spec/fixtures/filtering_layout.html +5 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db0d778b5e1e0ab68919ef23d08c1f1715304823
|
4
|
+
data.tar.gz: 28a2c9ccdf9de238f5ed558f1ae4d079b46699a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca4756a3697919d534c876cf379bfd7e025e261674884ebc18a37b672166684f7bb136ad9400b7c7bc598fe2dd02f5763b10b8f37df6e5aa652026adb1de8805
|
7
|
+
data.tar.gz: 7855026b72a8fff240054bc38842080b04d37bc9a9554247e02ffab0e88763051944fabc649b312c1ed83a37055dce25cc7dbe79f76c5bad12f68b2e5071ab9a
|
data/README.md
CHANGED
@@ -114,3 +114,30 @@ data_file_variables:
|
|
114
114
|
```
|
115
115
|
|
116
116
|
In this case, every data file has a `page.version` of `2.0`. However, only data files prefixed with `ent`, containing one or more word characters (`\w+`), and followed by an underscore (`_`), have a value of `2.1`.
|
117
|
+
|
118
|
+
## Rendering filtered data files in layouts
|
119
|
+
|
120
|
+
As an addition to the above, a new tag, `data_render`, can be used to iterate over filtered data files.
|
121
|
+
|
122
|
+
You can call this filter by:
|
123
|
+
|
124
|
+
* Passing a data file name to `data_render`
|
125
|
+
* Passing any optional variables to this filter
|
126
|
+
* The YAML information will be temporarily stored within `site.data.data_render`
|
127
|
+
* You can iterate over `site.data.data_render` to walk along the data
|
128
|
+
* Multiple calls to `data_render` rewrite to `site.data.data_render`
|
129
|
+
|
130
|
+
Here's an example:
|
131
|
+
|
132
|
+
``` liquid
|
133
|
+
{% data_render site.data.filtered_categories(:version => 2.0) %}
|
134
|
+
|
135
|
+
{% for category_hash in site.data.data_render %}
|
136
|
+
{% assign category_title = category_hash[0] %}
|
137
|
+
{% assign category_articles = category_hash[1] %}
|
138
|
+
{{ category_title }}
|
139
|
+
{{ category_articles }}
|
140
|
+
{% endfor %}
|
141
|
+
```
|
142
|
+
|
143
|
+
Note that data files are read *once*, to improve performance. The variables passed in are evaluated for each call.
|
data/lib/jekyll-conrefifier.rb
CHANGED
@@ -1,16 +1,3 @@
|
|
1
|
-
class Hash
|
2
|
-
def insert_before(key, kvpair)
|
3
|
-
arr = to_a
|
4
|
-
pos = arr.index(arr.assoc(key))
|
5
|
-
if pos
|
6
|
-
arr.insert(pos, kvpair)
|
7
|
-
else
|
8
|
-
arr << kvpair
|
9
|
-
end
|
10
|
-
replace Hash[arr]
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
1
|
module Jekyll
|
15
2
|
class Document
|
16
3
|
alias_method :old_read, :read
|
@@ -32,7 +19,6 @@ module Jekyll
|
|
32
19
|
|
33
20
|
class Site
|
34
21
|
alias_method :old_read, :read
|
35
|
-
alias_method :old_read_data_to, :read_data_to
|
36
22
|
|
37
23
|
def in_source_dir(*paths)
|
38
24
|
paths.reduce(source) do |base, path|
|
@@ -40,7 +26,7 @@ module Jekyll
|
|
40
26
|
end
|
41
27
|
end
|
42
28
|
|
43
|
-
# allows us to filter data file
|
29
|
+
# allows us to filter data file contents via conditionals, eg. `{% if page.version == ... %}`
|
44
30
|
def read_data_to(dir, data)
|
45
31
|
return unless File.directory?(dir) && (!safe || !File.symlink?(dir))
|
46
32
|
|
@@ -48,8 +34,9 @@ module Jekyll
|
|
48
34
|
Dir['*.{yaml,yml,json,csv}'] + Dir['*'].select { |fn| File.directory?(fn) }
|
49
35
|
end
|
50
36
|
|
37
|
+
# all of this is copied from the Jekyll source, except...
|
51
38
|
entries.each do |entry|
|
52
|
-
path = in_source_dir(dir, entry)
|
39
|
+
path = self.in_source_dir(dir, entry)
|
53
40
|
next if File.symlink?(path) && safe
|
54
41
|
|
55
42
|
key = sanitize_filename(File.basename(entry, '.*'))
|
@@ -60,61 +47,107 @@ module Jekyll
|
|
60
47
|
when '.csv'
|
61
48
|
data[key] = CSV.read(path, :headers => true).map(&:to_hash)
|
62
49
|
else
|
50
|
+
# if we hit upon if/unless conditionals, we'll need to pause and render them
|
63
51
|
contents = File.read(path)
|
64
52
|
if (matches = contents.scan /(\{% (?:if|unless).+? %\}.*?\{% end(?:if|unless) %\})/m)
|
65
|
-
unless
|
66
|
-
contents =
|
53
|
+
unless data_file_variables(path).nil?
|
54
|
+
contents = contents.gsub(/\{\{/, '[[')
|
55
|
+
contents = apply_vars_to_datafile(contents, matches, path)
|
67
56
|
end
|
68
57
|
end
|
69
58
|
data[key] = SafeYAML.load(contents)
|
70
59
|
end
|
71
60
|
end
|
72
61
|
end
|
62
|
+
|
63
|
+
# once we're all done, we need to iterate once more to parse out `{{ }}` blocks.
|
64
|
+
# two reasons for this: one, we need to collect every data file before attempting to
|
65
|
+
# parse these vars; two, the Liquid parse above obliterates these tags, so we
|
66
|
+
# first need to convert them into `[[ }}`, and *then* continue with the parse
|
67
|
+
data.each_pair do |datafile, value|
|
68
|
+
yaml_dump = YAML::dump value
|
69
|
+
yaml_dump = yaml_dump.gsub(/\[\[/, '{{')
|
70
|
+
|
71
|
+
data[datafile] = SafeYAML.load transform_liquid_variables(yaml_dump, datafile)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# apply the custom scoope plus the rest of the `site.data` information
|
76
|
+
def apply_vars_to_datafile(contents, matches, path)
|
77
|
+
return contents if matches.empty?
|
78
|
+
|
79
|
+
data_vars = path.nil? ? {} : data_file_variables(path)
|
80
|
+
|
81
|
+
config = { 'page' => data_vars }
|
82
|
+
config = { 'site' => { 'data' => self.data } }.merge(config)
|
83
|
+
|
84
|
+
matches.each do |match|
|
85
|
+
contents = contents.sub(match.first, Liquid::Template.parse(match.first).render(config))
|
86
|
+
end
|
87
|
+
|
88
|
+
contents
|
73
89
|
end
|
74
90
|
|
75
|
-
|
76
|
-
|
91
|
+
# fetch the custom scope vars, as defined in _config.yml
|
92
|
+
def data_file_variables(path)
|
77
93
|
data_vars = {}
|
78
|
-
scopes = data_file_variables.select { |v| v['scope']['path'].empty? || Regexp.new(v['scope']['path']) =~ path }
|
94
|
+
scopes = config['data_file_variables'].select { |v| v['scope']['path'].empty? || Regexp.new(v['scope']['path']) =~ path }
|
79
95
|
scopes.each do |scope|
|
80
96
|
data_vars = data_vars.merge(scope['values'])
|
81
97
|
end
|
82
|
-
temp_config = self.config.merge({ 'page' => data_vars })
|
83
|
-
matches.each do |match|
|
84
|
-
contents = contents.sub(match.first, Liquid::Template.parse(match.first).render(temp_config))
|
85
|
-
end
|
86
98
|
|
87
|
-
|
99
|
+
data_vars
|
88
100
|
end
|
89
101
|
|
90
102
|
# allow us to use any variable within Jekyll data files; for example:
|
91
103
|
# - '{{ site.data.conrefs.product_name[site.audience] }} Glossary'
|
92
104
|
# renders as "GitHub Glossary" for dotcom, but "GitHub Enterprise Glossary" for Enterprise
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
data.each_pair do |data_file, data_set|
|
97
|
-
if data_set.is_a? Hash
|
98
|
-
data_set.each_pair do |key, values|
|
99
|
-
if key =~ /\{\{.+?\}\}/
|
100
|
-
new_key = Liquid::Template.parse(key).render({ "site" => { "data" => data }.merge(config) })
|
101
|
-
keys_to_modify[key] = new_key
|
102
|
-
end
|
103
|
-
if values.is_a? Array
|
104
|
-
values.each_with_index do |value, i|
|
105
|
-
if value =~ /\{\{.+?\}\}/
|
106
|
-
value = Liquid::Template.parse(value).render({ "site" => { "data" => data }.merge(config) })
|
107
|
-
data[data_file][key][i] = value
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
keys_to_modify.each_pair do |old_key, new_key|
|
113
|
-
data[data_file].insert_before(old_key, [new_key, data[data_file][old_key]])
|
114
|
-
data[data_file].delete(old_key)
|
115
|
-
end
|
116
|
-
end
|
105
|
+
def transform_liquid_variables(contents, path=nil)
|
106
|
+
if (matches = contents.scan /(\{\{.+?\}\})/)
|
107
|
+
contents = apply_vars_to_datafile(contents, matches, path)
|
117
108
|
end
|
109
|
+
|
110
|
+
contents
|
118
111
|
end
|
119
112
|
end
|
113
|
+
|
114
|
+
class DataRenderTag < Liquid::Tag
|
115
|
+
def initialize(tag_name, text, tokens)
|
116
|
+
super
|
117
|
+
|
118
|
+
keys = text.strip.split('.', 3)
|
119
|
+
keys.shift(2) # this is just site.data
|
120
|
+
paren_arg = keys.last.match(/\((.+?)\)/)
|
121
|
+
unless paren_arg.nil?
|
122
|
+
last_key = keys.last.sub(paren_arg[0], '')
|
123
|
+
keys.pop
|
124
|
+
keys << last_key
|
125
|
+
@hash_args = paren_arg[1].gsub(/[{}:]/,'').split(', ').map{|h| h1,h2 = h.split('=>'); {h1.strip => h2.strip}}.reduce(:merge)
|
126
|
+
end
|
127
|
+
@keys = keys
|
128
|
+
@id = keys.join('-')
|
129
|
+
end
|
130
|
+
|
131
|
+
def fetch_datafile(context, keys)
|
132
|
+
data_file = context.registers[:site].data["data_render_#{@id}"]
|
133
|
+
return data_file unless data_file.nil?
|
134
|
+
|
135
|
+
path = @id.sub('.', '/')
|
136
|
+
data_source = File.join(context.registers[:site].source, context.registers[:site].config['data_source'])
|
137
|
+
data_file = File.read("#{data_source}/#{path}.yml")
|
138
|
+
context.registers[:site].data["data_render_#{@id}"] = data_file
|
139
|
+
end
|
140
|
+
|
141
|
+
def render(context)
|
142
|
+
datafile = fetch_datafile(context, @keys)
|
143
|
+
|
144
|
+
config = { 'page' => @hash_args }
|
145
|
+
config = { 'site' => { "data" => context.registers[:site].data } }.merge(config)
|
146
|
+
versioned_yaml = SafeYAML.load(Liquid::Template.parse(datafile).render(config))
|
147
|
+
context.registers[:site].data['data_render'] = versioned_yaml
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
Liquid::Template.register_tag('data_render', Jekyll::DataRenderTag)
|
120
153
|
end
|
data/lib/version.rb
CHANGED
data/spec/conrefifier_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe("Conrefifier") do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "writes the proper content for values after fetching info from a data file" do
|
13
|
-
index_file = @dest.join(
|
13
|
+
index_file = @dest.join('index.html')
|
14
14
|
expect(index_file).to exist
|
15
15
|
index_contents = File.read(index_file)
|
16
16
|
expect(index_contents).to include("GitHub Glossary")
|
@@ -34,7 +34,7 @@ describe("Conrefifier") do
|
|
34
34
|
filtered_index_file = @dest.join("filtered_index.html")
|
35
35
|
expect(filtered_index_file).to exist
|
36
36
|
filtered_index_contents = File.read(filtered_index_file)
|
37
|
-
expect(filtered_index_contents).to include("GitHub Glossary")
|
37
|
+
expect(filtered_index_contents).to include("GitHub Enterprise Glossary")
|
38
38
|
expect(filtered_index_contents).to include("Fork A Repo")
|
39
39
|
expect(filtered_index_contents).to include("Article v2.0")
|
40
40
|
expect(filtered_index_contents).to include("Still show")
|
@@ -46,11 +46,22 @@ describe("Conrefifier") do
|
|
46
46
|
enterprise_filtered_index = @dest.join("enterprise_filtered_index.html")
|
47
47
|
expect(enterprise_filtered_index).to exist
|
48
48
|
filtered_index_contents = File.read(enterprise_filtered_index)
|
49
|
-
expect(filtered_index_contents).to include("GitHub Glossary")
|
49
|
+
expect(filtered_index_contents).to include("GitHub Enterprise Glossary")
|
50
50
|
expect(filtered_index_contents).to include("Fork A Repo")
|
51
51
|
expect(filtered_index_contents).to include("Article v2.1")
|
52
52
|
expect(filtered_index_contents).to include("Still show")
|
53
53
|
expect(filtered_index_contents).to_not include("Article v2.0")
|
54
54
|
expect(filtered_index_contents).to_not include("Ignored")
|
55
55
|
end
|
56
|
+
|
57
|
+
it 'uses the data_render tag to provide filtered data in a layout' do
|
58
|
+
filtering_layout = @dest.join("filtering_layout.html")
|
59
|
+
expect(filtering_layout).to exist
|
60
|
+
filtering_layout_contents = File.read(filtering_layout)
|
61
|
+
expect(filtering_layout_contents).to include('GitHub Enterprise Glossary')
|
62
|
+
expect(filtering_layout_contents.scan(/Bootcamp/).count).to eq(2)
|
63
|
+
expect(filtering_layout_contents.scan(/Article v2.1/).count).to eq(1)
|
64
|
+
expect(filtering_layout_contents.scan(/Article v2.0/).count).to eq(1)
|
65
|
+
expect(filtering_layout_contents.scan(/Ignored/).count).to eq(1)
|
66
|
+
end
|
56
67
|
end
|
data/spec/fixtures/_config.yml
CHANGED
@@ -3,7 +3,7 @@ Bootcamp:
|
|
3
3
|
- Create A Repo
|
4
4
|
- Fork A Repo
|
5
5
|
- Be Social
|
6
|
-
- '{{ site.data.conrefs.product_name[
|
6
|
+
- '{{ site.data.conrefs.product_name[page.version] }} Glossary'
|
7
7
|
- Good Resources for Learning Git and GitHub
|
8
8
|
|
9
9
|
'{{ site.data.conrefs.product_type }}':
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
{% data_render site.data.filtered_categories(:version => 2.0) %}
|
3
|
+
|
4
|
+
{% for category_hash in site.data.data_render %}
|
5
|
+
{% assign category_title = category_hash[0] %}
|
6
|
+
{% assign category_articles = category_hash[1] %}
|
7
|
+
{{ category_title }}
|
8
|
+
{{ category_articles }}
|
9
|
+
{% endfor %}
|
10
|
+
|
11
|
+
{{ content }}
|
12
|
+
|
13
|
+
{% data_render site.data.filtered_categories(:version => 2.1) %}
|
14
|
+
|
15
|
+
{% for category_hash in site.data.data_render %}
|
16
|
+
{% assign category_title = category_hash[0] %}
|
17
|
+
{% assign category_articles = category_hash[1] %}
|
18
|
+
{{ category_title }}
|
19
|
+
{{ category_articles }}
|
20
|
+
{% endfor %}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-conrefifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garen J. Torikian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -80,8 +80,10 @@ files:
|
|
80
80
|
- spec/fixtures/_data/enterprise_filtered_categories.yml
|
81
81
|
- spec/fixtures/_data/filtered_categories.yml
|
82
82
|
- spec/fixtures/_layouts/article.html
|
83
|
+
- spec/fixtures/_layouts/filtering_layout.html
|
83
84
|
- spec/fixtures/enterprise_filtered_index.html
|
84
85
|
- spec/fixtures/filtered_index.html
|
86
|
+
- spec/fixtures/filtering_layout.html
|
85
87
|
- spec/fixtures/index.html
|
86
88
|
- spec/spec_helper.rb
|
87
89
|
homepage: ''
|