Comparing sensitive data, confidential files or internal emails?

Most legal and privacy policies prohibit uploading sensitive data online. Diffchecker Desktop ensures your confidential information never leaves your computer. Work offline and compare documents securely.

documentation v6.3.2 vs modifications

Created Diff never expires
31 removals
386 lines
99 additions
423 lines
/* @flow */
/* @flow */


const u = require('unist-builder');
const u = require('unist-builder');
const remark = require('remark');
const remark = require('remark');
const mergeConfig = require('../merge_config');
const mergeConfig = require('../merge_config');
const toc = require('remark-toc');
const toc = require('remark-toc');
const links = require('remark-reference-links');
const links = require('remark-reference-links');
const hljs = require('highlight.js');
const hljs = require('highlight.js');
const GithubSlugger = require('github-slugger');
const GithubSlugger = require('github-slugger');
const LinkerStack = require('./util/linker_stack');
const LinkerStack = require('./util/linker_stack');
const rerouteLinks = require('./util/reroute_links');
const rerouteLinks = require('./util/reroute_links');
const _formatType = require('./util/format_type');
const _formatType = require('./util/format_type');


const DEFAULT_LANGUAGE = 'javascript';
const DEFAULT_LANGUAGE = 'javascript';


/**
/**
* Given a hierarchy-nested set of comments, generate an remark-compatible
* Given a hierarchy-nested set of comments, generate an remark-compatible
* Abstract Syntax Tree usable for generating Markdown output
* Abstract Syntax Tree usable for generating Markdown output
*
*
* @param comments nested comment
* @param comments nested comment
* @param {Object} args currently none accepted
* @param {Object} args currently none accepted
* @param {boolean} [args.markdownToc=true] whether to include a table of contents
* @param {boolean} [args.markdownToc=true] whether to include a table of contents
* in markdown output.
* in markdown output.
* @param {Object} [args.hljs={}] config to be passed to highlightjs for code highlighting:
* @param {Object} [args.hljs={}] config to be passed to highlightjs for code highlighting:
* consult hljs.configure for the full list.
* consult hljs.configure for the full list.
* @returns {Promise<Object>} returns an eventual Markdown value
* @returns {Promise<Object>} returns an eventual Markdown value
*/
*/
function markdownAST(comments: Array<Comment>, args: Object) {
function markdownAST(comments: Array<Comment>, args: Object) {
return mergeConfig(args).then(config => buildMarkdownAST(comments, config));
return mergeConfig(args).then(config => buildMarkdownAST(comments, config));
}
}


