diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 7d9ed0903..b5976dbbb 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -27,3 +27,24 @@ This puts the top level API documentation for the `Map`, `LngLat`, and `LngLatBo items in the given order, and inserts a narrative item titled `Geography` after the section on maps. The `description` property of that narrative item is interpreted as Markdown. +If you would like reuse your existing markdown files or just keep the content separate from the configuration you can use the `file` property. It is a filename it will be resolved against the directory that the `documentation.yml` file resides in. + +So with a `documentation.yml` file like this + +```yml +toc: + - Map + - name: Geography + file: geo.md + - LngLat + - LngLatBounds +``` + +and a file `geo.md` + +```markdown +These are Mapbox GL JS's ways of representing locations +and areas on the sphere. +``` + +it would produce the same output as the previous example. diff --git a/lib/load_config.js b/lib/load_config.js index f57a91d4c..3e0e9781b 100644 --- a/lib/load_config.js +++ b/lib/load_config.js @@ -16,16 +16,15 @@ var yaml = require('js-yaml'), */ function loadConfig(filePath) { var ext = path.extname(filePath); - var rawFile = fs.readFileSync( - path.resolve(process.cwd(), filePath), 'utf8' - ); + var absFilePath = path.resolve(process.cwd(), filePath); + var rawFile = fs.readFileSync(absFilePath, 'utf8'); try { if (ext === '.json') { - return JSON.parse(stripComments(rawFile)); + return processToc(JSON.parse(stripComments(rawFile))); } - return yaml.safeLoad(rawFile); + return processToc(yaml.safeLoad(rawFile)); } catch (e) { e.message = 'Cannot read config file: ' + filePath + @@ -33,6 +32,25 @@ function loadConfig(filePath) { e.message; throw e; } + + function processToc(config) { + if (!config || !config.toc) { + return config; + } + + config.toc = config.toc.map(function (entry) { + if (entry && entry.file) { + entry.file = path.join( + path.dirname(absFilePath), + entry.file + ); + } + + return entry; + }); + + return config; + } } module.exports = loadConfig; diff --git a/lib/sort.js b/lib/sort.js index ef3519143..cac44ffb4 100644 --- a/lib/sort.js +++ b/lib/sort.js @@ -2,6 +2,8 @@ var parseMarkdown = require('./parse_markdown'); var chalk = require('chalk'); +var path = require('path'); +var fs = require('fs'); /** * Sort two documentation objects, given an optional order object. Returns @@ -36,6 +38,19 @@ module.exports = function sortDocs(comments, options) { var fixed = options.toc.filter(function (val) { return typeof val === 'object' && val.name; }).map(function (val) { + if (typeof val.file === 'string') { + var filename = val.file; + if (!path.isAbsolute(val.file)) { + filename = path.join(process.cwd(), val.file); + } + + try { + val.description = fs.readFileSync(filename).toString(); + delete val.file; + } catch (err) { + process.stderr.write(chalk.red('Failed to read file ' + filename)); + } + } if (typeof val.description === 'string') { val.description = parseMarkdown(val.description); } diff --git a/test/config_fixture/config_file.yml b/test/config_fixture/config_file.yml new file mode 100644 index 000000000..cfd70b87c --- /dev/null +++ b/test/config_fixture/config_file.yml @@ -0,0 +1,3 @@ +toc: + - name: snowflake + file: ../fixture/snowflake.md diff --git a/test/fixture/snowflake.md b/test/fixture/snowflake.md new file mode 100644 index 000000000..74ebe7b33 --- /dev/null +++ b/test/fixture/snowflake.md @@ -0,0 +1 @@ +# The Snowflake diff --git a/test/lib/load_config.js b/test/lib/load_config.js index 31e5bc737..64ee5d48f 100644 --- a/test/lib/load_config.js +++ b/test/lib/load_config.js @@ -28,5 +28,12 @@ test('loadConfig', function (t) { t.deepEqual(loadConfig(path.join(__dirname, '../config_fixture/config_links.yml')), { foo: 'hello [link](https://github.com/my/link) world' }, 'config with markdown link'); + t.deepEqual(loadConfig(path.join(__dirname, '../config_fixture/config_file.yml')),{ + toc: [{ + name: 'snowflake', + file: path.join(__dirname, '../fixture/snowflake.md') + }] + }, 'config with file reference'); + t.end(); }); diff --git a/test/lib/sort.js b/test/lib/sort.js index e07adcf61..9b3f405aa 100644 --- a/test/lib/sort.js +++ b/test/lib/sort.js @@ -1,7 +1,8 @@ 'use strict'; var test = require('tap').test, - sort = require('../../lib/sort'); + sort = require('../../lib/sort'), + path = require('path'); test('sort stream alphanumeric', function (t) { var apples = { context: { sortKey: 'a' }, name: 'apples' }; @@ -177,3 +178,103 @@ test('sort an already-sorted stream containing a section/description', function t.deepEqual(sortTwice, [carrot, sectionMarkdown, bananas, apples]); t.end(); }); + +test('sort toc with files', function (t) { + var apples = { context: { sortKey: 'a' }, name: 'apples' }; + var carrot = { context: { sortKey: 'b' }, name: 'carrot' }; + var bananas = { context: { sortKey: 'c' }, name: 'bananas' }; + + var snowflake = { + name: 'snowflake', + file: 'test/fixture/snowflake.md' + }; + + var processedSnowflake = { + name: 'snowflake', + kind: 'note', + description: { + children: [{ + children: [{ + position: { + end: {column: 16, line: 1, offset: 15}, + indent: [], + start: {column: 3, line: 1, offset: 2} + }, + type: 'text', + value: 'The Snowflake' + }], + depth: 1, + position: { + end: {column: 16, line: 1, offset: 15}, + indent: [], + start: {column: 1, line: 1, offset: 0} + }, + type: 'heading' + }], + position: { + end: {column: 1, line: 2, offset: 16}, + start: {column: 1, line: 1, offset: 0} + }, + type: 'root' + } + }; + t.deepEqual(sort([ + apples, carrot, bananas + ], { + toc: [snowflake] + }), [ + processedSnowflake, apples, carrot, bananas + ], 'with configuration'); + + t.end(); +}); + +test('sort toc with files absolute path', function (t) { + var apples = { context: { sortKey: 'a' }, name: 'apples' }; + var carrot = { context: { sortKey: 'b' }, name: 'carrot' }; + var bananas = { context: { sortKey: 'c' }, name: 'bananas' }; + + var snowflake = { + name: 'snowflake', + file: path.join(__dirname, '../fixture/snowflake.md') + }; + + var processedSnowflake = { + name: 'snowflake', + kind: 'note', + description: { + children: [{ + children: [{ + position: { + end: {column: 16, line: 1, offset: 15}, + indent: [], + start: {column: 3, line: 1, offset: 2} + }, + type: 'text', + value: 'The Snowflake' + }], + depth: 1, + position: { + end: {column: 16, line: 1, offset: 15}, + indent: [], + start: {column: 1, line: 1, offset: 0} + }, + type: 'heading' + }], + position: { + end: {column: 1, line: 2, offset: 16}, + start: {column: 1, line: 1, offset: 0} + }, + type: 'root' + } + }; + t.deepEqual(sort([ + apples, carrot, bananas + ], { + toc: [snowflake] + }), [ + processedSnowflake, apples, carrot, bananas + ], 'with configuration'); + + t.end(); +});
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: