summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-markdown/lib
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2015-01-19 10:24:43 +0100
committerSamy Pessé <samypesse@gmail.com>2016-12-22 15:00:28 +0100
commit3f1041209582c26abc595be9c2c99189f5b85f3f (patch)
tree9bd3ef143b64712bee64b293e74e5a0dfe48e6fd /packages/gitbook-markdown/lib
parent8e513c8e60063358286fc286037da1969f17bba0 (diff)
downloadgitbook-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.js4
-rw-r--r--packages/gitbook-markdown/lib/summary.js148
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;