nanoc-conref-fs 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35dc702fdbe8ffa00711be829afcf827fe5565fe
4
- data.tar.gz: 83767a5ade9f4945c99f25d3a03122e1ff3467e7
3
+ metadata.gz: fdb225742e914ae1ac3f39c539c290a2c91aabf0
4
+ data.tar.gz: 694937b4c238491409411370271cc9d5d061c0c3
5
5
  SHA512:
6
- metadata.gz: bf4dd287a13d192f38777a6dc31211976ba3e6398ce7b9f53a06769740086dc706217788e05b1a954c35425863b75a41bea4937eaaa801eef7a2c87487b56289
7
- data.tar.gz: 37c643e5e0b2ac33cb40aa87025146d3549aad0d48f7215ce4cbb5f41aa79a65f2580104e4ae78fd7a54343fe5c466b1a6eb70a657e10d83b0c6b98256d69d62
6
+ metadata.gz: 9edf0b62eb28ea4fb128303e7cb442f79b32916b6b562c08f784e09b3d4396e16043a9c96d43837f4b341d4be3a62668168c4a0335c75d42b572318040e34e27
7
+ data.tar.gz: f6cbdd94a675dadc4b3dc2b91704909b415f91c718baf57a85e10e8581d665b32aa93e7f174d5bef783c41b98f4a38649cce52ed3b4a463515f9f69d629c81a2
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # nanoc-conref-fs
2
2
 
3
- This gem adds a new Filesystem type called `ConrefFS` to nanoc.
3
+ This gem adds a new Filesystem type to Nanoc called `ConrefFS`. This filesystem permits you to use reusable content and Liquid variables in your content to generate multiple outputs from a single source. It makes heavy use of item representations (or `rep`s for short).
4
4
 
5
- The idea is that you have a set of YAML files in a data folder which act as your reusables. You can apply thse reusables throughout your content and layout.
5
+ The idea is that you have a set of YAML files in a data folder which act as your reusables. You can apply these reusables throughout your content.
6
6
 