function buildMarkdownAST(
function buildMarkdownAST(
comments: Array<Comment>,
comments: Array<Comment>,
config: DocumentationConfig
config: DocumentationConfig
) {
) {
// Configure code highlighting
// Configure code highlighting
const hljsOptions = config.hljs || {};
const hljsOptions = config.hljs || {};
hljs.configure(hljsOptions);
hljs.configure(hljsOptions);


const linkerStack = new LinkerStack(config).namespaceResolver(
const linkerStack = new LinkerStack(config).namespaceResolver(
comments,
comments,
namespace => {
namespace => {
const slugger = new GithubSlugger();
const slugger = new GithubSlugger();
return '#' + slugger.slug(namespace);
return '#' + slugger.slug(namespace);
}
}
);
);


const formatType = _formatType.bind(undefined, linkerStack.link);
const formatType = _formatType.bind(undefined, linkerStack.link);


const generatorComment = [
const generatorComment = [
u(
u(
'html',
'html',
'<!-- Generated by documentation.js. Update this documentation by updating the source code. -->'
'<!-- Generated by documentation.js. Update this documentation by updating the source code. -->'
)
)
];
];


const tableOfContentsHeading = [
const tableOfContentsHeading = [
u('heading', { depth: 3 }, [u('text', 'Table of Contents')])
u('heading', { depth: 3 }, [u('text', 'Table of Contents')])
];
];


/**
/**
* Generate an AST chunk for a comment at a given depth: this is
* Generate an AST chunk for a comment at a given depth: this is
* split from the main function to handle hierarchially nested comments
* split from the main function to handle hierarchially nested comments
*
*
* @param {number} depth nesting of the comment, starting at 1
* @param {number} depth nesting of the comment, starting at 1
* @param {Object} comment a single comment
* @param {Object} comment a single comment
* @returns {Object} remark-compatible AST
* @returns {Object} remark-compatible AST
*/
*/
function generate(depth: number, comment: Comment) {
function generate(depth: number, comment: Comment) {
function typeSection(comment: Comment) {
function typeSection(comment: Comment) {
return (
if (comment.type) {
comment.type &&
return u(
u('paragraph', [u('text', 'Type: ')].concat(formatType(comment.type)))
'paragraph',
);
[u('text', 'Type: ')].concat(formatType(comment.type))
);
} else if (comment.kind) {
var c = Object.assign(
{
type: 'FunctionType'
},
comment,
{
result:
comment.returns && comment.returns[0] && comment.returns[0].type
}
);

return u('paragraph', [u('text', 'Type: ')].concat(formatType(c)));
}
}
}


function paramList(params: Array<CommentTag>) {
function paramList(params: Array<CommentTag>) {
if (params.length === 0) return [];
if (params.length === 0) return [];
return u(
return u(
'list',
'list',
{ ordered: false },
{ ordered: false },
params.map(param =>
params.map(param =>
u(
u(
'listItem',
'listItem',
[
[
u(
u(
'paragraph',
'paragraph',
[
[
u('inlineCode', param.name),
u('inlineCode', param.name),
u('text', ' '),
u('text', ' '),
!!param.type && u('strong', formatType(param.type)),
!!param.type && u('strong', formatType(param.type)),
u('text', ' ')
u('text', ' ')
]
]
.concat(param.description ? param.description.children : [])
.concat(param.description ? param.description.children : [])
.concat([
.concat([
!!param.default &&
!!param.default &&
u('paragraph', [
u('paragraph', [
u('text', ' (optional, default '),
u('text', ' (optional, default '),
u('inlineCode', param.default),
u('inlineCode', param.default),
u('text', ')')
u('text', ')')
])
])
])
])
.filter(Boolean)
.filter(Boolean)
)
)
]
]
.concat(param.properties && paramList(param.properties))
.concat(param.properties && paramList(param.properties))
.filter(Boolean)
.filter(Boolean)
)
)
)
)
);
);
}
}


function paramSection(comment: Comment) {
function paramSection(comment: Comment) {
return (
return (
comment.params.length > 0 && [
comment.params.length > 0 && [
u('strong', [u('text', 'Parameters')]),
// u('text', 'Parameters:'),
paramList(comment.params)
paramList(comment.params)
]
]
);
);
}
}


function propertySection(comment: Comment) {
function propertySection(comment: Comment) {
return (
return (
comment.properties.length > 0 && [
comment.properties.length > 0 && [
u('strong', [u('text', 'Properties')]),
// u('text', 'Properties:'),
propertyList(comment.properties)
propertyList(comment.properties)
]
]
);
);
}
}


function propertyList(properties: Array<CommentTag>) {
function propertyList(properties: Array<CommentTag>) {
return u(
return u(
'list',
'list',
{ ordered: false },
{ ordered: false },
properties.map(property =>
properties.map(property =>
u(
u(
'listItem',
'listItem',
[
[
u(
u(
'paragraph',
'paragraph',
[
[
u('inlineCode', property.name),
u('inlineCode', property.name),
u('text', ' '),
u('text', ' '),
u('strong', formatType(property.type)),
u('strong', formatType(property.type)),
u('text', ' ')
u('text', ' ')
]
]
.concat(
.concat(
property.description ? property.description.children : []
property.description ? property.description.children : []
)
)
.filter(Boolean)
.filter(Boolean)
),
),
property.properties && propertyList(property.properties)
property.properties && propertyList(property.properties)
].filter(Boolean)
].filter(Boolean)
)
)
)
)
);
);
}
}


function examplesSection(comment: Comment) {
function examplesSection(comment: Comment) {
const isSingle = comment.examples.length === 1;
return (
return (
comment.examples.length > 0 &&
comment.examples.length > 0 &&
[u('strong', [u('text', 'Examples')])].concat(
[u('text', isSingle ? 'Example:' : 'Examples:')].concat(
comment.examples.reduce(function(memo, example) {
comment.examples.reduce(function(memo, example) {
const language = hljsOptions.highlightAuto
const language = hljsOptions.highlightAuto
? hljs.highlightAuto(example.description).language
? hljs.highlightAuto(example.description).language
: DEFAULT_LANGUAGE;
: DEFAULT_LANGUAGE;
return memo
return memo
.concat(
.concat(
example.caption
example.caption
? [u('paragraph', [u('emphasis', example.caption)])]
? [u('paragraph', [u('emphasis', example.caption)])]
: []
: []
)
)
.concat([u('code', { lang: language }, example.description)]);
.concat([u('code', { lang: language }, example.description)]);
}, [])
}, [])
)
)
);
);
}
}


function returnsSection(comment: Comment) {
function returnsSection(comment: Comment) {
return (
return (
comment.returns.length > 0 &&
comment.returns.length > 0 &&
comment.returns.map(returns =>
comment.returns.map(returns =>
u(
u(
'paragraph',
'paragraph',
[
[
u('text', 'Returns '),
u('text', 'Returns:'),
u('text', ' '),
u('strong', formatType(returns.type)),
u('strong', formatType(returns.type)),
u('text', ' ')
u('text', ' ')
].concat(returns.description ? returns.description.children : [])
].concat(returns.description ? returns.description.children : [])
)
)
)
)
);
);
}
}


function throwsSection(comment: Comment) {
function throwsSection(comment: Comment) {
return (
return (
comment.throws.length > 0 &&
comment.throws.length > 0 &&
u(
u(
'list',
'list',
{ ordered: false },
{ ordered: false },
comment.throws.map(returns =>
comment.throws.map(returns =>
u('listItem', [
u('listItem', [
u(
u(
'paragraph',
'paragraph',
[
[
u('text', 'Throws '),
u('text', 'Throws:'),
u('text', ' '),
u('strong', formatType(returns.type)),
u('strong', formatType(returns.type)),
u('text', ' ')
u('text', ' ')
].concat(
].concat(
returns.description ? returns.description.children : []
returns.description ? returns.description.children : []
)
)
)
)
])
])
)
)
)
)
);
);
}
}


function augmentsLink(comment: Comment) {
function augmentsLink(comment: Comment) {
return (
return (
comment.augments.length > 0 &&
comment.augments.length > 0 &&
u('paragraph', [
u('paragraph', [
u('strong', [
u('strong', [
u('text', 'Extends '),
u('text', 'Extends: '),
u('text', comment.augments.map(tag => tag.name).join(', '))
u('text', comment.augments.map(tag => tag.name).join(', '))
])
])
])
])
);
);
}
}


function seeLink(comment: Comment) {
function seeLink(comment: Comment) {
return (
return (
comment.sees.length > 0 &&
comment.sees.length > 0 &&
u(
u(
'list',
'list',
{ ordered: false },
{ ordered: false },
comment.sees.map(see =>
comment.sees.map(see =>
u('listItem', [
u('listItem', [
u('strong', [u('text', 'See: ')].concat(see.children))
u('strong', [u('text', 'See: ')].concat(see.children))
])
])
)
)
)
)
);
);
}
}


function githubLink(comment: Comment) {
function githubLink(comment: Comment) {
return (
return (
comment.context &&
comment.context &&
comment.context.github &&
comment.context.github &&
u('paragraph', [
u('paragraph', [
u('text', 'Source: '),
u(
u(
'link',
'link',
{
{
title: 'Source code on GitHub',
title: 'Source code on GitHub',
url: comment.context.github.url
url: comment.context.github.url
},
},
[
[
u(
u(
'text',
'text',
comment.context.github.path +
comment.context.github.path +
':' +
':' +
comment.context.loc.start.line +
comment.context.loc.start.line
'-' +
comment.context.loc.end.line
)
)
]
]
)
)
])
])
);
);
}
}


function metaSection(comment: Comment) {
function metaSection(comment: Comment) {
const meta = [
const meta = [
'version',
'version',
'since',
'since',
'copyright',
'copyright',
'author',
'author',
'license',
'license',
'deprecated'
'deprecated'
].filter(tag => comment[tag]);
].filter(tag => comment[tag]);
return (
return (
!!meta.length &&
!!meta.length &&
[u('strong', [u('text', 'Meta')])].concat(
[u('strong', [u('text', 'Meta')])].concat(
u(
u(
'list',
'list',
{ ordered: false },
{ ordered: false },
meta.map(tag => {
meta.map(tag => {
let metaContent;
let metaContent;
if (tag === 'copyright' || tag === 'deprecated') {
if (tag === 'copyright' || tag === 'deprecated') {
metaContent = comment[tag];
metaContent = comment[tag];
} else {
} else {
metaContent = u('text', comment[tag]);
metaContent = u('text', comment[tag]);
}
}
return u('listItem', [
return u('listItem', [
u('paragraph', [
u('paragraph', [
u('strong', [u('text', tag)]),
u('strong', [u('text', tag)]),
u('text', ': '),
u('text', ': '),
metaContent
metaContent
])
])
]);
]);
})
})
)
)
)
)
);
);
}
}


if (comment.kind === 'note') {
if (comment.kind === 'note') {
return [u('heading', { depth }, [u('text', comment.name || '')])]
return [u('heading', { depth }, [u('text', comment.name || '')])]
.concat(comment.description)
.concat(comment.description)
.concat(
.concat(
!!comment.members.static.length &&
!!comment.members.static.length &&
comment.members.static.reduce(
comment.members.static.reduce(
(memo, child) => memo.concat(generate(depth + 1, child)),
(memo, child) => memo.concat(generate(depth + 1, child)),
[]
[]
)
)
)
)
.filter(Boolean);
.filter(Boolean);
}
}


return [u('heading', { depth }, [u('text', comment.name || '')])]
var heading = [u('text', comment.name || '')];
.concat(githubLink(comment))
if (comment.context && comment.context.github) {
.concat(augmentsLink(comment))
heading = [
.concat(seeLink(comment))
u(
.concat(comment.description ? comment.description.children : [])
'link',
.concat(typeSection(comment))
{
.concat(paramSection(comment))
url: comment.context.github.url
.concat(propertySection(comment))
},
.concat(examplesSection(comment))
heading
.concat(throwsSection(comment))
)
.concat(returnsSection(comment))
];
.concat(metaSection(comment))
}
.concat(

!!comment.members.global.length &&
const prefix = config.markdownToc || depth > 2 ? [u('thematicBreak')] : [];
comment.members.global.reduce(

(memo, child) => memo.concat(generate(depth + 1, child)),
return (
[]
prefix
)
.concat([u('heading', { depth }, heading)])
)
.concat(augmentsLink(comment))
.concat(
.concat(seeLink(comment))
!!comment.members.instance.length &&
.concat(comment.description ? comment.description.children : [])
comment.members.instance.reduce(
.concat(typeSection(comment))
(memo, child) => memo.concat(generate(depth + 1, child)),
.concat(paramSection(comment))
[]
.concat(propertySection(comment))
)
.concat(throwsSection(comment))
)
// .concat(returnsSection(comment))
.concat(
// .concat(githubLink(comment))
!!comment.members.static.length &&
.concat(examplesSection(comment))
comment.members.static.reduce(
.concat(metaSection(comment))
(memo, child) => memo.concat(generate(depth + 1, child)),
.concat(
[]
!!comment.members.global.length &&
)
comment.members.global.reduce(
)
(memo, child) => memo.concat(generate(depth + 1, child)),
.concat(
[]
!!comment.members.inner.length &&
)
comment.members.inner.reduce(
)
(memo, child) => memo.concat(generate(depth + 1, child)),
.concat(
[]
!!comment.members.instance.length &&
)
comment.members.instance.reduce(
)
(memo, child) => memo.concat(generate(depth + 1, child)),
.filter(Boolean);
[]
)
)
.concat(
!!comment.members.static.length &&
comment.members.static.reduce(
(memo, child) => memo.concat(generate(depth + 1, child)),
[]
)
)
.concat(
!!comment.members.inner.length &&
comment.members.inner.reduce(
(memo, child) => memo.concat(generate(depth + 1, child)),
[]
)
)
.filter(Boolean)
);
}
}


let root = rerouteLinks(
let root = rerouteLinks(
linkerStack.link,
linkerStack.link,
u(
u(
'root',
'root',
generatorComment
generatorComment
.concat(config.markdownToc ? tableOfContentsHeading : [])
.concat(config.markdownToc ? tableOfContentsHeading : [])
.concat(
.concat(
comments.reduce(
comments.reduce(
(memo, comment) => memo.concat(generate(2, comment)),
(memo, comment) => memo.concat(generate(2, comment)),
[]
[]
)
)
)
)
.concat(config.markdownToc ? [u('thematicBreak')] : [])
)
)
);
);


const pluginRemark = remark();
const pluginRemark = remark();
if (config.markdownToc) pluginRemark.use(toc, { tight: true });
if (config.markdownToc) pluginRemark.use(toc, { tight: true });
if (config.noReferenceLinks !== true) pluginRemark.use(links);
if (config.noReferenceLinks !== true) pluginRemark.use(links);
root = pluginRemark.run(root);
root = pluginRemark.run(root);


return Promise.resolve(root);
return Promise.resolve(root);
}
}


module.exports = markdownAST;
module.exports = markdownAST;