Module: Howdoc::Navigation

Defined in:
lib/howdoc/navigation.rb

Overview

The menu, and the links from one guide to the next.

A guide is written the moment its test finishes, when no other guide is known yet -- tests run in forked workers and each one writes its own page -- so a guide cannot draw a menu of guides. It leaves an empty

Class Method Summary collapse

Class Method Details

.counterpart(record, records) ⇒ Object



99
100
101
102
103
# File 'lib/howdoc/navigation.rb', line 99

def counterpart(record, records)
  return records.find { |other| other.id == record.id } unless record.id.nil?

  records.find { |other| other.permalink == record.permalink }
end

.destination(locale, record, by_locale) ⇒ Object



93
94
95
96
97
# File 'lib/howdoc/navigation.rb', line 93

def destination(locale, record, by_locale)
  counterpart = record && counterpart(record, by_locale[locale] || [])

  "../#{locale}/#{counterpart ? counterpart.filename : Registry::INDEX_FILENAME}"
end

.fill(markup, name) ⇒ Object

Stripped, so that filling a page in a second time leaves it exactly as the first time left it: the pass runs once per suite and again at the end of a run, and a page that grew a blank line each time would show up as changed in a repository for no reason at all.



49
50
51
# File 'lib/howdoc/navigation.rb', line 49

def fill(markup, name)
  markup.sub(placeholder(name)) { yield.strip }
end

.install(by_locale, root: Howdoc.config.root) ⇒ Object

Writes the menu and the pager into every guide. by_locale is the sorted records the index was built from, so the menu lists the guides in the same order the index does.



24
25
26
27
28
29
30
# File 'lib/howdoc/navigation.rb', line 24

def install(by_locale, root: Howdoc.config.root)
  by_locale.each_value.flat_map do |records|
    records.each_with_index.filter_map do |record, position|
      write(record, records:, position:, by_locale:, root:)
    end
  end
end

.label(locale) ⇒ Object

A language names itself in its own language, which is how a reader who cannot read the current page still recognises the way out of it.



107
108
109
# File 'lib/howdoc/navigation.rb', line 107

def label(locale)
  Narrator.phrase(:languages, locale, locale:, default: locale.to_s.upcase)
end

.languages(current_locale:, by_locale:, record: nil) ⇒ Object

The same guide in the other languages the application publishes.

Matched by identifier rather than by file name: a guide with a translated heading gets a translated file name, so "1.3" is the only thing the two pages are sure to have in common. A guide that was never written in the other language points at that language's index instead of nowhere.



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/howdoc/navigation.rb', line 80

def languages(current_locale:, by_locale:, record: nil)
  ordered(by_locale.keys).map do |locale|
    current = locale.to_s == current_locale.to_s

    {
      code: locale.to_s,
      label: label(locale),
      current:,
      href: (destination(locale, record, by_locale) unless current)
    }
  end
end


57
58
59
60
61
62
63
# File 'lib/howdoc/navigation.rb', line 57

def nav(record, records, by_locale)
  Templates.render(
    'shared/html/nav.haml',
    locale: record.locale, records:, current: record, config: Howdoc.config,
    languages: languages(current_locale: record.locale, record:, by_locale:)
  )
end

.ordered(locales) ⇒ Object



111
112
113
114
115
116
# File 'lib/howdoc/navigation.rb', line 111

def ordered(locales)
  configured = Howdoc.config.locales&.map(&:to_s)
  return locales.map(&:to_s).sort if configured.nil?

  (configured & locales.map(&:to_s)) | locales.map(&:to_s).sort
end

.pager(record, records, position) ⇒ Object



65
66
67
68
69
70
71
72
# File 'lib/howdoc/navigation.rb', line 65

def pager(record, records, position)
  Templates.render(
    'shared/html/pager.haml',
    locale: record.locale, config: Howdoc.config,
    previous: (records[position - 1] if position.positive?),
    next: records[position + 1]
  )
end

.placeholder(name) ⇒ Object



53
54
55
# File 'lib/howdoc/navigation.rb', line 53

def placeholder(name)
  %r{<nav[^>]*data-howdoc-#{name}[^>]*>.*?</nav>}m
end

.write(record, records:, position:, by_locale:, root:) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/howdoc/navigation.rb', line 32

def write(record, records:, position:, by_locale:, root:)
  path = File.join(root, record.locale.to_s, record.filename)
  return nil unless File.file?(path)

  markup = File.read(path)
  filled = fill(markup, :nav) { nav(record, records, by_locale) }
  filled = fill(filled, :pager) { pager(record, records, position) }
  return nil if filled == markup

  File.write(path, filled)
  path
end