class Sigmund::Liquid::Tags::CustomNav

Display the children pages of the site, current page or the parent page. If not precised, nav is applied on the current page. The html output is based on the ul/li tags.

Passing through depth will control how many nested children are output

Usage:

{% nav site %} => <ul class=“nav”><li class=“on”><a href=“/features”>Features</a></li></ul>

{% nav site, no_wrapper: true, exclude: 'contact|about', id: 'main-nav', class: 'nav', active_class: 'on' }

Constants

Syntax

Public Class Methods

new(tag_name, markup, tokens, context) click to toggle source
Calls superclass method
# File lib/sigmund/liquid/tags/custom_nav.rb, line 19
def initialize(tag_name, markup, tokens, context)
  if markup =~ Syntax
    begin
      @source = ($1 || 'page').gsub(/"|'/, '')
      @options = { id: 'nav', depth: 1, class: '', active_class: 'on', bootstrap: false }
      markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') }

      @options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude]

      @options[:add_attributes] = []
      if @options[:snippet]
        template = @options[:snippet].include?('{') ? @options[:snippet] : context[:site].snippets.where(slug: @options[:snippet] ).try(:first).try(:template)
        unless template.blank?
          @options[:liquid_render] = ::Liquid::Template.parse(template)
          @options[:add_attributes] = ['editable_elements']
        end
      end
    rescue
      nil
    end
  else
    raise ::Liquid::SyntaxError.new("Syntax Error in 'nav' - Valid syntax: nav <page|site> <options>")
  end

  super
end

Public Instance Methods

render(context) click to toggle source
# File lib/sigmund/liquid/tags/custom_nav.rb, line 46
def render(context)
  children_output = []

  entries = fetch_entries(context)

  entries.each_with_index do |p, index|
    css = []
    css << 'first' if index == 0
    css << 'last' if index == entries.size - 1

    children_output << render_entry_link(context, p, css.join(' '), 1, index == 0, index == entries.size - 1)
  end

  output = children_output.join("\n")

  if @options[:no_wrapper] != 'true'
    list_class  = !@options[:class].blank? ? %( class="#{@options[:class]}") : ''
    output      = %{<nav id="#{@options[:id]}"#{list_class}><ul>\n#{output}</ul></nav>}
  end
  output
end

Private Instance Methods

bootstrap?() click to toggle source
# File lib/sigmund/liquid/tags/custom_nav.rb, line 164
def bootstrap?
  @options[:bootstrap] == 'true'
end
fetch_entries(context) click to toggle source

Determines root node for the list

# File lib/sigmund/liquid/tags/custom_nav.rb, line 71
def fetch_entries(context)
  @site, @page = context.registers[:site], context.registers[:page]

  children = (case @source
  when 'site'     then @site.pages.root.minimal_attributes(@options[:add_attributes]).first # start from home page
  when 'parent'   then @page.parent || @page
  when 'page'     then @page
  else
    @site.pages.fullpath(@source).minimal_attributes(@options[:add_attributes]).first
  end).children_with_minimal_attributes(@options[:add_attributes]).to_a

  children.delete_if { |p| !include_page?(p) }
end
include_page?(page) click to toggle source

Determines whether or not a page should be a part of the menu

# File lib/sigmund/liquid/tags/custom_nav.rb, line 154
def include_page?(page)
  if !page.listed? || page.templatized? || !page.published?
    false
  elsif @options[:exclude]
    (page.fullpath =~ @options[:exclude]).nil?
  else
    true
  end
end
render_children_for_page?(page, depth) click to toggle source
# File lib/sigmund/liquid/tags/custom_nav.rb, line 116
def render_children_for_page?(page, depth)
  depth.succ <= @options[:depth].to_i && page.children.reject { |c| !include_page?(c) }.any?
end
render_entry_children(context, page, depth) click to toggle source

Recursively creates a nested unordered list for the depth specified

# File lib/sigmund/liquid/tags/custom_nav.rb, line 121
def render_entry_children(context, page, depth)
  output = %{}

  children = page.children_with_minimal_attributes(@options[:add_attributes]).reject { |c| !include_page?(c) }
  if children.present?
    children.each do |c, page|
      css = []
      css << 'first' if children.first == c
      css << 'last'  if children.last  == c

      output << render_entry_link(context, c, css.join(' '), depth, children.first == c, children.last  == c)
    end
  end

  output
end
render_entry_link(context, page, css, depth, is_first, is_last) click to toggle source

Returns a list element, a link to the page and its children

# File lib/sigmund/liquid/tags/custom_nav.rb, line 86
def render_entry_link(context, page, css, depth, is_first, is_last)
  selected = @page.fullpath =~ /^#{page.fullpath}(\/.*)?$/ ? " #{@options[:active_class]}" : ''

  icon  = @options[:icon] ? '<span></span>' : ''

  href = File.join('/', @site.localized_page_fullpath(page))

  title = render_title(context, page, href, selected, is_first, is_last)
  if @options[:liquid_render]
    return title
  end
  label = %{#{icon if @options[:icon] != 'after' }#{title}#{icon if @options[:icon] == 'after' }}

  link_options = caret = ''

  if render_children_for_page?(page, depth) && bootstrap?
    css           += ' dropdown'
    link_options  = %{ class="dropdown-toggle" data-toggle="dropdown"}
    href          = '#'
    caret         = %{ <b class="caret"></b>}
  end

  output  = %{<li id="#{page.slug.to_s.dasherize}-link" class="link#{selected} #{css}">}
  output << %{<a href="#{href}"#{link_options}>#{label}#{caret}</a>}
  output << render_entry_children(context, page, depth.succ) if (depth.succ <= @options[:depth].to_i)
  output << %{</li>}

  output.strip
end
render_title(context, page, href, selected, is_first, is_last) click to toggle source
# File lib/sigmund/liquid/tags/custom_nav.rb, line 138
def render_title(context, page, href, selected, is_first, is_last)
  if @options[:liquid_render]
    context.stack do
      context['page'] = page
      context['is_first'] = is_first
      context['is_last'] = is_last
      context['href'] = href
      context['selected'] = selected
      @options[:liquid_render].render(context)
    end
  else
    page.title
  end
end