Skip to content

Commit

Permalink
Add ChildParent helper
Browse files Browse the repository at this point in the history
  • Loading branch information
denisdefreyne committed Apr 17, 2016
1 parent b2df02e commit 4458be2
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/nanoc/helpers.rb
Expand Up @@ -2,6 +2,7 @@ module Nanoc::Helpers
autoload 'Blogging', 'nanoc/helpers/blogging'
autoload 'Breadcrumbs', 'nanoc/helpers/breadcrumbs'
autoload 'Capturing', 'nanoc/helpers/capturing'
autoload 'ChildParent', 'nanoc/helpers/child_parent'
autoload 'Filtering', 'nanoc/helpers/filtering'
autoload 'HTMLEscape', 'nanoc/helpers/html_escape'
autoload 'LinkTo', 'nanoc/helpers/link_to'
Expand Down
51 changes: 51 additions & 0 deletions lib/nanoc/helpers/child_parent.rb
@@ -0,0 +1,51 @@
module Nanoc::Helpers
# Provides functionality for fetching the children and the parent of a given
# item. This works for both full identifiers and legacy identifiers.
module ChildParent
# Returns the parent of the given item.
#
# For items with legacy identifiers, the parent is the item where the
# identifier contains one less component than the identifier of the given
# item. For # example, the parent of the “/projects/nanoc/” item is the
# “/projects/” item.
#
# For items with full identifiers, the parent is the item where the
# identifier contains one less component than the identifier of the given
# item, and ends with any extension. For example, the parent of the
# “/projects/nanoc.md” item could be the “/projects.md” item, or the
# “/projects.html” item, etc. Note that the parent is ambiguous for items
# that have a full identifier; only the first candidate parent item will be
# returned.
def parent_of(item)
if item.identifier.legacy?
item.parent
else
path_without_last_component = item.identifier.to_s.sub(/[^\/]+$/, '').chop
@items[path_without_last_component + '.*']
end
end

# Returns the children of the given item.
#
# For items with legacy identifiers, the children are the items where the
# identifier contains one more component than the identifier of the given
# item. For example, the children of the “/projects/” item could be
# “/projects/nanoc/” and “/projects/cri/”, but not “/about/” nor
# “/projects/nanoc/history/”.
#
# For items with full identifiers, the children are the item where the
# identifier starts with the identifier of the given item, minus the
# extension, followed by a slash. For example, the children of the
# “/projects.md” item could be the “/projects/nanoc.md” and
# “/projects/cri.adoc” items , but not “/about.md” nor
# “/projects/nanoc/history.md”.
def children_of(item)
if item.identifier.legacy?
item.children
else
pattern = item.identifier.without_ext + '/*'
@items.find_all(pattern)
end
end
end
end
105 changes: 105 additions & 0 deletions spec/nanoc/helpers/child_parent_spec.rb
@@ -0,0 +1,105 @@
describe Nanoc::Helpers::ChildParent, helper: true do
describe '#children_of' do
subject { helper.children_of(item) }

let(:item) { ctx.create_item('some content', {}, identifier) }

context 'legacy identifier' do
let(:identifier) { Nanoc::Identifier.new('/foo/', type: :legacy) }

let!(:child_item) do
ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo/a/', type: :legacy))
end

let!(:grandchild_item) do
ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/a/b/', type: :legacy))
end

let!(:sibling_item) do
ctx.create_item('xyz', {}, Nanoc::Identifier.new('/bar/', type: :legacy))
end

it 'returns only direct children' do
expect(subject).to eql([child_item])
end
end

context 'full identifier' do
let(:identifier) { Nanoc::Identifier.new('/foo.md', type: :full) }

let!(:child_item) do
ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo/a.md', type: :full))
end

let!(:grandchild_item) do
ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/a/b.md', type: :full))
end

let!(:sibling_item) do
ctx.create_item('xyz', {}, Nanoc::Identifier.new('/bar.md', type: :full))
end

let!(:index_child_item) do
ctx.create_item('xyz', {}, Nanoc::Identifier.new('/foo/a/index.md', type: :full))
end

it 'returns only direct children' do
expect(subject).to eql([child_item])
end
end
end

describe '#parent_of' do
subject { helper.parent_of(item) }

let(:item) { ctx.create_item('some content', {}, identifier) }

context 'legacy identifier' do
let(:identifier) { Nanoc::Identifier.new('/foo/bar/', type: :legacy) }

let!(:parent_item) do
ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo/', type: :legacy))
end

let!(:sibling_item) do
ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/qux/', type: :legacy))
end

let!(:child_item) do
ctx.create_item('xyz', {}, Nanoc::Identifier.new('/foo/bar/asdf/', type: :legacy))
end

let!(:grandparent_item) do
ctx.create_item('opq', {}, Nanoc::Identifier.new('/', type: :legacy))
end

it 'returns parent' do
expect(subject).to eql(parent_item)
end
end

context 'full identifier' do
let(:identifier) { Nanoc::Identifier.new('/foo/bar.md', type: :full) }

let!(:parent_item) do
ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo.md', type: :full))
end

let!(:sibling_item) do
ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/qux.md', type: :full))
end

let!(:child_item) do
ctx.create_item('xyz', {}, Nanoc::Identifier.new('/foo/bar/asdf.md', type: :full))
end

let!(:grandparent_item) do
ctx.create_item('opq', {}, Nanoc::Identifier.new('/index.md', type: :full))
end

it 'returns parent' do
expect(subject).to eql(parent_item)
end
end
end
end

0 comments on commit 4458be2

Please sign in to comment.