# Generates a table of contents based on markdown headers in the body # # The block has 2 optional args: # * A variable name. If provided, the toc will only be generated if the var is true # * An integer, describing the maximum depth at which headers are added to the toc class TocMakerBlock < Liquid::Block def initialize(tag_name, arg, tokens) super condition, depth = arg.split @max_depth = depth.to_s.empty? ? 100 : depth.to_i @condition_var = condition.strip unless condition.to_s.empty? @body = tokens end def to_internal_link(header) url = header.downcase.gsub(/[^a-zA-Z0-9 -]+/, "").strip.gsub(/\s+/, "-") "[#{header}](##{url})" end def render(context) contents = @body.render(context) if @condition_var && !context[@condition_var] # If the condition is false, the toc is not generated return contents end headers = contents.lines.map {|l| if /^(#+)\s+(\S.*)$/ =~ l [$1.length, $2] end }.compact min_indent = headers.map {|t| t[0]}.min headers = headers.map {|t| actual_depth = t[0] - min_indent if actual_depth < @max_depth then indent = " " * actual_depth "#{indent}* #{to_internal_link(t[1])}" end }.compact headers.unshift("### Table Of Contents\n") headers.join("\n") + contents end end Liquid::Template.register_tag('tocmaker', TocMakerBlock)