lib/nanoc/helpers/breadcrumbs.rb in nanoc-4.9.9 vs lib/nanoc/helpers/breadcrumbs.rb in nanoc-4.10.0

- old
+ new

@@ -31,26 +31,55 @@ end end # @return [Array] def breadcrumbs_trail + # 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] } if @item.identifier.legacy? prefixes.map { |pr| @items[Nanoc::Identifier.new('/' + pr, type: :legacy)] } else - prefixes - .reject { |pr| pr =~ /^\/index\./ } - .map do |pr| + 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| @items[pat] }.find(&:itself) end end + ancestral_items + [item] end end end end