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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 065d8f8c53f11bc9a9e5a8657fba8844228da1d1
4
- data.tar.gz: 5cd34e692c71e470491b88c5ed4629fff3ad0e6a
3
+ metadata.gz: db0d778b5e1e0ab68919ef23d08c1f1715304823
4
+ data.tar.gz: 28a2c9ccdf9de238f5ed558f1ae4d079b46699a6
5
5
  SHA512:
6
- metadata.gz: b67b2493701b2b63cd47bf639837dfe6435df9707b12062fd56ad39c9a9ec24b3c38e668520e070fc71742821e4d4429722cbe012f96080f3994d5dd1c74f221
7
- data.tar.gz: ef625b18abef60fae8b637c7c9b492dc813faba80c3b2bdf0d0413758b14a80e17b3636c3ed94b51bb0333d2670878b037f56cca5aefd968b0e49e1d838ad9c4
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.
@@ -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 content out on conditionals, eg. `{% if page.version == ... %}`
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 matches.empty?
66
- contents = apply_vars_to_datafile(contents, path, matches, config['data_file_variables'])
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
- def apply_vars_to_datafile(contents, path, matches, data_file_variables)
76
- return contents if data_file_variables.nil?
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
- contents
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 read
94
- keys_to_modify = {}
95
- old_read
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
@@ -1,3 +1,3 @@
1
1
  module JekyllConrefifier
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -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("index.html")
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
@@ -22,6 +22,11 @@ data_file_variables:
22
22
  path: ""
23
23
  values:
24
24
  version: "2.0"
25
+ -
26
+ scope:
27
+ path: "^categories"
28
+ values:
29
+ version: "dotcom"
25
30
  -
26
31
  scope:
27
32
  path: "ent\\w+_"
@@ -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[site.audience] }} Glossary'
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 }}':
@@ -1,6 +1,7 @@
1
1
  product_name:
2
2
  dotcom: GitHub
3
- 2.0: GitHub Enterprise
3
+ '2.0': GitHub Enterprise
4
+ '2.1': GitHub Enterprise
4
5
  11.10.340: GitHub Enterprise
5
6
 
6
7
  product_type: 'Amazing'
@@ -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[site.audience] }} Glossary'
6
+ - '{{ site.data.conrefs.product_name[page.version] }} Glossary'
7
7
  - Good Resources for Learning Git and GitHub
8
8
 
9
9
  Listing:
@@ -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[site.audience] }} Glossary'
6
+ - '{{ site.data.conrefs.product_name[page.version] }} Glossary'
7
7
  - Good Resources for Learning Git and GitHub
8
8
 
9
9
  Listing:
@@ -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 %}
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: filtering_layout
3
+ ---
4
+
5
+ test
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.2.1
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-02 00:00:00.000000000 Z
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: ''