diff options
Diffstat (limited to 'packages/gitbook')
18 files changed, 333 insertions, 243 deletions
diff --git a/packages/gitbook/src/json/encodeBook.js b/packages/gitbook/src/json/encodeBook.js index 0b259a9..c5632d2 100644 --- a/packages/gitbook/src/json/encodeBook.js +++ b/packages/gitbook/src/json/encodeBook.js @@ -7,11 +7,11 @@ const encodeReadme = require('./encodeReadme'); const encodeLanguages = require('./encodeLanguages'); /** - Encode a book to JSON - - @param {Book} - @return {Object} -*/ + * Encode a book to JSON + * + * @param {Book} + * @return {Object} + */ function encodeBookToJson(book) { const config = book.getConfig(); const language = book.getLanguage(); diff --git a/packages/gitbook/src/json/encodeReadme.js b/packages/gitbook/src/json/encodeReadme.js index cc71bcb..5fe5a63 100644 --- a/packages/gitbook/src/json/encodeReadme.js +++ b/packages/gitbook/src/json/encodeReadme.js @@ -1,11 +1,11 @@ const encodeFile = require('./encodeFile'); /** - Encode a readme to JSON - - @param {Readme} - @return {Object} -*/ + * Encode a readme to JSON + * + * @param {Readme} + * @return {Object} + */ function encodeReadme(readme) { const file = readme.getFile(); diff --git a/packages/gitbook/src/json/encodeSummary.js b/packages/gitbook/src/json/encodeSummary.js index 9a07da4..0a9dbe7 100644 --- a/packages/gitbook/src/json/encodeSummary.js +++ b/packages/gitbook/src/json/encodeSummary.js @@ -2,11 +2,11 @@ const encodeFile = require('./encodeFile'); const encodeSummaryPart = require('./encodeSummaryPart'); /** - Encode a summary to JSON - - @param {Summary} - @return {Object} -*/ + * Encode a summary to JSON + * + * @param {Summary} + * @return {Object} + */ function encodeSummary(summary) { const file = summary.getFile(); const parts = summary.getParts(); diff --git a/packages/gitbook/src/json/encodeSummaryArticle.js b/packages/gitbook/src/json/encodeSummaryArticle.js index 0b9461c..b6d7d9f 100644 --- a/packages/gitbook/src/json/encodeSummaryArticle.js +++ b/packages/gitbook/src/json/encodeSummaryArticle.js @@ -1,10 +1,10 @@ /** - Encode a SummaryArticle to JSON - - @param {SummaryArticle} - @return {Object} -*/ + * Encode a SummaryArticle to JSON + * + * @param {SummaryArticle} + * @return {Object} + */ function encodeSummaryArticle(article, recursive) { let articles = undefined; if (recursive !== false) { @@ -14,13 +14,13 @@ function encodeSummaryArticle(article, recursive) { } return { - title: article.getTitle(), - level: article.getLevel(), - depth: article.getDepth(), + title: article.getTitle(), + level: article.getLevel(), + depth: article.getDepth(), anchor: article.getAnchor(), - url: article.getUrl(), - path: article.getPath(), - ref: article.getRef(), + url: article.getUrl(), + path: article.getPath(), + ref: article.getRef(), articles }; } diff --git a/packages/gitbook/src/json/encodeSummaryPart.js b/packages/gitbook/src/json/encodeSummaryPart.js index eb16719..9ff3583 100644 --- a/packages/gitbook/src/json/encodeSummaryPart.js +++ b/packages/gitbook/src/json/encodeSummaryPart.js @@ -1,11 +1,11 @@ const encodeSummaryArticle = require('./encodeSummaryArticle'); /** - Encode a SummaryPart to JSON - - @param {SummaryPart} - @return {Object} -*/ + * Encode a SummaryPart to JSON + * + * @param {SummaryPart} + * @return {Object} + */ function encodeSummaryPart(part) { return { title: part.getTitle(), diff --git a/packages/gitbook/src/models/book.js b/packages/gitbook/src/models/book.js index c96843b..4668154 100644 --- a/packages/gitbook/src/models/book.js +++ b/packages/gitbook/src/models/book.js @@ -10,7 +10,6 @@ const Summary = require('./summary'); const Glossary = require('./glossary'); const Languages = require('./languages'); const Ignore = require('./ignore'); -const URIIndex = require('./uriIndex'); const DEFAULTS = { // Logger for output message @@ -25,8 +24,6 @@ const DEFAULTS = { summary: new Summary(), glossary: new Glossary(), languages: new Languages(), - // Index of urls - urls: new URIIndex(), // ID of the language for language books language: String(), // List of children, if multilingual (String -> Book) diff --git a/packages/gitbook/src/models/output.js b/packages/gitbook/src/models/output.js index ae68f4c..e4870ba 100644 --- a/packages/gitbook/src/models/output.js +++ b/packages/gitbook/src/models/output.js @@ -1,107 +1,105 @@ -const Immutable = require('immutable'); +const { Record, OrderedMap, Map, List } = require('immutable'); -const Book = require('./book'); const LocationUtils = require('../utils/location'); +const Book = require('./book'); +const URIIndex = require('./uriIndex'); -const Output = Immutable.Record({ - book: new Book(), - +const DEFAULTS = { + book: new Book(), // Name of the generator being used - generator: String(), - + generator: String(), // Map of plugins to use (String -> Plugin) - plugins: Immutable.OrderedMap(), - + plugins: OrderedMap(), // Map pages to generation (String -> Page) - pages: Immutable.OrderedMap(), - + pages: OrderedMap(), // List assets (String) - assets: Immutable.List(), - + assets: List(), // Option for the generation - options: Immutable.Map(), - + options: Map(), // Internal state for the generation - state: Immutable.Map() -}); - -Output.prototype.getBook = function() { - return this.get('book'); -}; - -Output.prototype.getGenerator = function() { - return this.get('generator'); -}; - -Output.prototype.getPlugins = function() { - return this.get('plugins'); -}; - -Output.prototype.getPages = function() { - return this.get('pages'); -}; - -Output.prototype.getOptions = function() { - return this.get('options'); -}; - -Output.prototype.getAssets = function() { - return this.get('assets'); -}; - -Output.prototype.getState = function() { - return this.get('state'); -}; - -/** - Return a page byt its file path - - @param {String} filePath - @return {Page|undefined} -*/ -Output.prototype.getPage = function(filePath) { - filePath = LocationUtils.normalize(filePath); - - const pages = this.getPages(); - return pages.get(filePath); -}; - -/** - Get root folder for output - - @return {String} -*/ -Output.prototype.getRoot = function() { - return this.getOptions().get('root'); + state: Map(), + // Index of urls + urls: new URIIndex() }; -/** - Update state of output - - @param {Map} newState - @return {Output} -*/ -Output.prototype.setState = function(newState) { - return this.set('state', newState); -}; - -/** - Update options - - @param {Map} newOptions - @return {Output} -*/ -Output.prototype.setOptions = function(newOptions) { - return this.set('options', newOptions); -}; - -/** - Return logegr for this output (same as book) - - @return {Logger} -*/ -Output.prototype.getLogger = function() { - return this.getBook().getLogger(); -}; +class Output extends Record(DEFAULTS) { + getBook() { + return this.get('book'); + } + + getGenerator() { + return this.get('generator'); + } + + getPlugins() { + return this.get('plugins'); + } + + getPages() { + return this.get('pages'); + } + + getOptions() { + return this.get('options'); + } + + getAssets() { + return this.get('assets'); + } + + getState() { + return this.get('state'); + } + + /** + * Return a page byt its file path + * + * @param {String} filePath + * @return {Page|undefined} + */ + getPage(filePath) { + filePath = LocationUtils.normalize(filePath); + + const pages = this.getPages(); + return pages.get(filePath); + } + + /** + * Get root folder for output. + * @return {String} + */ + getRoot() { + return this.getOptions().get('root'); + } + + /** + * Update state of output + * + * @param {Map} newState + * @return {Output} + */ + setState(newState) { + return this.set('state', newState); + } + + /** + * Update options + * + * @param {Map} newOptions + * @return {Output} + */ + setOptions(newOptions) { + return this.set('options', newOptions); + } + + /** + * Return logegr for this output (same as book) + * + * @return {Logger} + */ + getLogger() { + return this.getBook().getLogger(); + } +} module.exports = Output; diff --git a/packages/gitbook/src/models/page.js b/packages/gitbook/src/models/page.js index dd60298..e2ab977 100644 --- a/packages/gitbook/src/models/page.js +++ b/packages/gitbook/src/models/page.js @@ -1,70 +1,69 @@ -const Immutable = require('immutable'); +const { Record, Map } = require('immutable'); const yaml = require('js-yaml'); const File = require('./file'); -const Page = Immutable.Record({ - file: File(), - +const DEFAULTS = { + file: File(), // Attributes extracted from the YAML header - attributes: Immutable.Map(), - + attributes: Map(), // Content of the page - content: String(), - + content: String(), // Direction of the text - dir: String('ltr') -}); - -Page.prototype.getFile = function() { - return this.get('file'); -}; - -Page.prototype.getAttributes = function() { - return this.get('attributes'); + dir: String('ltr') }; -Page.prototype.getContent = function() { - return this.get('content'); -}; +class Page extends Record(DEFAULTS) { + getFile() { + return this.get('file'); + } -Page.prototype.getDir = function() { - return this.get('dir'); -}; + getAttributes() { + return this.get('attributes'); + } -/** - * Return page as text - * @return {String} -*/ -Page.prototype.toText = function() { - const attrs = this.getAttributes(); - const content = this.getContent(); + getContent() { + return this.get('content'); + } - if (attrs.size === 0) { - return content; + getDir() { + return this.get('dir'); } - const frontMatter = '---\n' + yaml.safeDump(attrs.toJS(), { skipInvalid: true }) + '---\n\n'; - return (frontMatter + content); -}; + /** + * Return page as text + * @return {String} + */ + toText() { + const attrs = this.getAttributes(); + const content = this.getContent(); -/** - * Return path of the page - * @return {String} -*/ -Page.prototype.getPath = function() { - return this.getFile().getPath(); -}; + if (attrs.size === 0) { + return content; + } -/** - * Create a page for a file - * @param {File} file - * @return {Page} -*/ -Page.createForFile = function(file) { - return new Page({ - file - }); -}; + const frontMatter = '---\n' + yaml.safeDump(attrs.toJS(), { skipInvalid: true }) + '---\n\n'; + return (frontMatter + content); + } + + /** + * Return path of the page + * @return {String} + */ + getPath() { + return this.getFile().getPath(); + } + + /** + * Create a page for a file + * @param {File} file + * @return {Page} + */ + static createForFile(file) { + return new Page({ + file + }); + } +} module.exports = Page; diff --git a/packages/gitbook/src/output/callHook.js b/packages/gitbook/src/output/callHook.js index 2180102..34c16ab 100644 --- a/packages/gitbook/src/output/callHook.js +++ b/packages/gitbook/src/output/callHook.js @@ -11,14 +11,14 @@ function defaultHandleResult(output, result) { } /** - Call a "global" hook for an output - - @param {String} name - @param {Function(Output) -> Mixed} getArgument - @param {Function(Output, result) -> Output} handleResult - @param {Output} output - @return {Promise<Output>} -*/ + * Call a "global" hook for an output. Hooks are functions exported by plugins. + * + * @param {String} name + * @param {Function(Output) -> Mixed} getArgument + * @param {Function(Output, result) -> Output} handleResult + * @param {Output} output + * @return {Promise<Output>} + */ function callHook(name, getArgument, handleResult, output) { getArgument = getArgument || defaultGetArgument; handleResult = handleResult || defaultHandleResult; diff --git a/packages/gitbook/src/output/callPageHook.js b/packages/gitbook/src/output/callPageHook.js index af249c9..0c7adfa 100644 --- a/packages/gitbook/src/output/callPageHook.js +++ b/packages/gitbook/src/output/callPageHook.js @@ -2,13 +2,13 @@ const Api = require('../api'); const callHook = require('./callHook'); /** - Call a hook for a specific page - - @param {String} name - @param {Output} output - @param {Page} page - @return {Promise<Page>} -*/ + * Call a hook for a specific page. + * + * @param {String} name + * @param {Output} output + * @param {Page} page + * @return {Promise<Page>} + */ function callPageHook(name, output, page) { return callHook( name, diff --git a/packages/gitbook/src/output/createTemplateEngine.js b/packages/gitbook/src/output/createTemplateEngine.js index 03e7d84..93b1c58 100644 --- a/packages/gitbook/src/output/createTemplateEngine.js +++ b/packages/gitbook/src/output/createTemplateEngine.js @@ -8,12 +8,12 @@ const defaultBlocks = require('../constants/defaultBlocks'); const defaultFilters = require('../constants/defaultFilters'); /** - Create template engine for an output. - It adds default filters/blocks, then add the ones from plugins - - @param {Output} output - @return {TemplateEngine} -*/ + * Create template engine for an output. + * It adds default filters/blocks, then add the ones from plugins + * + * @param {Output} output + * @return {TemplateEngine} + */ function createTemplateEngine(output) { const plugins = output.getPlugins(); const book = output.getBook(); diff --git a/packages/gitbook/src/output/generateAssets.js b/packages/gitbook/src/output/generateAssets.js index 2129553..f926492 100644 --- a/packages/gitbook/src/output/generateAssets.js +++ b/packages/gitbook/src/output/generateAssets.js @@ -1,12 +1,12 @@ const Promise = require('../utils/promise'); /** - Output all assets using a generator - - @param {Generator} generator - @param {Output} output - @return {Promise<Output>} -*/ + * Output all assets using a generator + * + * @param {Generator} generator + * @param {Output} output + * @return {Promise<Output>} + */ function generateAssets(generator, output) { const assets = output.getAssets(); const logger = output.getLogger(); diff --git a/packages/gitbook/src/output/generateBook.js b/packages/gitbook/src/output/generateBook.js index ea8c78e..e27d3ce 100644 --- a/packages/gitbook/src/output/generateBook.js +++ b/packages/gitbook/src/output/generateBook.js @@ -167,7 +167,7 @@ function generateBook(generator, book, options) { ) // Cleanup output folder - .then(function(output) { + .then((output) => { const logger = output.getLogger(); const rootFolder = output.getRoot(); @@ -176,10 +176,10 @@ function generateBook(generator, book, options) { .thenResolve(output); }) - .then(processOutput.bind(null, generator)) + .then(output => processOutput(generator, output)) // Log duration and end message - .then(function(output) { + .then((output) => { const logger = output.getLogger(); const end = Date.now(); const duration = (end - start) / 1000; diff --git a/packages/gitbook/src/output/preparePages.js b/packages/gitbook/src/output/preparePages.js index e65367e..ba8519f 100644 --- a/packages/gitbook/src/output/preparePages.js +++ b/packages/gitbook/src/output/preparePages.js @@ -1,12 +1,13 @@ const Parse = require('../parse'); const Promise = require('../utils/promise'); +const parseURIIndexFromPages = require('../parse/parseURIIndexFromPages'); /** - List and prepare all pages - - @param {Output} - @return {Promise<Output>} -*/ + * List and parse all pages, then create the urls mapping. + * + * @param {Output} + * @return {Promise<Output>} + */ function preparePages(output) { const book = output.getBook(); const logger = book.getLogger(); @@ -16,10 +17,14 @@ function preparePages(output) { } return Parse.parsePagesList(book) - .then(function(pages) { + .then((pages) => { logger.info.ln('found', pages.size, 'pages'); + const urls = parseURIIndexFromPages(pages); - return output.set('pages', pages); + return output.merge({ + pages, + urls + }); }); } diff --git a/packages/gitbook/src/parse/__tests__/parseURIIndexFromPages.js b/packages/gitbook/src/parse/__tests__/parseURIIndexFromPages.js new file mode 100644 index 0000000..e3b9b55 --- /dev/null +++ b/packages/gitbook/src/parse/__tests__/parseURIIndexFromPages.js @@ -0,0 +1,37 @@ +const { OrderedMap } = require('immutable'); + +const parseURIIndexFromPages = require('../parseURIIndexFromPages'); +const Page = require('../../models/page'); + +describe.only('parseURIIndexFromPages', () => { + + it('should map file to html', () => { + const pages = OrderedMap({ + 'page.md': new Page() + }); + const urls = parseURIIndexFromPages(pages); + + expect(urls.resolve('page.md')).toBe('page.html'); + }); + + it('should map README to index.html (directoryIndex: false)', () => { + const pages = OrderedMap({ + 'hello/README.md': new Page() + }); + const urls = parseURIIndexFromPages(pages, { + directoryIndex: false + }); + + expect(urls.resolve('hello/README.md')).toBe('hello/index.html'); + }); + + it('should map README to folder', () => { + const pages = OrderedMap({ + 'hello/README.md': new Page() + }); + const urls = parseURIIndexFromPages(pages); + + expect(urls.resolve('hello/README.md')).toBe('hello/'); + }); + +}); diff --git a/packages/gitbook/src/parse/parseBook.js b/packages/gitbook/src/parse/parseBook.js index 85f4519..e5c1784 100644 --- a/packages/gitbook/src/parse/parseBook.js +++ b/packages/gitbook/src/parse/parseBook.js @@ -10,11 +10,11 @@ const parseReadme = require('./parseReadme'); const parseLanguages = require('./parseLanguages'); /** - Parse content of a book - - @param {Book} book - @return {Promise<Book>} -*/ + * Parse content of a book + * + * @param {Book} book + * @return {Promise<Book>} + */ function parseBookContent(book) { return Promise(book) .then(parseReadme) @@ -23,11 +23,11 @@ function parseBookContent(book) { } /** - Parse a multilingual book - - @param {Book} book - @return {Promise<Book>} -*/ + * Parse a multilingual book + * + * @param {Book} book + * @return {Promise<Book>} + */ function parseMultilingualBook(book) { const languages = book.getLanguages(); const langList = languages.getList(); @@ -52,11 +52,11 @@ function parseMultilingualBook(book) { /** - Parse a whole book from a filesystem - - @param {Book} book - @return {Promise<Book>} -*/ + * Parse a whole book from a filesystem + * + * @param {Book} book + * @return {Promise<Book>} + */ function parseBook(book) { return timing.measure( 'parse.book', diff --git a/packages/gitbook/src/parse/parsePagesList.js b/packages/gitbook/src/parse/parsePagesList.js index 2383dbf..89a1a4f 100644 --- a/packages/gitbook/src/parse/parsePagesList.js +++ b/packages/gitbook/src/parse/parsePagesList.js @@ -7,12 +7,12 @@ const parsePage = require('./parsePage'); /** - Parse a page from a path - - @param {Book} book - @param {String} filePath - @return {Page?} -*/ + * Parse a page from a path + * + * @param {Book} book + * @param {String} filePath + * @return {Page?} + */ function parseFilePage(book, filePath) { const fs = book.getContentFS(); @@ -36,11 +36,11 @@ function parseFilePage(book, filePath) { /** - Parse all pages from a book as an OrderedMap - - @param {Book} book - @return {Promise<OrderedMap<Page>>} -*/ + * Parse all pages from a book as an OrderedMap + * + * @param {Book} book + * @return {Promise<OrderedMap<Page>>} + */ function parsePagesList(book) { const summary = book.getSummary(); const glossary = book.getGlossary(); diff --git a/packages/gitbook/src/parse/parseURIIndexFromPages.js b/packages/gitbook/src/parse/parseURIIndexFromPages.js new file mode 100644 index 0000000..d5f745e --- /dev/null +++ b/packages/gitbook/src/parse/parseURIIndexFromPages.js @@ -0,0 +1,54 @@ +const path = require('path'); +const PathUtils = require('../utils/path'); +const LocationUtils = require('../utils/location'); +const URIIndex = require('../models/uriIndex'); + +const OUTPUT_EXTENSION = '.html'; + +/** + * Convert a filePath (absolute) to an url (without hostname). + * It returns an absolute path. + * + * "README.md" -> "/" + * "test/hello.md" -> "test/hello.html" + * "test/README.md" -> "test/" + * + * @param {Output} output + * @param {String} filePath + * @return {String} + */ +function fileToURL(filePath, directoryIndex) { + if ( + path.basename(filePath, path.extname(filePath)) == 'README' + ) { + filePath = path.join(path.dirname(filePath), 'index' + OUTPUT_EXTENSION); + } else { + filePath = PathUtils.setExtension(filePath, OUTPUT_EXTENSION); + } + + if (directoryIndex && path.basename(filePath) == 'index.html') { + filePath = path.dirname(filePath) + '/'; + } + + return LocationUtils.normalize(filePath); +} + +/** + * Parse a set of pages into an URIIndex. + * Each pages is added as an entry in the index. + * + * @param {OrderedMap<Page>} pages + * @param {Boolean} options.directoryIndex: should we use "index.html" or "/" + * @return {URIIndex} index + */ +function parseURIIndexFromPages(pages, options) { + options = options || {}; + if (typeof options.directoryIndex === 'undefined') { + options.directoryIndex = true; + } + + const urls = pages.map((page, filePath) => fileToURL(filePath, options.directoryIndex)); + return new URIIndex(urls); +} + +module.exports = parseURIIndexFromPages; |