UNPKG

esxdoc

Version:

Good Documentation Generator For JavaScript

288 lines (237 loc) 10.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _iceCap = require('ice-cap'); var _iceCap2 = _interopRequireDefault(_iceCap); var _DocBuilder = require('./DocBuilder.js'); var _DocBuilder2 = _interopRequireDefault(_DocBuilder); var _util = require('./util.js'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Class Output Builder class. */ class ClassDocBuilder extends _DocBuilder2.default { /** * execute building output. * @param {function(html: string, filePath: string)} callback - is called each class. */ exec(callback) { const ice = this._buildLayoutDoc(); ice.autoDrop = false; const docs = this._find({ kind: ['class'] }); for (const doc of docs) { const fileName = this._getOutputFileName(doc); const baseUrl = this._getBaseUrl(fileName); const title = this._getTitle(doc); ice.load('content', this._buildClassDoc(doc), _iceCap2.default.MODE_WRITE); ice.attr('baseUrl', 'href', baseUrl, _iceCap2.default.MODE_WRITE); ice.text('title', title, _iceCap2.default.MODE_WRITE); callback(ice.html, fileName); } } /** * build class output. * @param {DocObject} doc - class doc object. * @returns {IceCap} built output. * @private */ _buildClassDoc(doc) { const expressionExtends = this._buildExpressionExtendsHTML(doc); const mixinClasses = this._buildMixinClassesHTML(doc); const extendsChain = this._buildExtendsChainHTML(doc); const directSubclass = this._buildDirectSubclassHTML(doc); const indirectSubclass = this._buildIndirectSubclassHTML(doc); const instanceDocs = this._find({ kind: 'variable' }).filter(v => { return v.type && v.type.types.includes(doc.longname); }); const ice = new _iceCap2.default(this._readTemplate('class.html')); // header if (doc.export && doc.importPath && doc.importStyle) { const link = this._buildFileDocLinkHTML(doc, doc.importPath); ice.into('importPath', `import ${ doc.importStyle } from '${ link }'`, (code, ice) => { ice.load('importPathCode', code); }); } ice.text('access', doc.access); ice.text('kind', doc.interface ? 'interface' : 'class'); ice.load('source', this._buildFileDocLinkHTML(doc, 'source'), 'append'); ice.text('since', doc.since, 'append'); ice.text('version', doc.version, 'append'); ice.load('variation', this._buildVariationHTML(doc), 'append'); ice.into('expressionExtends', expressionExtends, (expressionExtends, ice) => ice.load('expressionExtendsCode', expressionExtends)); ice.load('mixinExtends', mixinClasses, 'append'); ice.load('extendsChain', extendsChain, 'append'); ice.load('directSubclass', directSubclass, 'append'); ice.load('indirectSubclass', indirectSubclass, 'append'); ice.load('implements', this._buildDocsLinkHTML(doc.implements, null, false, ', '), 'append'); ice.load('indirectImplements', this._buildDocsLinkHTML(doc._custom_indirect_implements, null, false, ', '), 'append'); ice.load('directImplemented', this._buildDocsLinkHTML(doc._custom_direct_implemented, null, false, ', '), 'append'); ice.load('indirectImplemented', this._buildDocsLinkHTML(doc._custom_indirect_implemented, null, false, ', '), 'append'); // self ice.text('name', doc.name); ice.load('description', doc.description); ice.load('deprecated', this._buildDeprecatedHTML(doc)); ice.load('experimental', this._buildExperimentalHTML(doc)); ice.load('see', this._buildDocsLinkHTML(doc.see), 'append'); ice.load('todo', this._buildDocsLinkHTML(doc.todo), 'append'); ice.load('decorator', this._buildDecoratorHTML(doc), 'append'); ice.into('instanceDocs', instanceDocs, (instanceDocs, ice) => { ice.loop('instanceDoc', instanceDocs, (i, instanceDoc, ice) => { ice.load('instanceDoc', this._buildDocLinkHTML(instanceDoc.longname)); }); }); ice.into('exampleDocs', doc.examples, (examples, ice) => { ice.loop('exampleDoc', examples, (i, example, ice) => { const parsed = (0, _util.parseExample)(example); ice.text('exampleCode', parsed.body); ice.text('exampleCaption', parsed.caption); }); }); ice.into('tests', doc._custom_tests, (tests, ice) => { ice.loop('test', tests, (i, test, ice) => { const testDoc = this._find({ longname: test })[0]; ice.load('test', this._buildFileDocLinkHTML(testDoc, testDoc.testFullDescription)); }); }); // summary ice.load('staticMemberSummary', this._buildSummaryHTML(doc, 'member', 'Members', true)); ice.load('staticMethodSummary', this._buildSummaryHTML(doc, 'method', 'Methods', true)); ice.load('constructorSummary', this._buildSummaryHTML(doc, 'constructor', 'Constructor', false)); ice.load('memberSummary', this._buildSummaryHTML(doc, 'member', 'Members', false)); ice.load('methodSummary', this._buildSummaryHTML(doc, 'method', 'Methods', false)); ice.load('inheritedSummary', this._buildInheritedSummaryHTML(doc), 'append'); // detail ice.load('staticMemberDetails', this._buildDetailHTML(doc, 'member', 'Members', true)); ice.load('staticMethodDetails', this._buildDetailHTML(doc, 'method', 'Methods', true)); ice.load('constructorDetails', this._buildDetailHTML(doc, 'constructor', 'Constructors', false)); ice.load('memberDetails', this._buildDetailHTML(doc, 'member', 'Members', false)); ice.load('methodDetails', this._buildDetailHTML(doc, 'method', 'Methods', false)); return ice; } /** * build variation of doc. * @param {DocObject} doc - target doc object. * @returns {string} variation links html. * @private * @experimental */ _buildVariationHTML(doc) { const variationDocs = this._find({ memberof: doc.memberof, name: doc.name }); const html = []; for (const variationDoc of variationDocs) { if (variationDoc.variation === doc.variation) continue; html.push(this._buildDocLinkHTML(variationDoc.longname, `(${ variationDoc.variation || 1 })`)); } return html.join(', '); } /** * build mixin extends html. * @param {DocObject} doc - target class doc. * @return {string} mixin extends html. */ _buildMixinClassesHTML(doc) { if (!doc.extends) return ''; if (doc.extends.length <= 1) return ''; const links = []; for (const longname of doc.extends) { links.push(this._buildDocLinkHTML(longname)); } return `<div>${ links.join(', ') }</div>`; } /** * build expression extends html. * @param {DocObject} doc - target class doc. * @return {string} expression extends html. */ _buildExpressionExtendsHTML(doc) { if (!doc.expressionExtends) return ''; const html = doc.expressionExtends.replace(/[A-Z_$][a-zA-Z0-9_$]*/g, v => { return this._buildDocLinkHTML(v); }); return `class ${ doc.name } extends ${ html }`; } /** * build class ancestor extends chain. * @param {DocObject} doc - target class doc. * @returns {string} extends chain links html. * @private */ _buildExtendsChainHTML(doc) { if (!doc._custom_extends_chains) return ''; if (doc.extends.length > 1) return ''; const links = []; for (const longname of doc._custom_extends_chains) { links.push(this._buildDocLinkHTML(longname)); } links.push(doc.name); return `<div>${ links.join(' → ') }</div>`; } /** * build in-direct subclass list. * @param {DocObject} doc - target class doc. * @returns {string} html of in-direct subclass links. * @private */ _buildIndirectSubclassHTML(doc) { if (!doc._custom_indirect_subclasses) return ''; const links = []; for (const longname of doc._custom_indirect_subclasses) { links.push(this._buildDocLinkHTML(longname)); } return `<div>${ links.join(', ') }</div>`; } /** * build direct subclass list. * @param {DocObject} doc - target class doc. * @returns {string} html of direct subclass links. * @private */ _buildDirectSubclassHTML(doc) { if (!doc._custom_direct_subclasses) return ''; const links = []; for (const longname of doc._custom_direct_subclasses) { links.push(this._buildDocLinkHTML(longname)); } return `<div>${ links.join(', ') }</div>`; } /** * build inherited method/member summary. * @param {DocObject} doc - target class doc. * @returns {string} html of inherited method/member from ancestor classes. * @private */ _buildInheritedSummaryHTML(doc) { if (['class', 'interface'].indexOf(doc.kind) === -1) return ''; const longnames = [...(doc._custom_extends_chains || []) // ...doc.implements || [], // ...doc._custom_indirect_implements || [], ]; const html = []; for (const longname of longnames) { const superDoc = this._find({ longname })[0]; if (!superDoc) continue; const targetDocs = this._find({ memberof: longname, kind: ['member', 'method', 'get', 'set'] }); targetDocs.sort((a, b) => { if (a.static !== b.static) return -(a.static - b.static); let order = { get: 0, set: 0, member: 1, method: 2 }; if (order[a.kind] !== order[b.kind]) { return order[a.kind] - order[b.kind]; } order = { public: 0, protected: 1, private: 2 }; if (a.access !== b.access) return order[a.access] - order[b.access]; if (a.name !== b.name) return a.name < b.name ? -1 : 1; order = { get: 0, set: 1, member: 2 }; return order[a.kind] - order[b.kind]; }); const title = `<span class="toggle closed"></span> From ${ superDoc.kind } ${ this._buildDocLinkHTML(longname, superDoc.name) }`; const result = this._buildSummaryDoc(targetDocs, '----------', false, superDoc.kind); if (result) { result.load('title', title, _iceCap2.default.MODE_WRITE); html.push(result.html); } } return html.join('\n'); } } exports.default = ClassDocBuilder;