Module: GuidesStyle18F::NavigationMenu

Defined in:
lib/guides_style_18f/navigation.rb

Constant Summary collapse

YAML_PREFIX =
"---\n"

Class Method Summary collapse

Class Method Details

.apply_nav_update(url, nav, nav_data, original) ⇒ Object



185
186
187
188
189
190
191
192
# File 'lib/guides_style_18f/navigation.rb', line 185

def self.apply_nav_update(url, nav, nav_data, original)
  orig = original[url]
  if orig.nil?
    apply_new_nav_item(url, nav, nav_data, original)
  else
    orig['text'] = nav['text']
  end
end

.apply_new_nav_item(url, nav, nav_data, original) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
# File 'lib/guides_style_18f/navigation.rb', line 194

def self.apply_new_nav_item(url, nav, nav_data, original)
  parent_url = File.dirname(url || '/')
  parent = original["#{parent_url}/"]
  if parent_url == '/'
    nav_data << (original[url] = nav)
  elsif parent.nil?
    nav_data << { orphan_url: url }
  else
    (parent['children'] ||= []) << nav
  end
end

.check_for_orphaned_items(nav_data) ⇒ Object



206
207
208
209
210
211
212
# File 'lib/guides_style_18f/navigation.rb', line 206

def self.check_for_orphaned_items(nav_data)
  orphans = nav_data.map { |nav| nav[:orphan_url] }.compact
  unless orphans.empty?
    fail(StandardError, "Parent pages missing for the following:\n  " +
      orphans.join("\n  "))
  end
end

.format_navigation_section(nav_data) ⇒ Object



238
239
240
# File 'lib/guides_style_18f/navigation.rb', line 238

def self.format_navigation_section(nav_data)
  nav_data.empty? ? '' : nav_data.to_yaml[YAML_PREFIX.size..-1]
end

.map_nav_items_by_url(parent_url, nav_data) ⇒ Object



140
141
142
143
144
145
# File 'lib/guides_style_18f/navigation.rb', line 140

def self.map_nav_items_by_url(parent_url, nav_data)
  nav_data.flat_map do |nav|
    url = File.join('', parent_url, nav['url'] || '')
    [[url, nav]].concat(map_nav_items_by_url(url, nav['children'] || []))
  end
end


155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/guides_style_18f/navigation.rb', line 155

def self.page_nav(front_matter)
  url_components = front_matter['permalink'].split('/')[1..-1]
  result = {
    'text' => front_matter['navtitle'] || front_matter['title'],
    'url' => "#{url_components.nil? ? '' : url_components.last}/",
    'internal' => true,
  }
  # Delete the root URL so we don't have an empty `url:` property laying
  # around.
  result.delete 'url' if result['url'] == '/'
  result
end

.process_line(line, lines, nav_data, in_navigation = false) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/guides_style_18f/navigation.rb', line 223

def self.process_line(line, lines, nav_data, in_navigation = false)
  if !in_navigation && line.start_with?('navigation:')
    lines << line << format_navigation_section(nav_data)
    in_navigation = true
  elsif in_navigation
    in_navigation = line.start_with?(' ') || line.start_with?('-')
    lines << line unless in_navigation
  else
    lines << line
  end
  in_navigation
end

.remove_stale_children(parent) ⇒ Object



178
179
180
181
182
183
# File 'lib/guides_style_18f/navigation.rb', line 178

def self.remove_stale_children(parent)
  children = (parent['children'] || [])
  children.delete_if { |nav| nav['delete'] }
  parent.delete 'children' if children.empty?
  children.each { |child| remove_stale_children(child) }
end

.remove_stale_nav_entries(nav_data, original, updated) ⇒ Object



168
169
170
171
172
173
174
175
176
# File 'lib/guides_style_18f/navigation.rb', line 168

def self.remove_stale_nav_entries(nav_data, original, updated)
  # Remove old entries whose pages have been deleted
  original.each do |url, nav|
    nav['delete'] = true if !updated.member?(url) && nav['internal']
  end
  original.delete_if { |_url, nav| nav['delete'] }
  nav_data.delete_if { |nav| nav['delete'] }
  nav_data.each { |nav| remove_stale_children(nav) }
end

.update_navigation_data(nav_data, basedir) ⇒ Object



132
133
134
135
136
137
138
# File 'lib/guides_style_18f/navigation.rb', line 132

def self.update_navigation_data(nav_data, basedir)
  original = map_nav_items_by_url('/', nav_data).to_h
  updated = updated_nav_data(basedir)
  remove_stale_nav_entries(nav_data, original, updated)
  updated.map { |url, nav| apply_nav_update(url, nav, nav_data, original) }
  check_for_orphaned_items(nav_data)
end

.updated_nav_data(basedir) ⇒ Object



147
148
149
150
151
152
153
# File 'lib/guides_style_18f/navigation.rb', line 147

def self.updated_nav_data(basedir)
  front_matter = FrontMatter.load basedir
  errors = FrontMatter.validate_with_message_upon_error front_matter
  abort errors + "\n_config.yml not updated" if errors
  front_matter.values.sort_by { |fm| fm['permalink'] }
    .map { |fm| [fm['permalink'], page_nav(fm)] }.to_h
end

.write_navigation_data_to_config_file(config_path, nav_data) ⇒ Object



214
215
216
217
218
219
220
221
# File 'lib/guides_style_18f/navigation.rb', line 214

def self.write_navigation_data_to_config_file(config_path, nav_data)
  lines = []
  in_navigation = false
  open(config_path).each_line do |line|
    in_navigation = process_line line, lines, nav_data, in_navigation
  end
  File.write config_path, lines.join
end