diff options
author | Samy Pessé <samypesse@gmail.com> | 2015-01-19 10:24:43 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2016-12-22 15:00:28 +0100 |
commit | 3f1041209582c26abc595be9c2c99189f5b85f3f (patch) | |
tree | 9bd3ef143b64712bee64b293e74e5a0dfe48e6fd /packages/gitbook-markdown/lib | |
parent | 8e513c8e60063358286fc286037da1969f17bba0 (diff) | |
download | gitbook-3f1041209582c26abc595be9c2c99189f5b85f3f.zip gitbook-3f1041209582c26abc595be9c2c99189f5b85f3f.tar.gz gitbook-3f1041209582c26abc595be9c2c99189f5b85f3f.tar.bz2 |
Add base summary parser and test associated
Diffstat (limited to 'packages/gitbook-markdown/lib')
-rw-r--r-- | packages/gitbook-markdown/lib/index.js | 4 | ||||
-rw-r--r-- | packages/gitbook-markdown/lib/summary.js | 148 |
2 files changed, 151 insertions, 1 deletions
diff --git a/packages/gitbook-markdown/lib/index.js b/packages/gitbook-markdown/lib/index.js index e4ada5e..15a7f54 100644 --- a/packages/gitbook-markdown/lib/index.js +++ b/packages/gitbook-markdown/lib/index.js @@ -2,5 +2,7 @@ var kramed = require("kramed"); var _ = require("lodash"); module.exports = { - + parse: { + summary: require("./summary") + } }; diff --git a/packages/gitbook-markdown/lib/summary.js b/packages/gitbook-markdown/lib/summary.js new file mode 100644 index 0000000..21eadd1 --- /dev/null +++ b/packages/gitbook-markdown/lib/summary.js @@ -0,0 +1,148 @@ +var _ = require('lodash'); +var kramed = require('kramed'); + + +// 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 kramed 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, nums) { + // Check if it's a link + var matches = kramed.InlineLexer.rules.link.exec(src); + + var level = nums.join('.'); + + // Not a link, return plain text + if(!matches) { + return { + title: src, + level: level, + path: null, + }; + } + + return { + title: matches[1], + level: level, + + // Normalize path + // 1. Convert Window's "\" to "/" + // 2. Remove leading "/" if exists + path: matches[2].replace(/\\/g, '/').replace(/^\/+/, ''), + }; +} + +function parseChapter(nodes, nums) { + // Convert single number to an array + nums = _.isArray(nums) ? nums : [nums]; + + return _.extend(parseTitle(_.first(nodes).text, nums), { + articles: _.map(listSplit(filterList(nodes), 'list_item_start', 'list_item_end'), function(nodes, i) { + return parseChapter(nodes, nums.concat(i + 1)); + }) + }); +} + +function defaultChapterList(chapterList) { + var first = _.first(chapterList); + + // Check if introduction node was specified in SUMMARY.md + if (first) { + var chapter = parseChapter(first, [0]); + + // Already have README node, we're good to go + if(chapter.path === 'README.md') { + return chapterList; + } + } + + // It wasn't specified, so add in default + return [ + [ { type: 'text', text: '[Introduction](README.md)' } ] + ].concat(chapterList); +} + +function listGroups(src) { + var nodes = kramed.lexer(src); + + // Get out groups of lists + return listSplit( + filterList(nodes), + 'list_item_start', 'list_item_end' + ); +} + +function parseSummary(src) { + // Split out chapter sections + var chapters = defaultChapterList(listGroups(src)) + .map(parseChapter); + + return { + chapters: chapters + }; +} + +function parseEntries (src) { + return listGroups(src).map(parseChapter); +} + + +// Exports +module.exports = parseSummary; +module.exports.entries = parseEntries; |