diff options
Diffstat (limited to 'lib/backbone')
-rw-r--r-- | lib/backbone/file.js | 69 | ||||
-rw-r--r-- | lib/backbone/glossary.js | 99 | ||||
-rw-r--r-- | lib/backbone/index.js | 8 | ||||
-rw-r--r-- | lib/backbone/langs.js | 81 | ||||
-rw-r--r-- | lib/backbone/readme.js | 44 | ||||
-rw-r--r-- | lib/backbone/summary.js | 349 |
6 files changed, 0 insertions, 650 deletions
diff --git a/lib/backbone/file.js b/lib/backbone/file.js deleted file mode 100644 index 209e261..0000000 --- a/lib/backbone/file.js +++ /dev/null @@ -1,69 +0,0 @@ -var _ = require('lodash'); - -function BackboneFile(book) { - if (!(this instanceof BackboneFile)) return new BackboneFile(book); - - this.book = book; - this.log = this.book.log; - - // Filename in the book - this.path = ''; - this.parser; - - _.bindAll(this); -} - -// Type of the backbone file -BackboneFile.prototype.type = ''; - -// Parse a backbone file -BackboneFile.prototype.parse = function() { - // To be implemented by each child -}; - -// Handle case where file doesn't exists -BackboneFile.prototype.parseNotFound = function() { - -}; - -// Return true if backbone file exists -BackboneFile.prototype.exists = function() { - return Boolean(this.path); -}; - -// Locate a backbone file, could be .md, .asciidoc, etc -BackboneFile.prototype.locate = function() { - var that = this; - var filename = this.book.config.getStructure(this.type, true); - this.log.debug.ln('locating', this.type, ':', filename); - - return this.book.findParsableFile(filename) - .then(function(result) { - if (!result) return; - - that.path = result.path; - that.parser = result.parser; - }); -}; - -// Read and parse the file -BackboneFile.prototype.load = function() { - var that = this; - this.log.debug.ln('loading', this.type, ':', that.path); - - return this.locate() - .then(function() { - if (!that.path) return that.parseNotFound(); - - that.log.debug.ln(that.type, 'located at', that.path); - - return that.book.readFile(that.path) - - // Parse it - .then(function(content) { - return that.parse(content); - }); - }); -}; - -module.exports = BackboneFile; diff --git a/lib/backbone/glossary.js b/lib/backbone/glossary.js deleted file mode 100644 index cc0fdce..0000000 --- a/lib/backbone/glossary.js +++ /dev/null @@ -1,99 +0,0 @@ -var _ = require('lodash'); -var util = require('util'); -var BackboneFile = require('./file'); - -// Normalize a glossary entry name into a unique id -function nameToId(name) { - return name.toLowerCase() - .replace(/[\/\\\?\%\*\:\;\|\"\'\\<\\>\#\$\(\)\!\.\@]/g, '') - .replace(/ /g, '_') - .trim(); -} - - -/* -A glossary entry is represented by a name and a short description -An unique id for the entry is generated using its name -*/ -function GlossaryEntry(name, description) { - if (!(this instanceof GlossaryEntry)) return new GlossaryEntry(name, description); - - this.name = name; - this.description = description; - - Object.defineProperty(this, 'id', { - get: _.bind(this.getId, this) - }); -} - -// Normalizes a glossary entry's name to create an ID -GlossaryEntry.prototype.getId = function() { - return nameToId(this.name); -}; - - -/* -A glossary is a list of entries stored in a GLOSSARY.md file -*/ -function Glossary() { - BackboneFile.apply(this, arguments); - - this.entries = []; -} -util.inherits(Glossary, BackboneFile); - -Glossary.prototype.type = 'glossary'; - -// Get templating context -Glossary.prototype.getContext = function() { - if (!this.path) return {}; - - return { - glossary: { - path: this.path - } - }; -}; - -// Parse the readme content -Glossary.prototype.parse = function(content) { - var that = this; - - return this.parser.glossary(content) - .then(function(entries) { - that.entries = _.map(entries, function(entry) { - return new GlossaryEntry(entry.name, entry.description); - }); - }); -}; - -// Return an entry by its id -Glossary.prototype.get = function(id) { - return _.find(this.entries, { - id: id - }); -}; - -// Find an entry by its name -Glossary.prototype.find = function(name) { - return this.get(nameToId(name)); -}; - -// Return false if glossary has entries (and exists) -Glossary.prototype.isEmpty = function(id) { - return _.size(this.entries) === 0; -}; - -// Convert the glossary to a list of annotations -Glossary.prototype.annotations = function() { - return _.map(this.entries, function(entry) { - return { - id: entry.id, - name: entry.name, - description: entry.description, - href: '/' + this.path + '#' + entry.id - }; - }, this); -}; - -module.exports = Glossary; diff --git a/lib/backbone/index.js b/lib/backbone/index.js deleted file mode 100644 index 4c3c3f3..0000000 --- a/lib/backbone/index.js +++ /dev/null @@ -1,8 +0,0 @@ - -module.exports = { - Readme: require('./readme'), - Summary: require('./summary'), - Glossary: require('./glossary'), - Langs: require('./langs') -}; - diff --git a/lib/backbone/langs.js b/lib/backbone/langs.js deleted file mode 100644 index e339fa9..0000000 --- a/lib/backbone/langs.js +++ /dev/null @@ -1,81 +0,0 @@ -var _ = require('lodash'); -var path = require('path'); -var util = require('util'); -var BackboneFile = require('./file'); - -function Language(title, folder) { - var that = this; - - this.title = title; - this.folder = folder; - - Object.defineProperty(this, 'id', { - get: function() { - return path.basename(that.folder); - } - }); -} - -/* -A Langs is a list of languages stored in a LANGS.md file -*/ -function Langs() { - BackboneFile.apply(this, arguments); - - this.languages = []; -} -util.inherits(Langs, BackboneFile); - -Langs.prototype.type = 'langs'; - -// Parse the readme content -Langs.prototype.parse = function(content) { - var that = this; - - return this.parser.langs(content) - .then(function(langs) { - that.languages = _.map(langs, function(entry) { - return new Language(entry.title, entry.path); - }); - }); -}; - -// Return the list of languages -Langs.prototype.list = function() { - return this.languages; -}; - -// Return default/main language for the book -Langs.prototype.getDefault = function() { - return _.first(this.languages); -}; - -// Return true if a language is the default one -// "lang" cam be a string (id) or a Language entry -Langs.prototype.isDefault = function(lang) { - lang = lang.id || lang; - return (this.cound() > 0 && this.getDefault().id == lang); -}; - -// Return the count of languages -Langs.prototype.count = function() { - return _.size(this.languages); -}; - -// Return templating context for the languages list -Langs.prototype.getContext = function() { - if (this.count() == 0) return {}; - - return { - languages: { - list: _.map(this.languages, function(lang) { - return { - id: lang.id, - title: lang.title - }; - }) - } - }; -}; - -module.exports = Langs; diff --git a/lib/backbone/readme.js b/lib/backbone/readme.js deleted file mode 100644 index 088a942..0000000 --- a/lib/backbone/readme.js +++ /dev/null @@ -1,44 +0,0 @@ -var util = require('util'); -var BackboneFile = require('./file'); - -function Readme() { - BackboneFile.apply(this, arguments); - - this.title; - this.description; -} -util.inherits(Readme, BackboneFile); - -Readme.prototype.type = 'readme'; - -/* - Return and extension of context to define the readme - - @retrun {Object} -*/ -Readme.prototype.getContext = function() { - return { - readme: { - path: this.path - } - }; -}; - -/* - Parse the readme content - - @param {String} content - @retrun {Promise} -*/ -Readme.prototype.parse = function(content) { - var that = this; - - return this.parser.readme(content) - .then(function(out) { - that.title = out.title; - that.description = out.description; - }); -}; - - -module.exports = Readme; diff --git a/lib/backbone/summary.js b/lib/backbone/summary.js deleted file mode 100644 index 2dbcecb..0000000 --- a/lib/backbone/summary.js +++ /dev/null @@ -1,349 +0,0 @@ -var _ = require('lodash'); -var util = require('util'); - -var location = require('../utils/location'); -var error = require('../utils/error'); -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) -*/ -function TOCArticle(def, parent) { - // Title - this.title = def.title; - - // Parent TOCPart or TOCArticle - this.parent = parent; - - // As string indicating the overall position - // ex: '1.0.0' - this.level; - this._next; - this._prev; - - // When README has been automatically added - this.isAutoIntro = def.isAutoIntro; - this.isIntroduction = def.isIntroduction; - - this.validate(); - - // Path can be a relative path or an url, or nothing - this.ref = def.path; - if (this.ref && !this.isExternal()) { - var parts = this.ref.split('#'); - this.path = (parts.length > 1? parts.slice(0, -1).join('#') : this.ref); - this.anchor = (parts.length > 1? '#' + _.last(parts) : null); - - // Normalize path to remove ('./', etc) - this.path = location.normalize(this.path); - } - - this.articles = _.map(def.articles || [], function(article) { - if (article instanceof TOCArticle) return article; - return new TOCArticle(article, this); - }, 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; - - _.each(this.articles, function(article, i) { - var level = levelId(base, i); - - if (iter(article, level) === false) { - return false; - } - article.walk(iter, level); - }); -}; - -// Return templating context for an article -TOCArticle.prototype.getContext = function() { - return { - level: this.level, - title: this.title, - depth: this.depth(), - path: this.isExternal()? undefined : this.path, - anchor: this.isExternal()? undefined : this.anchor, - url: this.isExternal()? this.ref : undefined - }; -}; - -// Return true if is pointing to a file -TOCArticle.prototype.hasLocation = function() { - return Boolean(this.path); -}; - -// Return true if is pointing to an external location -TOCArticle.prototype.isExternal = function() { - return location.isExternal(this.ref); -}; - -// Return true if this article is the introduction -TOCArticle.prototype.isIntro = function() { - return Boolean(this.isIntroduction); -}; - -// Return true if has children -TOCArticle.prototype.hasChildren = function() { - return this.articles.length > 0; -}; - -// Return true if has an article as parent -TOCArticle.prototype.hasParent = function() { - return !(this.parent instanceof TOCPart); -}; - -// Return depth of this article -TOCArticle.prototype.depth = function() { - return this.level.split('.').length; -}; - -// Return next article in the TOC -TOCArticle.prototype.next = function() { - return this._next; -}; - -// Return previous article in the TOC -TOCArticle.prototype.prev = function() { - return this._prev; -}; - -// Map over all articles -TOCArticle.prototype.map = function(iter) { - return _.map(this.articles, iter); -}; - - -/* - A part of a ToC is a composed of a tree of articles and an optiona title -*/ -function TOCPart(part, parent) { - if (!(this instanceof TOCPart)) return new TOCPart(part, parent); - - TOCArticle.apply(this, arguments); -} -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.parent.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) { - var articles = this.articles; - - if (articles.length == 0) return; - - // Has introduction? - if (articles[0].isIntro()) { - if (iter(articles[0], '0') === false) { - return; - } - - articles = articles.slice(1); - } - - - _.each(articles, function(article, i) { - var level = levelId(base, i); - - if (iter(article, level) === false) { - return false; - } - - article.walk(iter, level); - }); -}; - -// 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) - }; -}; - -/* -A summary is composed of a list of parts, each composed wit a tree of articles. -*/ -function Summary() { - BackboneFile.apply(this, arguments); - - this.parts = []; - this._length = 0; -} -util.inherits(Summary, BackboneFile); - -Summary.prototype.type = 'summary'; - -// Prepare summary when non existant -Summary.prototype.parseNotFound = function() { - this.update([]); -}; - -// Parse the summary content -Summary.prototype.parse = function(content) { - var that = this; - - return this.parser.summary(content) - - .then(function(summary) { - that.update(summary.parts); - }); -}; - -// Return templating context for the summary -Summary.prototype.getContext = function() { - function onArticle(article) { - var result = article.getContext(); - if (article.hasChildren()) { - result.articles = article.map(onArticle); - } - - return result; - } - - return { - summary: { - path: this.path, - parts: _.map(this.parts, function(part) { - return part.getContext(onArticle); - }) - } - }; -}; - -// Iterate over all entries of the summary -// iter is called with an TOCArticle -Summary.prototype.walk = function(iter) { - var hasMultipleParts = this.parts.length > 1; - - _.each(this.parts, function(part, i) { - part.walk(iter, hasMultipleParts? levelId('', i) : null); - }); -}; - -// Find a specific article using a filter -Summary.prototype.find = function(filter) { - var result; - - this.walk(function(article) { - if (filter(article)) { - result = article; - return false; - } - }); - - return result; -}; - -// Flatten the list of articles -Summary.prototype.flatten = function() { - var result = []; - - this.walk(function(article) { - result.push(article); - }); - - return result; -}; - -// Return the first TOCArticle for a specific page (or path) -Summary.prototype.getArticle = function(page) { - if (!_.isString(page)) page = page.path; - - return this.find(function(article) { - return article.path == page; - }); -}; - -// Return the first TOCArticle for a specific level -Summary.prototype.getArticleByLevel = function(lvl) { - return this.find(function(article) { - return article.level == lvl; - }); -}; - -// Return the count of articles in the summary -Summary.prototype.count = function() { - return this._length; -}; - -// Prepare the summary -Summary.prototype.update = function(parts) { - var that = this; - - - that.parts = _.map(parts, function(part) { - return new TOCPart(part, that); - }); - - // Create first part if none - if (that.parts.length == 0) { - that.parts.push(new TOCPart({}, that)); - } - - // Add README as first entry - var firstArticle = that.parts[0].articles[0]; - if (!firstArticle || firstArticle.path != that.book.readme.path) { - that.parts[0].articles.unshift(new TOCArticle({ - title: 'Introduction', - path: that.book.readme.path, - isAutoIntro: true - }, that.parts[0])); - } - that.parts[0].articles[0].isIntroduction = true; - - - // Update the count and indexing of "level" - var prev = undefined; - - that._length = 0; - that.walk(function(article, level) { - // Index level - article.level = level; - - // Chain articles - article._prev = prev; - if (prev) prev._next = article; - - prev = article; - - that._length += 1; - }); -}; - - -// Return a level string from a base level and an index -function levelId(base, i) { - i = i + 1; - return (base? [base || '', i] : [i]).join('.'); -} - -module.exports = Summary; |