Module: Nanoc::Helpers::Breadcrumbs

Defined in:
lib/nanoc/helpers/breadcrumbs.rb

Overview

Defined Under Namespace

Modules: Int Classes: AmbiguousAncestorError

Instance Method Summary collapse

Instance Method Details



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/nanoc/helpers/breadcrumbs.rb', line 77

def breadcrumbs_trail(tiebreaker: Int::DEFAULT_TIEBREAKER)
  # The design of this function is a little complicated.
  #
  # We can’t use #parent_of from the ChildParent helper, because the
  # breadcrumb trail can have gaps. For example, the breadcrumbs trail for
  # /software/oink.md might be /index.md -> nil -> /software/oink.md if
  # there is no item matching /software.* or /software/index.*.
  #
  # What this function does instead is something more complicated:
  #
  # 1.  It creates an ordered prefix list, based on the identifier of the
  #     item to create a breadcrumbs trail for. For example,
  #     /software/oink.md might have the prefix list
  #     ['', '/software', '/software/oink.md'].
  #
  # 2.  For each of the elements in that list, it will create a list of
  #     patterns could match zero or more items. For example, the element
  #     '/software' would correspond to the pattern '/software.*'.
  #
  # 3.  For each of the elements in that list, and for each pattern for that
  #     element, it will find any matching element. For example, the
  #     pattern '/software.*' (coming from the prefix /software) would match
  #     the item /software.md.
  #
  # 4.  Return the list of items, with the last element replaced by the item
  #     for which the breadcrumb is generated for -- while ancestral items
  #     in the breadcrumbs trail can have a bit of ambiguity, the item for
  #     which to generate the breadcrumbs trail is fixed.

  # e.g. ['', '/foo', '/foo/bar']
  components = item.identifier.components
  prefixes = components.inject(['']) { |acc, elem| acc + [acc.last + '/' + elem] }

  tiebreaker = Int::ERROR_TIEBREAKER if tiebreaker == :error

  if @item.identifier.legacy?
    prefixes.map { |pr| @items[Nanoc::Core::Identifier.new('/' + pr, type: :legacy)] }
  else
    ancestral_prefixes = prefixes.reject { |pr| pr =~ /^\/index\./ }[0..-2]
    ancestral_items =
      ancestral_prefixes.map do |pr|
        if pr == ''
          @items['/index.*']
        else
          prefix_patterns = Int.patterns_for_prefix(pr)
          prefix_patterns.lazy.map { |pat| Int.find_one(@items, pat, tiebreaker) }.find(&:itself)
        end
      end
    ancestral_items + [item]
  end
end