So I parse through a document in order to grab all the headings with stackHeadings(). I do this in order to build a Microsoft Word style document map with buildNav(). This currently works OK but its not very robust and breaks anytime the headings do not follow a strict order... e.g. (If you start with an H2 it breaks, if you nest a H3 under and H1 it breaks, etc...)
I can't quite figure out the best way to fix this (make it more robust). I'm taking advantage of jQuery's `nextUntil' function to find all the h2s between two h1s.
One possibility is replacing:
elem.nextUntil( 'h' + cur, 'h' + next )
with
elem.nextUntil( 'h' + cur, 'h' + next + ',h' + (next + 1) + ',h' + (next + 2) ... )
to find ALL subheadings between two headings of the same level. But now h3 children of h1s would only be nested one level rather than two.
So then you'd have to compare the current heading level with the parent heading level, and if there's a jump of more than one (h1 -> h3), you'd have to create an empty child between them as a nesting placeholder for the missing h2.
Any ideas or solutions would be greatly appreciated!
stackHeadings = (items, cur, counter) ->
cur = 1 if cur == undefined
counter ?= 1
next = cur + 1
for elem, index in items
elem = $(elem)
children = filterHeadlines( elem.nextUntil( 'h' + cur, 'h' + next ) )
d.children = stackHeadings( children, next, counter ) if children.length > 0
d
filterHeadlines = ( $hs ) ->
_.filter( $hs, ( h ) -> $(h).text().match(/[^\s]/) )
buildNav = ( ul, items ) ->
for child, index in items
li = $( "<li>" )
$( ul ).append( li )
$a = $("<a/>")
$a.attr( "id", "nav-title-" + child.id )
li.append( $a )
if child.children
subUl = document.createElement( 'ul' )
li.append( subUl )
buildNav( subUl, child.children )
items = stackHeadings( filterHeadlines( source.find( 'h1' ) ) )
ul = $('<ul>')
buildNav( ul, items)