7
7
  [![Build Status](https://travis-ci.org/gjtorikian/nanoc-conref-fs.svg)](https://travis-ci.org/gjtorikian/nanoc-conref-fs)
8
8
 
9
- Set the data source in your *nanoc.yaml* file:
9
+ To get started, set the data source in your *nanoc.yaml* file:
10
10
 
11
11
  ``` yml
12
12
  data_sources:
@@ -14,7 +14,18 @@ data_sources:
14
14
  type: conref-fs
15
15
  ```
16
16
 
17
- **NOTE:** If you use this library with nanoc's ERB filter, and want to use `render`, you'll need to monkey-patch an alias to avoid conflicts:
17
+ You'll probably also want to provide a list of `rep`s which define all the item reps available to your site. For example:
18
+
19
+ ``` yml
20
+ data_sources:
21
+ -
22
+ type: conref-fs
23
+ reps:
24
+ - :default
25
+ - :X
26
+ ```
27
+
28
+ **NOTE:** If you use this library with Nanoc's ERB filter, and want to use `render`, you'll need to monkey-patch an alias to avoid conflicts with Liquid:
18
29
 
19
30
  ``` ruby
20
31
  require 'nanoc-conref-fs'
@@ -27,64 +38,100 @@ Nanoc::Helpers::Rendering.module_eval do
27
38
  end
28
39
  ```
29
40
 
30
- Then, use `renderp` instead of `render`.
41
+ Then, you can use `renderp` just as you would with `render`.
31
42
 
32
43
  ## Usage
33
44
 
34
- Nearly all the usage of this gem relies on a *data* folder, sibling to your *content* and *layouts* folders. See [the test fixture](test/fixtures/data) for an example.
35
-
36
- You'll also need some relevant keys added to your *nanoc.yaml* file:
37
-
38
- * The `data_variables` key applies additional/dynamic values to your data files, based on their path. For example, the following `data_variables` configuration adds a `version` attribute to every data file, whose value is `dotcom`:
39
-
40
- ``` yaml
41
- data_variables:
42
- -
43
- scope:
44
- path: ""
45
- values:
46
- version: "dotcom"
47
- ```
48
-
49
- You could add to this key to indicate that any data file called *changed* instead has a version of `something_different`:
50
-
51
- ``` yaml
52
- data_variables:
53
- -
54
- scope:
55
- path: ""
56
- values:
57
- version: "dotcom"
58
- -
59
- scope:
60
- path: "changed"
61
- values:
62
- version: "2.0"
63
- ```
64
-
65
- * Similarly, the `page_variables` also use `scope`s and `value`s to determine variables:
66
-
67
- ``` yaml
68
- page_variables:
69
- -
70
- scope:
71
- path: ""
72
- values:
73
- version: "dotcom"
74
- -
75
- scope:
76
- path: "different"
77
- values:
78
- version: "2.0"
79
- ```
80
-
81
- In this case, every file path will get a `version` of `dotcom`, but any file matching `different` will get a version of 2.0.
45
+ Nearly all the usage of this gem relies on a *data* folder, sibling to your *content* and *layouts* folders. See [the test fixture](test/fixtures/data) for an example. You can change this with the `data_dir` config option:
46
+
47
+ ``` yml
48
+ data_sources:
49
+ -
50
+ type: conref-fs
51
+ data_dir: 'somewhere_else'
52
+ reps:
53
+ - :default
54
+ - :X
55
+ ```
56
+
57
+ Then, you can [construct a data folder filled with YAML files](https://github.com/gjtorikian/nanoc-conref-fs/tree/master/test/fixtures/data). These act as the source of your reusable content.
58
+
59
+ Finally, you'll need some relevant keys added to your *nanoc.yaml* file.
60
+
61
+ ### Data folder variables
62
+
63
+ The `data_variables` key applies additional/dynamic values to your data files, based on their path. For example, the following `data_variables` configuration adds a `version` attribute to every data file, whose value is `dotcom`:
64
+
65
+ ``` yaml
66
+ data_variables:
67
+ -
68
+ scope:
69
+ path: ""
70
+ values:
71
+ version: "dotcom"
72
+ ```
73
+
74
+ You could add to this key to indicate that any data file called *changed* instead has a version of `something_different`:
75
+
76
+ ``` yaml
77
+ data_variables:
78
+ -
79
+ scope:
80
+ path: ""
81
+ values:
82
+ version: "dotcom"
83
+ -
84
+ scope:
85
+ path: "changed"
86
+ values:
87
+ version: "2.0"
88
+ ```
89
+
90
+ In addition to `path`, you can provide an array of `reps` to define which `reps` should receive which version:
91
+
92
+ ``` yaml
93
+ data_variables:
94
+ -
95
+ scope:
96
+ path: "feature"
97
+ values:
98
+ version: "dotcom"
99
+ -
100
+ scope:
101
+ path: "feature"
102
+ reps:
103
+ - :X
104
+ values:
105
+ version: "something_else"
106
+ ```
107
+
108
+ In this example, any data folder with a path containing "feature" will have `page.version` equal to `dotcom`. However, if you're constructing for the `:X` item representation, `page.version` becomes `something_else`.
109
+
110
+ ### Page variables
111
+
112
+ Similarly, the `page_variables` also use `scope`s, `rep`s, and `value`s to determine variables:
113
+
114
+ ``` yaml
115
+ page_variables:
116
+ -
117
+ scope:
118
+ path: ""
119
+ values:
120
+ version: "dotcom"
121
+ -
122
+ scope:
123
+ path: "different"
124
+ values:
125
+ version: "2.0"
126
+ ```
127
+
128
+ In this case, every file path will get a `version` of `dotcom`, but any file matching `different` will get a version of 2.0.
82
129
 
83
130
  See the tests for further usage of these conditionals. In both cases, `path` is converted into a Ruby regular expression before being matched against a filename.
84
131
 
85
132
  ### Associating files with data
86
133
 
87
- If you have a special `data_association` value, additional metadata to items will be applied:
134
+ If you have a special `data_association` value in your `scope`, additional metadata to items will be applied:
88
135
 
89
136
  * An attribute called `:parents`, which adds the parent "map topic" to an item.
90
137
  * An attribute called `:children`, which adds any children of a "map topic."
@@ -96,3 +143,25 @@ You can retrieve the stored data at any time (for example, in a layout) by calli
96
143
  ### Retrieving data files
97
144
 
98
145
  You can fetch anything in the *data* folder by passing in a string, demarcated with `.`s, to `VariableMixin.fetch_data_file`. For example, `VariableMixin.fetch_data_file('reusables.intro')` will fetch the file in *data/reusables/intro.yml*.
146
+
147
+ ### Ignoring content
148
+
149
+ You can use the `create_ignore_rules` method to construct ignore rules for your content. For example, say you have a category file that looks like this:
150
+
151
+ ``` yaml
152
+ Something:
153
+ - Blah1
154
+ {% if page.version == 'dotcom' %}
155
+ - Blah2
156
+ {% endif %}
157
+ ```
158
+
159
+ By default, Nanoc will try to compile and layout a page for `Blah2` for every item rep, even though it probably shouldn't.
160
+
161
+ You can use `create_ignore_rules`, passing in an item rep and a category file to generate ignore rules. For example:
162
+
163
+ ``` ruby
164
+ ConrefFS.create_ignore_rules(:X, 'categories.category').each do |f|
165
+ ignore f, rep: :X
166
+ end
167
+ ```
@@ -0,0 +1,98 @@
1
+ module NanocConrefFS
2
+ module Ancestry
3
+ def create_parents(toc, meta)
4
+ if toc.is_a?(Array)
5
+ find_array_parents(toc, meta[:title])
6
+ elsif toc.is_a?(Hash)
7
+ find_hash_parents(toc, meta[:title])
8
+ end
9
+ end
10
+ module_function :create_parents
11
+
12
+ def create_children(toc, meta)
13
+ if toc.is_a?(Array)
14
+ find_array_children(toc, meta[:title])
15
+ elsif toc.is_a?(Hash)
16
+ find_hash_children(toc, meta[:title])
17
+ end
18
+ end
19
+ module_function :create_children
20
+
21
+ # Given a category file that's an array, this method finds
22
+ # the parent of an item
23
+ def find_array_parents(toc, title)
24
+ parents = ''
25
+ toc.each do |item|
26
+ if item.is_a?(Hash)
27
+ parents = find_hash_parents(item, title)
28
+ break unless parents.empty?
29
+ end
30
+ end
31
+ parents
32
+ end
33
+ module_function :find_array_parents
34
+
35
+ # Given a category file that's a hash, this method finds
36
+ # the parent of an item
37
+ def find_hash_parents(toc, title)
38
+ parents = ''
39
+ toc.each_key do |key|
40
+ toc[key].each do |item|
41
+ if item.is_a?(Hash)
42
+ if item.keys.include?(title)
43
+ parents = key
44
+ break
45
+ else
46
+ if item[item.keys.first].include?(title)
47
+ parents = key
48
+ break
49
+ end
50
+ end
51
+ elsif title == item
52
+ parents = key
53
+ break
54
+ end
55
+ end
56
+ break unless parents.empty?
57
+ end
58
+ parents
59
+ end
60
+ module_function :find_hash_parents
61
+
62
+ # Given a category file that's an array, this method finds
63
+ # the children of an item, probably a map topic
64
+ def find_array_children(toc, title)
65
+ children = ''
66
+ toc.each do |item|
67
+ next unless item.is_a?(Hash)
68
+ item.each_pair do |key, values|
69
+ if key == title
70
+ children = values.flatten
71
+ break
72
+ end
73
+ end
74
+ break unless children.empty?
75
+ end
76
+ children
77
+ end
78
+ module_function :find_array_children
79
+
80
+ # Given a category file that's a hash, this method finds
81
+ # the children of an item, probably a map topic
82
+ def find_hash_children(toc, title)
83
+ children = ''
84
+ toc.each_key do |key|
85
+ toc[key].each do |item|
86
+ next unless item.is_a?(Hash)
87
+ unless item[title].nil?
88
+ children = item.values.flatten
89
+ break
90
+ end
91
+ end
92
+ break unless children.empty?
93
+ end
94
+ children
95
+ end
96
+ module_function :find_hash_children
97
+ end
98
+ end
@@ -0,0 +1,27 @@
1
+ module Nanoc
2
+ class ItemView
3
+ # allows apply_attributes to create new item attributes
4
+ def []=(key, value)
5
+ unwrap.attributes[key] = value
6
+ end
7
+ end
8
+ end
9
+
10
+ module Nanoc::HashExtensions
11
+ alias_method :original_freeze, :__nanoc_freeze_recursively
12
+
13
+ # prevents the item's frozen attributes from remaining frozen
14
+ def __nanoc_freeze_recursively
15
+ return if caller.first =~ %r{base/entities/document.rb}
16
+ original_freeze
17
+ end
18
+ end
19
+
20
+ class ConrefFSFilter < Nanoc::Filter
21
+ identifier :'conref-fs-filter'
22
+
23
+ def run(content, _)
24
+ ConrefFS.apply_attributes(@config, item, @rep.name)
25
+ NanocConrefFS::Conrefifier.liquify(@config, path: @item[:filename], content: content, rep: @rep.name)
26
+ end
27
+ end
@@ -1,202 +1,145 @@
1
1
  require_relative 'conrefifier'
2
-
3
- # Unsure why attr_accessor does not work here
4
- module VariableMixin
5
- def self.variables
6
- @variables
7
- end
8
-
9
- def self.variables=(variables)
10
- @variables = variables
11
- end
12
-
13
- def self.fetch_data_file(association)
14
- reference = association.split('.')
15
- variables = VariableMixin.variables
16
- data = variables['site']['data']
17
- while key = reference.shift
18
- data = data[key]
19
- end
20
- data
21
- end
22
- end
2
+ require 'active_support/core_ext/string'
23
3
 
24
4
  class ConrefFS < Nanoc::DataSource
25
5
  include Nanoc::DataSources::Filesystem
26
- include VariableMixin
6
+ include NanocConrefFS::Variables
7
+ include NanocConrefFS::Ancestry
27
8
 
28
9
  identifier :'conref-fs'
29
10
 
30
11
  # Before iterating over the file objects, this method loads the data folder
31
12
  # and applies it to an ivar for later usage.
32
- def load_objects(dir_name, kind, klass)
33
- if klass == Nanoc::Int::Item && @variables.nil?
34
- data = Datafiles.process(@site_config)
35
- config = @site_config.to_h
36
- @variables = { 'site' => { 'config' => config, 'data' => data } }
37
- VariableMixin.variables = @variables
38
- end
39
- super
13
+ def up
14
+ data_files = NanocConrefFS::Datafiles.collect_data(data_dir_name)
15
+ NanocConrefFS::Variables.data_files = data_files
16
+ NanocConrefFS::Variables.variables = {}
17
+ reps = @config[:reps] || [:default]
18
+ reps.each { |rep| ConrefFS.load_data_folder(@site_config, rep) }
40
19
  end
41
20
 
42
- # This function calls the parent super, then adds additional metadata to the item.
43
- def parse(content_filename, meta_filename, _kind)
44
- meta, content = super
45
- page_vars = Conrefifier.file_variables(@site_config[:page_variables], content_filename)
21
+ def data_dir_name
22
+ config.fetch(:data_dir) { |_| 'data' }
23
+ end
24
+
25
+ def self.load_data_folder(config, rep)
26
+ return unless NanocConrefFS::Variables.variables[rep].nil?
27
+ data_files = NanocConrefFS::Variables.data_files
28
+ data = NanocConrefFS::Datafiles.process(data_files, config, rep)
29
+ NanocConrefFS::Variables.variables[rep] = { 'site' => { 'config' => config, 'data' => data } }
30
+ end
31
+
32
+ def self.apply_attributes(config, item, rep)
33
+ page_vars = NanocConrefFS::Conrefifier.file_variables(config[:page_variables], item[:filename], rep)
34
+
35
+ frontmatter_vars = { :page => page_vars }.merge(NanocConrefFS::Variables.variables[rep])
36
+
46
37
  unless page_vars[:data_association].nil?
47
38
  association = page_vars[:data_association]
48
- toc = VariableMixin.fetch_data_file(association)
49
- meta[:parents] = if toc.is_a?(Array)
50
- find_array_parents(toc, meta['title'])
51
- elsif toc.is_a?(Hash)
52
- find_hash_parents(toc, meta['title'])
53
- end
54
-
55
- meta[:children] = if toc.is_a?(Array)
56
- find_array_children(toc, meta['title'])
57
- elsif toc.is_a?(Hash)
58
- find_hash_children(toc, meta['title'])
59
- end
60
- end
61
- page_vars.each_pair do |name, value|
62
- meta[name.to_s] = value
39
+ toc = NanocConrefFS::Variables.fetch_data_file(association, rep)
40
+ item[:parents] = NanocConrefFS::Ancestry::create_parents(toc, item.attributes)
41
+ item[:children] = NanocConrefFS::Ancestry::create_children(toc, item.attributes)
63
42
  end
64
- [meta, content]
65
- end
66
43
 
67
- # Given a category file that's an array, this method finds
68
- # the parent of an item
69
- def find_array_parents(toc, title)
70
- parents = ''
71
- toc.each do |item|
72
- if item.is_a?(Hash)
73
- parents = find_hash_parents(item, title)
74
- break unless parents.empty?
75
- end
44
+ page_vars.each_pair do |key, value|
45
+ item[key] = value
76
46
  end
77
- parents
78
- end
79
47
 
80
- # Given a category file that's a hash, this method finds
81
- # the parent of an item
82
- def find_hash_parents(toc, title)
83
- parents = ''
84
- toc.keys.each do |key|
85
- toc[key].each do |item|
86
- if item.is_a?(Hash)
87
- if item.keys.include?(title)
88
- parents = key
89
- break
90
- else
91
- if item[item.keys.first].include?(title)
92
- parents = key
93
- break
94
- end
95
- end
96
- elsif title == item
97
- parents = key
98
- break
48
+ item.attributes.each_pair do |key, value|
49
+ if value.is_a?(Array)
50
+ item[key] = value.map do |arr_v|
51
+ return arr_v unless arr_v =~ NanocConrefFS::Conrefifier::SINGLE_SUB
52
+ NanocConrefFS::Conrefifier.apply_liquid(arr_v, frontmatter_vars)
53
+ end
54
+ else
55
+ if value =~ NanocConrefFS::Conrefifier::SINGLE_SUB
56
+ value = NanocConrefFS::Conrefifier.apply_liquid(value, frontmatter_vars)
57
+ item[key] = value
99
58
  end
100
59
  end
101
- break unless parents.empty?
102
60
  end
103
- parents
104
61
  end
105
62
 
106
- # Given a category file that's an array, this method finds
107
- # the children of an item, probably a map topic
108
- def find_array_children(toc, title)
109
- children = ''
110
- toc.each do |item|
111
- next unless item.is_a?(Hash)
112
- item.each_pair do |key, values|
113
- if key == title
114
- children = values.flatten
115
- break
116
- end
117
- end
118
- break unless children.empty?
119
- end
120
- children
63
+ # There are a lot of problems when trying to parse liquid
64
+ # out of the frontmatter—all of them dealing with collision between
65
+ # the { character in Liquid and its signfigance in YAML. We'll overload
66
+ # the parse method here to resolve those issues ahead of time.
67
+ def parse(content_filename, meta_filename, _kind)
68
+ # Read data
69
+ data = read(content_filename)
70
+
71
+ # Check presence of metadata section
72
+ return [{}, data] if data !~ /\A-{3,5}\s*$/
73
+
74
+ # Split data
75
+ pieces = data.split(/^(-{5}|-{3})[ \t]*\r?\n?/, 3)
76
+ if pieces.size < 4
77
+ raise RuntimeError.new(
78
+ "The file '#{content_filename}' appears to start with a metadata section (three or five dashes at the top) but it does not seem to be in the correct format.",
79
+ )
121
80
  end
122
81
 
123
- # Given a category file that's a hash, this method finds
124
- # the children of an item, probably a map topic
125
- def find_hash_children(toc, title)
126
- children = ''
127
- toc.keys.each do |key|
128
- toc[key].each do |item|
129
- next unless item.is_a?(Hash)
130
- unless item[title].nil?
131
- children = item.values.flatten
132
- break
133
- end
134
- end
135
- break unless children.empty?
136
- end
137
- children
138
- end
82
+ # N.B. the only change to the original function
83
+ pieces[2].gsub!(/^([^:]+): (\{\{.+)/, '\1: \'\2\'')
139
84
 
140
- # This file reads each piece of content as it comes in. It also applies the conref variables
141
- # (demarcated by Liquid's {{ }} tags) using both the data/ folder and any variables defined
142
- # within the nanoc.yaml config file
143
- def read(filename)
144
- content = ''
85
+ # Parse
145
86
  begin
146
- page_vars = Conrefifier.file_variables(@site_config[:page_variables], filename)
147
- page_vars = { :page => page_vars }.merge(@variables)
148
-
149
- content = File.read(filename)
150
- return content unless filename.start_with?('content', 'layouts')
151
-
152
- # we must obfuscate essential ExtendedMarkdownFilter content
153
- content = content.gsub(/\{\{\s*#(\S+)\s*\}\}/, '[[#\1]]')
154
- content = content.gsub(/\{\{\s*\/(\S+)\s*\}\}/, '[[/\1]]')
155
- content = content.gsub(/\{\{\s*(octicon-\S+\s*[^\}]+)\s*\}\}/, '[[\1]]')
156
- rescue => e
157
- raise "Could not read #{filename}: #{e.inspect}"
87
+ meta = YAML.load(pieces[2]) || {}
88
+ rescue Exception => e
89
+ raise "Could not parse YAML for #{content_filename}: #{e.message}"
158
90
  end
91
+ verify_meta(meta, content_filename)
92
+ content = pieces[4]
159
93
 
160
- begin
161
- result = content
94
+ # Done
95
+ [meta, content]
96
+ end
162
97
 
163
- # This pass replaces any matched conditionals
164
- if result =~ Conrefifier::BLOCK_SUB || result =~ Conrefifier::SINGLE_SUB
165
- result = Conrefifier.apply_liquid(result, page_vars)
166
- end
98
+ def self.create_ignore_rules(rep, file)
99
+ current_articles = NanocConrefFS::Variables.fetch_data_file(file, rep)
100
+ current_articles = flatten_list(current_articles).flatten
101
+ current_articles = fix_nested_content(current_articles)
167
102
 
168
- # This second pass renders any previously inserted
169
- # data conditionals within the body. If a Liquid parse
170
- # returns a blank string, we'll return the original
171
- if result =~ Conrefifier::SINGLE_SUB
172
- result = result.gsub(Conrefifier::SINGLE_SUB) do |match|
173
- liquified = Conrefifier.apply_liquid(match, page_vars)
174
- liquified.empty? ? match : liquified
175
- end
176
- end
103
+ basic_yaml = NanocConrefFS::Variables.data_files["data/#{file.tr!('.', '/')}.yml"]
104
+ basic_yaml.gsub!(/\{%.+/, '')
105
+ full_file = YAML.load(basic_yaml)
106
+
107
+ full_user_articles = flatten_list(full_file).flatten
108
+ full_user_articles = fix_nested_content(full_user_articles)
109
+
110
+ blacklisted_articles = full_user_articles - current_articles
111
+ blacklisted_articles.map do |article|
112
+ "#{article.parameterize}.md"
113
+ end
114
+ end
177
115
 
178
- # This converts ": *" frontmatter strings into HTML equivalents;
179
- # otherwise, ": *" messes the YAML parsing
180
- result = result.gsub(/\A---\s*\n(.*?\n?)^---\s*$\n?/m) do |frontmatter|
181
- frontmatter.gsub(/:\s*(\*.+)/) do |_|
182
- asterisk_match = Regexp.last_match[1]
183
- if asterisk_match[1] != '*'
184
- asterisk_match = asterisk_match.sub(/\*(.+?)\*/, ': <em>\1</em>')
185
- else
186
- asterisk_match = asterisk_match.sub(/\*{2}(.+?)\*{2}/, ': <strong>\1</strong>')
187
- end
188
- asterisk_match
116
+ def self.flatten_list(arr)
117
+ result = []
118
+ return result unless arr
119
+ arr.each do |item|
120
+ if item.is_a?(Hash)
121
+ item.each_pair do |key, value|
122
+ result << key
123
+ result.concat(value)
189
124
  end
125
+ else
126
+ result << item
190
127
  end
128
+ end
191
129
 
192
- result
193
- rescue Liquid::SyntaxError => e
194
- # unrecognized Liquid, so just return the content
195
- STDERR.puts "Could not convert #{filename}: #{e.message}"
196
- result
197
- rescue => e
198
- raise "#{e.message}: #{e.inspect}"
130
+ result
131
+ end
132
+
133
+ def self.fix_nested_content(articles)
134
+ articles.delete_if do |i|
135
+ if i.is_a? Hash
136
+ articles.concat(i.keys.concat(i.values).flatten)
137
+ true
138
+ else
139
+ false
140
+ end
199
141
  end
142
+ articles
200
143
  end
201
144
 
202
145
  # This method is extracted from the Nanoc default FS