jekyll-conrefifier 0.2.1 → 0.3.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 +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: ''
|