var _ = require('lodash');
var marked = require('marked');


// Utility function for splitting a list into groups
function splitBy(list, starter, ender) {
    var starts = 0;
    var ends = 0;
    var group = [];

    // Groups
    return _.reduce(list, function(groups, value) {
        // Ignore start and end delimiters in resulted groups
        if(starter(value)) {
            starts++;
        } else if(ender(value)) {
            ends++;
        }

        // Add current value to group
        group.push(value);

        // We've got a matching
        if(starts === ends && starts !== 0) {
            // Add group to end groups
            // (remove starter and ender token)
            groups.push(group.slice(1, -1));

            // Reset group
            group = [];
        }

        return groups;
    }, []);
}

function listSplit(nodes, start_type, end_type) {
    return splitBy(nodes, function(el) {
        return el.type === start_type;
    }, function(el) {
        return el.type === end_type;
    });
}

// Get the biggest list
// out of a list of marked nodes
function filterList(nodes) {
    return _.chain(nodes)
    .toArray()
    .rest(function(el) {
        // Get everything after list_start
        return el.type !== 'list_start';
    })
    .reverse()
    .rest(function(el) {
        // Get everything after list_end (remember we're reversed)
        return el.type !== 'list_end';
    })
    .reverse()
    .value().slice(1, -1);
}

// Parses an Article or Chapter title
// supports extracting links
function parseTitle(src) {
    // Check if it's a link
    var matches = marked.InlineLexer.rules.link.exec(src);

    // Not a link, return plain text
    if(!matches) {
        return {
            title: src,
            path: null,
        };
    }

    return {
        title: matches[1],
        path: matches[2],
    };
}

function parseArticle(nodes) {
    return parseTitle(_.first(nodes).text);
}

function parseChapter(nodes) {
    return {
        chapter: parseTitle(_.first(nodes).text),
        articles: _.map(listSplit(filterList(nodes), 'list_item_start', 'list_item_end'), parseArticle)
    };
}

function parseSummary(src) {
    var nodes = marked.lexer(src);

    // Get out list of chapters
    var chapterList = filterList(nodes);

    // Split out chapter sections
    var chapters = _.chain(listSplit(chapterList, 'list_item_start', 'list_item_end'))
    .map(parseChapter)
    .value();

    return {
        chapters: chapters
    };
}


// Exports
module.exports = parseSummary;

@@ -1830,24 +1830,25 @@
 hes%5B1%5D,%0A
+%0A
         
 path: ma
@@ -1835,24 +1835,164 @@
 %5D,%0A%0A        
+// Replace .md references with .html%0A        path: matches%5B2%5D.replace(/%5C.md$/, '.html'),%0A%0A        // Original, non normalized path%0A        _
 path: matche

Normalize chapter & article paths