summaryrefslogtreecommitdiffstats
path: root/lib/backbone/summary.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/backbone/summary.js')
-rw-r--r--lib/backbone/summary.js119
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);
})
}
};