diff options
Diffstat (limited to 'lib/backbone/summary.js')
-rw-r--r-- | lib/backbone/summary.js | 119 |
1 files changed, 89 insertions, 30 deletions
diff --git a/lib/backbone/summary.js b/lib/backbone/summary.js index f3994ca..5cc1418 100644 --- a/lib/backbone/summary.js +++ b/lib/backbone/summary.js @@ -8,8 +8,9 @@ var BackboneFile = require('./file'); /* -An article represent an entry in the Summary. -It's defined by a title, a reference, and children articles, the reference (ref) can be a filename + anchor or an external file (optional) + An article represent an entry in the Summary. + It's defined by a title, a reference, and children articles, + the reference (ref) can be a filename + anchor or an external file (optional) */ function TOCArticle(def, parent) { // Title @@ -26,16 +27,17 @@ function TOCArticle(def, parent) { this.isAutoIntro = def.isAutoIntro; this.isIntroduction = def.isIntroduction; - if (!def.title) { - throw error.ParsingError(new Error('SUMMARY entries should have an non-empty title')); - } + this.validate(); - var parts = url.parse(def.path); + // Path can be a relative path or an url, or nothing this.ref = def.path; + if (this.ref) { + var parts = url.parse(this.ref); - if (!this.isExternal()) { - this.path = parts.pathname; - this.anchor = parts.hash; + if (!this.isExternal()) { + this.path = parts.pathname; + this.anchor = parts.hash; + } } this.articles = _.map(def.articles || [], function(article) { @@ -44,6 +46,13 @@ function TOCArticle(def, parent) { }, this); } +// Validate the article +TOCArticle.prototype.validate = function() { + if (!this.title) { + throw error.ParsingError(new Error('SUMMARY entries should have an non-empty title')); + } +}; + // Iterate over all articles in this articles TOCArticle.prototype.walk = function(iter, base) { base = base || this.level; @@ -91,11 +100,29 @@ TOCArticle.prototype.hasChildren = function() { // Return true if has an article as parent TOCArticle.prototype.hasParent = function() { - return (this.parent instanceof TOCArticle); + return !(this.parent instanceof TOCPart); +}; + +// Return true if has a part as parent +TOCArticle.prototype.hasParentPart = function() { + return (this.parent instanceof TOCPart); +}; + +// Return first article +TOCArticle.prototype.first = function() { + return _.first(this.articles); +}; + +// Return last article +TOCArticle.prototype.last = function() { + var last = _.last(this.articles); + if (!last) return null; + + return last.last() || last; }; // Return a sibling (next or prev) in the parent -// Withotu taking in consideration children/parent +// Without taking in consideration children/parent TOCArticle.prototype.sibling = function(direction) { var parentsArticles = this.parent.articles; var pos = _.findIndex(parentsArticles, this); @@ -115,17 +142,28 @@ TOCArticle.prototype._sibling = function(direction) { return _.first(this.articles); } + var part; var parentsArticles = this.parent.articles; var pos = _.findIndex(parentsArticles, this); // First child and has parent - if (pos == 0 && direction < 0 && this.hasParent()) { - return this.parent; + if (pos == 0 && direction < 0) { + if (this.hasParent()) { + return this.parent; + } else if (this.hasParentPart()) { + part = this.parent.sibling(-1); + return part? part.last() : null; + } } // Last child and has parent - if(pos == (parentsArticles.length - 1) && direction > 0 && this.hasParent()) { - return this.parent.sibling(1); + if(pos == (parentsArticles.length - 1) && direction > 0) { + if (this.hasParent()) { + return this.parent.sibling(1); + } else if (this.hasParentPart()) { + part = this.parent.sibling(1); + return part? part.first() : null; + } } if (parentsArticles[pos + direction]) { @@ -159,16 +197,31 @@ TOCArticle.prototype.map = function(iter) { /* -A part of a ToC is a composed of a tree of articles. + A part of a ToC is a composed of a tree of articles and an optiona title */ -function TOCPart(part) { +function TOCPart(part, summary) { if (!(this instanceof TOCPart)) return new TOCPart(part); - this.title = part.title; - this.articles = _.map(part.articles || part.chapters, function(article) { - return new TOCArticle(article, this); - }, this); + TOCArticle.apply(this, arguments); + + this.summary = summary; } +util.inherits(TOCPart, TOCArticle); + +// Validate the part +TOCPart.prototype.validate = function() { }; + +// Return a sibling (next or prev) of this part +TOCPart.prototype.sibling = function(direction) { + var parts = this.summary.parts; + var pos = _.findIndex(parts, this); + + if (parts[pos + direction]) { + return parts[pos + direction]; + } + + return null; +}; // Iterate over all entries of the part TOCPart.prototype.walk = function(iter, base) { @@ -197,9 +250,16 @@ TOCPart.prototype.walk = function(iter, base) { }); }; -// Map over all articles -TOCPart.prototype.map = function(iter) { - return _.map(this.articles, iter); +// Return templating context for a part +TOCPart.prototype.getContext = function(onArticle) { + onArticle = onArticle || function(article) { + return article.getContext(); + }; + + return { + title: this.title, + articles: this.map(onArticle) + }; }; /* @@ -222,11 +282,13 @@ Summary.prototype.parse = function(content) { return this.parser.summary(content) .then(function(summary) { - that.parts = _.map(summary.parts, TOCPart); + that.parts = _.map(summary.parts, function(part) { + return new TOCPart(part, that); + }); // Create first part if none if (that.parts.length == 0) { - that.parts.push(new TOCPart({})); + that.parts.push(new TOCPart({}, that)); } // Add README as first entry @@ -259,10 +321,7 @@ Summary.prototype.getContext = function() { return { summary: { parts: _.map(this.parts, function(part) { - return { - title: part.title, - articles: part.map(onArticle) - }; + return part.getContext(onArticle); }) } }; |