summaryrefslogtreecommitdiffstats
path: root/lib/parse
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2015-01-19 09:47:36 +0100
committerSamy Pessé <samypesse@gmail.com>2015-01-19 09:47:36 +0100
commitec586dd3cdf06e9567f5d3e4961022ddc3c94778 (patch)
treecc7825ab73110b4e6fbedee404427b052edffa17 /lib/parse
parent80432161708357bdcf0e00533d9e6d327636dab6 (diff)
downloadgitbook-ec586dd3cdf06e9567f5d3e4961022ddc3c94778.zip
gitbook-ec586dd3cdf06e9567f5d3e4961022ddc3c94778.tar.gz
gitbook-ec586dd3cdf06e9567f5d3e4961022ddc3c94778.tar.bz2
Clear folder
Diffstat (limited to 'lib/parse')
-rw-r--r--lib/parse/glossary.js48
-rw-r--r--lib/parse/include.js12
-rw-r--r--lib/parse/includer.js15
-rw-r--r--lib/parse/index.js11
-rw-r--r--lib/parse/is_exercise.js17
-rw-r--r--lib/parse/is_quiz.js87
-rw-r--r--lib/parse/langs.js25
-rw-r--r--lib/parse/lex.js79
-rw-r--r--lib/parse/navigation.js64
-rw-r--r--lib/parse/page.js160
-rw-r--r--lib/parse/progress.js47
-rw-r--r--lib/parse/readme.js45
-rw-r--r--lib/parse/renderer.js141
-rw-r--r--lib/parse/summary.js167
14 files changed, 0 insertions, 918 deletions
diff --git a/lib/parse/glossary.js b/lib/parse/glossary.js
deleted file mode 100644
index 549e9fd..0000000
--- a/lib/parse/glossary.js
+++ /dev/null
@@ -1,48 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-
-// Get all the pairs of header + paragraph in a list of nodes
-function groups(nodes) {
- // A list of next nodes
- var next = nodes.slice(1).concat(null);
-
- return _.reduce(nodes, function(accu, node, idx) {
- // Skip
- if(!(
- node.type === 'heading' &&
- (next[idx] && next[idx].type === 'paragraph')
- )) {
- return accu;
- }
-
- // Add group
- accu.push([
- node,
- next[idx]
- ]);
-
- return accu;
- }, []);
-}
-
-function parseGlossary(src) {
- var nodes = kramed.lexer(src);
-
- return groups(nodes)
- .map(function(pair) {
- // Simplify each group to a simple object with name/description
- return {
- name: pair[0].text,
- id: entryId(pair[0].text),
- description: pair[1].text,
- };
- });
-}
-
-// Normalizes a glossary entry's name to create an ID
-function entryId(name) {
- return name.toLowerCase();
-}
-
-module.exports = parseGlossary;
-module.exports.entryId = entryId;
diff --git a/lib/parse/include.js b/lib/parse/include.js
deleted file mode 100644
index 483b184..0000000
--- a/lib/parse/include.js
+++ /dev/null
@@ -1,12 +0,0 @@
-var _ = require('lodash');
-
-module.exports = function(markdown, includer) {
- // Memoized include function (to cache lookups)
- var _include = _.memoize(includer);
-
- return markdown.replace(/{{([\s\S]+?)}}/g, function(match, key) {
- // If fails leave content as is
- key = key.trim();
- return _include(key) || match;
- });
-};
diff --git a/lib/parse/includer.js b/lib/parse/includer.js
deleted file mode 100644
index f7f20e0..0000000
--- a/lib/parse/includer.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Return a fs inclduer
-module.exports = function(ctx, folders, resolveFile, readFile) {
- return function(name) {
- return ctx[name] ||
- folders.map(function(folder) {
- // Try including snippet from FS
- try {
- var fname = resolveFile(folder, name);
- // Trim trailing newlines/space of imported snippets
- return readFile(fname, 'utf8').trimRight();
- } catch(err) {}
- })
- .filter(Boolean)[0];
- }
-};
diff --git a/lib/parse/index.js b/lib/parse/index.js
deleted file mode 100644
index 23471af..0000000
--- a/lib/parse/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-module.exports = {
- summary: require('./summary'),
- glossary: require('./glossary'),
- langs: require('./langs'),
- page: require('./page'),
- lex: require('./lex'),
- progress: require('./progress'),
- navigation: require('./navigation'),
- readme: require('./readme'),
- includer: require('./includer')
-};
diff --git a/lib/parse/is_exercise.js b/lib/parse/is_exercise.js
deleted file mode 100644
index 74ed753..0000000
--- a/lib/parse/is_exercise.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var _ = require('lodash');
-
-function isExercise(nodes) {
- var codeType = { type: 'code' };
-
- // Number of code nodes in section
- var len = _.filter(nodes, codeType).length;
-
- return (
- // Got 3 or 4 code blocks
- (len === 3 || len === 4) &&
- // Ensure all nodes are at the end
- _.all(_.last(nodes, len), codeType)
- );
-}
-
-module.exports = isExercise;
diff --git a/lib/parse/is_quiz.js b/lib/parse/is_quiz.js
deleted file mode 100644
index 3322ff0..0000000
--- a/lib/parse/is_quiz.js
+++ /dev/null
@@ -1,87 +0,0 @@
-var _ = require('lodash');
-
-function isQuizNode(node) {
- return (/^[(\[][ x][)\]]/).test(node.text || node);
-}
-
-function isTableQuestion(nodes) {
- var block = questionBlock(nodes);
- return (
- block.length === 1 &&
- block[0].type === 'table' &&
- _.all(block[0].cells[0].slice(1), isQuizNode)
- );
-}
-
-function isListQuestion(nodes) {
- var block = questionBlock(nodes);
- // Counter of when we go in and out of lists
- var inlist = 0;
- // Number of lists we found
- var lists = 0;
- // Elements found outside a list
- var outsiders = 0;
- // Ensure that we have nothing except lists
- _.each(block, function(node) {
- if(node.type === 'list_start') {
- inlist++;
- } else if(node.type === 'list_end') {
- inlist--;
- lists++;
- } else if(inlist === 0) {
- // Found non list_start or list_end whilst outside a list
- outsiders++;
- }
- });
- return lists > 0 && outsiders === 0;
-}
-
-function isQuestion(nodes) {
- return isListQuestion(nodes) || isTableQuestion(nodes);
-}
-
-// Remove (optional) paragraph header node and blockquote
-function questionBlock(nodes) {
- return nodes.slice(
- nodes[0].type === 'paragraph' ? 1 : 0,
- _.findIndex(nodes, { type: 'blockquote_start' })
- );
-}
-
-function splitQuestions(nodes) {
- // Represents nodes in current question
- var buffer = [];
- return _.reduce(nodes, function(accu, node) {
- // Add node to buffer
- buffer.push(node);
-
- // Flush buffer once we hit the end of a question
- if(node.type === 'blockquote_end') {
- accu.push(buffer);
- // Clear buffer
- buffer = [];
- }
-
- return accu;
- }, []);
-}
-
-function isQuiz(nodes) {
- // Extract potential questions
- var questions = splitQuestions(
- // Skip quiz title if there
- nodes.slice(
- (nodes[0] && nodes[0].type) === 'paragraph' ? 1 : 0
- )
- );
-
- // Nothing that looks like questions
- if(questions.length === 0) {
- return false;
- }
-
- // Ensure all questions are correctly structured
- return _.all(questions, isQuestion);
-}
-
-module.exports = isQuiz;
diff --git a/lib/parse/langs.js b/lib/parse/langs.js
deleted file mode 100644
index 01b7c8c..0000000
--- a/lib/parse/langs.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var _ = require("lodash");
-var parseEntries = require("./summary").entries;
-
-
-var parseLangs = function(content) {
- var entries = parseEntries(content);
-
- return {
- list: _.chain(entries)
- .filter(function(entry) {
- return Boolean(entry.path);
- })
- .map(function(entry) {
- return {
- title: entry.title,
- path: entry.path,
- lang: entry.path.replace("/", "")
- };
- })
- .value()
- };
-};
-
-
-module.exports = parseLangs; \ No newline at end of file
diff --git a/lib/parse/lex.js b/lib/parse/lex.js
deleted file mode 100644
index 3391acf..0000000
--- a/lib/parse/lex.js
+++ /dev/null
@@ -1,79 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-
-var isExercise = require('./is_exercise');
-var isQuiz = require('./is_quiz');
-
-// Split a page up into sections (lesson, exercises, ...)
-function splitSections(nodes) {
- var section = [];
-
- return _.reduce(nodes, function(sections, el) {
- if(el.type === 'hr') {
- sections.push(section);
- section = [];
- } else {
- section.push(el);
- }
-
- return sections;
- }, []).concat([section]); // Add remaining nodes
-}
-
-// What is the type of this section
-function sectionType(nodes, idx) {
- if(isExercise(nodes)) {
- return 'exercise';
- } else if(isQuiz(nodes)) {
- return 'quiz';
- }
-
- return 'normal';
-}
-
-// Generate a uniqueId to identify this section in our code
-function sectionId(section, idx) {
- return _.uniqueId('gitbook_');
-}
-
-function lexPage(src) {
- // Lex file
- var nodes = kramed.lexer(src);
-
- return _.chain(splitSections(nodes))
- .map(function(section, idx) {
- // Detect section type
- section.type = sectionType(section, idx);
- return section;
- })
- .map(function(section, idx) {
- // Give each section an ID
- section.id = sectionId(section, idx);
- return section;
-
- })
- .filter(function(section) {
- return !_.isEmpty(section);
- })
- .reduce(function(sections, section) {
- var last = _.last(sections);
-
- // Merge normal sections together
- if(last && last.type === section.type && last.type === 'normal') {
- last.push.apply(last, [{'type': 'hr'}].concat(section));
- } else {
- // Add to list of sections
- sections.push(section);
- }
-
- return sections;
- }, [])
- .map(function(section) {
- section.links = nodes.links;
- return section;
- })
- .value();
-}
-
-// Exports
-module.exports = lexPage;
diff --git a/lib/parse/navigation.js b/lib/parse/navigation.js
deleted file mode 100644
index ae4eb9d..0000000
--- a/lib/parse/navigation.js
+++ /dev/null
@@ -1,64 +0,0 @@
-var _ = require('lodash');
-
-// Cleans up an article/chapter object
-// remove 'articles' attributes
-function clean(obj) {
- return obj && _.omit(obj, ['articles']);
-}
-
-function flattenChapters(chapters) {
- return _.reduce(chapters, function(accu, chapter) {
- return accu.concat([clean(chapter)].concat(flattenChapters(chapter.articles)));
- }, []);
-}
-
-// Returns from a summary a map of
-/*
- {
- "file/path.md": {
- prev: ...,
- next: ...,
- },
- ...
- }
-*/
-function navigation(summary, files) {
- // Support single files as well as list
- files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
-
- // List of all navNodes
- // Flatten chapters, then add in default README node if ndeeded etc ...
- var navNodes = flattenChapters(summary.chapters);
- var prevNodes = [null].concat(navNodes.slice(0, -1));
- var nextNodes = navNodes.slice(1).concat([null]);
-
- // Mapping of prev/next for a give path
- var mapping = _.chain(_.zip(navNodes, prevNodes, nextNodes))
- .map(function(nodes) {
- var current = nodes[0], prev = nodes[1], next = nodes[2];
-
- // Skip if no path
- if(!current.path) return null;
-
- return [current.path, {
- title: current.title,
- prev: prev,
- next: next,
- level: current.level,
- }];
- })
- .filter()
- .object()
- .value();
-
- // Filter for only files we want
- if(files) {
- return _.pick(mapping, files);
- }
-
- return mapping;
-}
-
-
-// Exports
-module.exports = navigation;
diff --git a/lib/parse/page.js b/lib/parse/page.js
deleted file mode 100644
index 5fb2081..0000000
--- a/lib/parse/page.js
+++ /dev/null
@@ -1,160 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-var hljs = require('highlight.js');
-
-var lex = require('./lex');
-var renderer = require('./renderer');
-
-var include = require('./include');
-var lnormalize = require('../utils/lang').normalize;
-
-
-
-// Render a section using our custom renderer
-function render(section, _options) {
- // Copy section
- var links = section.links || {};
- section = _.toArray(section);
- section.links = links;
-
- // Build options using defaults and our custom renderer
- var options = _.extend({}, kramed.defaults, {
- renderer: renderer(null, _options),
-
- // Synchronous highlighting with highlight.js
- highlight: function (code, lang) {
- if(!lang) return code;
-
- // Normalize lang
- lang = lnormalize(lang);
-
- try {
- return hljs.highlight(lang, code).value;
- } catch(e) { }
-
- return code;
- }
- });
-
- return kramed.parser(section, options);
-}
-
-function quizQuestion(node) {
- if (node.text) {
- node.text = node.text.replace(/^([\[(])x([\])])/, "$1 $2");
- } else {
- return node.replace(/^([\[(])x([\])])/, "$1 $2");
- }
-}
-
-function parsePage(src, options) {
- options = options || {};
-
- // Lex if not already lexed
- var parsed = {
- lexed: (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
- };
- parsed.sections = parsed.lexed.map(function(section) {
- // Transform given type
- if(section.type === 'exercise') {
- var nonCodeNodes = _.reject(section, {
- 'type': 'code'
- });
-
- var codeNodes = _.filter(section, {
- 'type': 'code'
- });
-
- // Languages in code blocks
- var langs = _.pluck(codeNodes, 'lang').map(lnormalize);
-
- // Check that they are all the same
- var validLangs = _.all(_.map(langs, function(lang) {
- return lang && lang === langs[0];
- }));
-
- // Main language
- var lang = validLangs ? langs[0] : null;
-
- return {
- id: section.id,
- type: section.type,
- content: render(nonCodeNodes, options),
- lang: lang,
- code: {
- base: codeNodes[0].text,
- solution: codeNodes[1].text,
- validation: codeNodes[2].text,
- // Context is optional
- context: codeNodes[3] ? codeNodes[3].text : null,
- }
- };
- } else if (section.type === 'quiz') {
- var quiz = [], question, foundFeedback = false;
- var nonQuizNodes = section[0].type === 'paragraph' && section[1].type !== 'list_start' ? [section[0]] : [];
- var quizNodes = section.slice(0);
- quizNodes.splice(0, nonQuizNodes.length);
-
- for (var i = 0; i < quizNodes.length; i++) {
- var node = quizNodes[i];
-
- if (question && (((node.type === 'list_end' || node.type === 'blockquote_end') && i === quizNodes.length - 1)
- || node.type === 'table' || (node.type === 'paragraph' && !foundFeedback))) {
- quiz.push({
- base: render(question.questionNodes, options),
- solution: render(question.solutionNodes, options),
- feedback: render(question.feedbackNodes, options)
- });
- }
-
- if (node.type === 'table' || (node.type === 'paragraph' && !foundFeedback)) {
- question = { questionNodes: [], solutionNodes: [], feedbackNodes: [] };
- }
-
- if (node.type === 'blockquote_start') {
- foundFeedback = true;
- } else if (node.type === 'blockquote_end') {
- foundFeedback = false;
- }
-
- if (node.type === 'table') {
- question.solutionNodes.push(_.cloneDeep(node));
- node.cells = node.cells.map(function(row) {
- return row.map(quizQuestion);
- });
- question.questionNodes.push(node);
- } else if (!/blockquote/.test(node.type)) {
- if (foundFeedback) {
- question.feedbackNodes.push(node);
- } else if (node.type === 'paragraph' || node.type === 'text'){
- question.solutionNodes.push(_.cloneDeep(node));
- quizQuestion(node);
- question.questionNodes.push(node);
- } else {
- question.solutionNodes.push(node);
- question.questionNodes.push(node);
- }
- }
- }
-
- return {
- id: section.id,
- type: section.type,
- content: render(nonQuizNodes, options),
- quiz: quiz
- };
- }
-
- // Render normal pages
- return {
- id: section.id,
- type: section.type,
- content: render(section, options)
- };
- });
-
- return parsed;
-}
-
-// Exports
-module.exports = parsePage;
diff --git a/lib/parse/progress.js b/lib/parse/progress.js
deleted file mode 100644
index 10a06d2..0000000
--- a/lib/parse/progress.js
+++ /dev/null
@@ -1,47 +0,0 @@
-var _ = require("lodash");
-
-// Returns from a navigation and a current file, a snapshot of current detailed state
-var calculProgress = function(navigation, current) {
- var n = _.size(navigation);
- var percent = 0, prevPercent = 0, currentChapter = null;
- var done = true;
-
- var chapters = _.chain(navigation)
- .map(function(nav, path) {
- nav.path = path;
- return nav;
- })
- .map(function(nav, i) {
- // Calcul percent
- nav.percent = (i * 100) / Math.max((n - 1), 1);
-
- // Is it done
- nav.done = done;
- if (nav.path == current) {
- currentChapter = nav;
- percent = nav.percent;
- done = false;
- } else if (done) {
- prevPercent = nav.percent;
- }
-
- return nav;
- })
- .value();
-
- return {
- // Previous percent
- prevPercent: prevPercent,
-
- // Current percent
- percent: percent,
-
- // List of chapter with progress
- chapters: chapters,
-
- // Current chapter
- current: currentChapter
- };
-}
-
-module.exports = calculProgress; \ No newline at end of file
diff --git a/lib/parse/readme.js b/lib/parse/readme.js
deleted file mode 100644
index 9d8f552..0000000
--- a/lib/parse/readme.js
+++ /dev/null
@@ -1,45 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-var textRenderer = require('kramed-text-renderer');
-
-function extractFirstNode(nodes, nType) {
- return _.chain(nodes)
- .filter(function(node) {
- return node.type == nType;
- })
- .pluck("text")
- .first()
- .value();
-}
-
-
-function parseReadme(src) {
- var nodes, title, description;
- var renderer = textRenderer();
-
- // Parse content
- nodes = kramed.lexer(src);
-
- title = extractFirstNode(nodes, "heading") || '';
- description = extractFirstNode(nodes, "paragraph") || '';
-
- var convert = _.compose(
- function(text) {
- return _.unescape(text.replace(/(\r\n|\n|\r)/gm, ""));
- },
- function(text) {
- return kramed.parse(text, _.extend({}, kramed.defaults, {
- renderer: renderer
- }));
- }
- );
-
- return {
- title: convert(title),
- description: convert(description)
- };
-}
-
-
-// Exports
-module.exports = parseReadme;
diff --git a/lib/parse/renderer.js b/lib/parse/renderer.js
deleted file mode 100644
index 5b6a79d..0000000
--- a/lib/parse/renderer.js
+++ /dev/null
@@ -1,141 +0,0 @@
-var url = require('url');
-var _ = require('lodash');
-var inherits = require('util').inherits;
-var links = require('../utils').links;
-var kramed = require('kramed');
-
-var rendererId = 0;
-
-function GitBookRenderer(options, extra_options) {
- if(!(this instanceof GitBookRenderer)) {
- return new GitBookRenderer(options, extra_options);
- }
- GitBookRenderer.super_.call(this, options);
-
- this._extra_options = extra_options;
- this.quizRowId = 0;
- this.id = rendererId++;
- this.quizIndex = 0;
-}
-inherits(GitBookRenderer, kramed.Renderer);
-
-GitBookRenderer.prototype._unsanitized = function(href) {
- var prot = '';
- try {
- prot = decodeURIComponent(unescape(href))
- .replace(/[^\w:]/g, '')
- .toLowerCase();
-
- } catch (e) {
- return true;
- }
-
- if(prot.indexOf('javascript:') === 0) {
- return true;
- }
-
- return false;
-};
-
-GitBookRenderer.prototype.link = function(href, title, text) {
- // Our "fixed" href
- var _href = href;
-
- // Don't build if it looks malicious
- if (this.options.sanitize && this._unsanitized(href)) {
- return text;
- }
-
- // Parsed version of the url
- var parsed = url.parse(href);
- var o = this._extra_options;
- var extname = parsed.path? _.last(parsed.path.split(".")) : "";
-
- // Relative link, rewrite it to point to github repo
- if(links.isRelative(_href) && extname == "md") {
- _href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
- _href = _href.replace(".md", ".html");
- }
-
- // Generate HTML for link
- var out = '<a href="' + _href + '"';
- // Title if no null
- if (title) {
- out += ' title="' + title + '"';
- }
- // Target blank if external
- if(parsed.protocol) {
- out += ' target="_blank"';
- }
- out += '>' + text + '</a>';
- return out;
-};
-
-GitBookRenderer.prototype.image = function(href, title, text) {
- // Our "fixed" href
- var _href = href;
-
- // Parsed version of the url
- var parsed = url.parse(href);
-
- // Options
- var o = this._extra_options;
-
- // Relative image, rewrite it depending output
- if(links.isRelative(href) && o && o.dir && o.outdir) {
- // o.dir: directory parent of the file currently in rendering process
- // o.outdir: directory parent from the html output
-
- _href = links.toAbsolute(_href, o.dir, o.outdir);
- }
-
- return GitBookRenderer.super_.prototype.image.call(this, _href, title, text);
-};
-
-GitBookRenderer.prototype.tablerow = function(content) {
- this.quizRowId += 1;
- return GitBookRenderer.super_.prototype.tablerow(content);
-};
-
-var fieldRegex = /^([(\[])([ x])[\])]/;
-GitBookRenderer.prototype._createCheckboxAndRadios = function(text) {
- var match = fieldRegex.exec(text);
- if (!match) {
- return text;
- }
- //fix radio input uncheck failed
- var quizFieldName='quiz-row-' + this.id + '-' + this.quizRowId ;
- var quizIdentifier = quizFieldName + '-' + this.quizIndex++;
- var field = "<input name='" + quizFieldName + "' id='" + quizIdentifier + "' type='";
- field += match[1] === '(' ? "radio" : "checkbox";
- field += match[2] === 'x' ? "' checked/>" : "'/>";
- var splittedText = text.split(fieldRegex);
- var length = splittedText.length;
- var label = '<label class="quiz-label" for="' + quizIdentifier + '">' + splittedText[length - 1] + '</label>';
- return text.replace(fieldRegex, field).replace(splittedText[length - 1], label);
-};
-
-GitBookRenderer.prototype.tablecell = function(content, flags) {
- return GitBookRenderer.super_.prototype.tablecell(this._createCheckboxAndRadios(content), flags);
-};
-
-GitBookRenderer.prototype.listitem = function(text) {
- return GitBookRenderer.super_.prototype.listitem(this._createCheckboxAndRadios(text));
-};
-
-GitBookRenderer.prototype.code = function(code, lang, escaped) {
- return GitBookRenderer.super_.prototype.code.call(
- this,
- code,
- lang,
- escaped
- );
-};
-
-GitBookRenderer.prototype.heading = function(text, level, raw) {
- var id = this.options.headerPrefix + raw.toLowerCase().replace(/[^\w -]+/g, '').replace(/ /g, '-');
- return '<h' + level + ' id="' + id + '">' + text + '</h' + level + '>\n';
-};
-
-// Exports
-module.exports = GitBookRenderer;
diff --git a/lib/parse/summary.js b/lib/parse/summary.js
deleted file mode 100644
index 2fdec8a..0000000
--- a/lib/parse/summary.js
+++ /dev/null
@@ -1,167 +0,0 @@
-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);
-}
-
-function skipSpace(nodes) {
- return _.filter(nodes, function(node) {
- return node && node.type != 'space';
- });
-}
-
-function correctLoose(nodes) {
- return _.map(nodes, function(node) {
- // Return normal nodes
- if(!node || node.type != 'loose_item_start') {
- return node
- }
-
- // Correct loose items
- node.type = 'list_item_start';
-
- return node;
- })
-}
-
-// 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(correctLoose(skipSpace(nodes))),
- 'list_item_start', 'list_item_end'
- );
-}
-
-function parseSummary(src) {
- // Split out chapter sections
- var chapters = defaultChapterList(listGroups(src));
-
- return {
- chapters: chapters.map(parseChapter)
- };
-}
-
-function parseEntries (src) {
- return listGroups(src).map(parseChapter);
-}
-
-
-// Exports
-module.exports = parseSummary;
-module.exports.entries = parseEntries;