diff --git a/lib/config/DocProcessor/doctool.config.json b/lib/config/DocProcessor/doctool.config.json index 6f7ef23478..ff5d36f910 100644 --- a/lib/config/DocProcessor/doctool.config.json +++ b/lib/config/DocProcessor/doctool.config.json @@ -1,5 +1,5 @@ { "enabledTools": [ - "index" + "tsInfo" ] } \ No newline at end of file diff --git a/lib/config/DocProcessor/templates/component.liquid b/lib/config/DocProcessor/templates/component.liquid new file mode 100644 index 0000000000..69f181f21a --- /dev/null +++ b/lib/config/DocProcessor/templates/component.liquid @@ -0,0 +1,17 @@ +{% if hasInputs -%} +### Properties + +| Name | Type | Default value | Description | +| -- | -- | -- | -- | +{% for prop in properties %}{% if prop.isInput %}| {{prop.name}} | `{{prop.type}}` | {{prop.defaultValue}} | {% if prop.isDeprecated %}(Deprecated) {% endif %}{{prop.docText}} | +{% endif %}{% endfor %} +{% endif %} + +{% if hasOutputs -%} +### Events + +| Name | Type | Description | +| -- | -- | -- | +{% for prop in properties %}{% if prop.isOutput %}| {{prop.name}} | `{{prop.type}}` | {% if prop.isDeprecated %}(Deprecated) {% endif %}{{prop.docText}} | +{% endif %}{% endfor %} +{% endif %} \ No newline at end of file diff --git a/lib/config/DocProcessor/templates/directive.liquid b/lib/config/DocProcessor/templates/directive.liquid new file mode 100644 index 0000000000..d33b70d05d --- /dev/null +++ b/lib/config/DocProcessor/templates/directive.liquid @@ -0,0 +1 @@ +{% include 'component' %} \ No newline at end of file diff --git a/lib/config/DocProcessor/templates/service.liquid b/lib/config/DocProcessor/templates/service.liquid new file mode 100644 index 0000000000..3937893c11 --- /dev/null +++ b/lib/config/DocProcessor/templates/service.liquid @@ -0,0 +1,10 @@ + +{% if hasMethods %} +### Methods + +{% for meth in methods %}- `{{meth.name}}{{meth.signature}}: {{meth.returnType}}`
+ {{meth.docText}} + {% for param in meth.params %} - `{{param.combined}}` - {% if param.isOptional %}(Optional){% endif %}{{param.docText}} +{% endfor %} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/lib/config/DocProcessor/tools/tsInfo.js b/lib/config/DocProcessor/tools/tsInfo.js new file mode 100644 index 0000000000..33141c4cff --- /dev/null +++ b/lib/config/DocProcessor/tools/tsInfo.js @@ -0,0 +1,164 @@ +"use strict"; +exports.__esModule = true; +var fs = require("fs"); +var path = require("path"); +var replaceSection = require("mdast-util-heading-range"); +var remark = require("remark"); +var frontMatter = require("remark-frontmatter"); +var liquid = require("liquidjs"); +var typedoc_1 = require("typedoc"); +var libFolders = ["content-services"]; //["core", "content-services", "process-services", "insights"]; +var templateFolder = path.resolve(".", "config", "DocProcessor", "templates"); +var excludePatterns = [ + "**/*.spec.ts" +]; +var nameExceptions = { + "datatable.component": "DataTableComponent", + "tasklist.service": "TaskListService" +}; +var PropInfo = /** @class */ (function () { + function PropInfo(rawProp) { + var _this = this; + this.name = rawProp.name; + this.docText = rawProp.comment ? rawProp.comment.shortText : ""; + this.docText = this.docText.replace(/[\n\r]+/g, " "); + this.defaultValue = rawProp.defaultValue || ""; + this.defaultValue = this.defaultValue.replace(/\|/, "\\|"); + this.type = rawProp.type ? rawProp.type.toString() : ""; + if (rawProp.decorators) { + rawProp.decorators.forEach(function (dec) { + if (dec.name === "Input") + _this.isInput = true; + if (dec.name === "Output") + _this.isOutput = true; + }); + } + this.isDeprecated = rawProp.comment && rawProp.comment.hasTag("deprecated"); + } + return PropInfo; +}()); +; +var ParamInfo = /** @class */ (function () { + function ParamInfo(rawParam) { + this.name = rawParam.name; + this.type = rawParam.type.toString(); + this.defaultValue = rawParam.defaultValue; + this.docText = rawParam.comment ? rawParam.comment.text : ""; + this.docText = this.docText.replace(/[\n\r]+/g, " "); + this.isOptional = rawParam.flags.isOptional; + this.combined = this.name; + if (this.isOptional) + this.combined += "?"; + this.combined += ": " + this.type; + if (this.defaultValue !== "") + this.combined += " = " + this.defaultValue; + } + return ParamInfo; +}()); +var MethodSigInfo = /** @class */ (function () { + function MethodSigInfo(rawSig) { + var _this = this; + this.name = rawSig.name; + this.docText = rawSig.hasComment() ? rawSig.comment.shortText + rawSig.comment.text : ""; + this.docText = this.docText.replace(/[\n\r]+/g, " "); + this.returnType = rawSig.type ? rawSig.type.toString() : ""; + this.isDeprecated = rawSig.comment && rawSig.comment.hasTag("deprecated"); + this.params = []; + var paramStrings = []; + if (rawSig.parameters) { + rawSig.parameters.forEach(function (rawParam) { + var param = new ParamInfo(rawParam); + _this.params.push(param); + paramStrings.push(param.combined); + }); + } + this.signature = "(" + paramStrings.join(", ") + ")"; + } + return MethodSigInfo; +}()); +var ComponentInfo = /** @class */ (function () { + function ComponentInfo(classRef) { + var _this = this; + var props = classRef.getChildrenByKind(typedoc_1.ReflectionKind.Property); + this.properties = props.map(function (item) { + return new PropInfo(item); + }); + var methods = classRef.getChildrenByKind(typedoc_1.ReflectionKind.Method); + this.methods = []; + methods.forEach(function (method) { + if (!(method.flags.isPrivate || method.flags.isProtected)) { + method.signatures.forEach(function (sig) { + _this.methods.push(new MethodSigInfo(sig)); + }); + } + }); + this.properties.forEach(function (prop) { + if (prop.isInput) + _this.hasInputs = true; + if (prop.isOutput) + _this.hasOutputs = true; + }); + this.hasMethods = methods.length > 0; + } + return ComponentInfo; +}()); +function initPhase(aggData) { + var app = new typedoc_1.Application({ + exclude: excludePatterns, + ignoreCompilerErrors: true + }); + var sources = app.expandInputFiles(libFolders); + aggData.projData = app.convert(sources); + aggData.liq = liquid({ + root: templateFolder + }); +} +exports.initPhase = initPhase; +function readPhase(tree, pathname, aggData) { +} +exports.readPhase = readPhase; +function aggPhase(aggData) { +} +exports.aggPhase = aggPhase; +function updatePhase(tree, pathname, aggData) { + var compName = angNameToClassName(path.basename(pathname, ".md")); + var classRef = aggData.projData.findReflectionByName(compName); + var compData = new ComponentInfo(classRef); + var classType = compName.match(/component|directive|service/i); + if (classType) { + var templateName = classType[0] + ".liquid"; + aggData.liq + .renderFile(templateName, compData) + .then(function (mdText) { + var newSection = remark().parse(mdText).children; + replaceSection(tree, "Class members", function (before, section, after) { + newSection.unshift(before); + newSection.push(after); + return newSection; + }); + fs.writeFileSync(pathname, remark().use(frontMatter, { type: 'yaml', fence: '---' }).data("settings", { paddedTable: false }).stringify(tree)); + }); + } + return false; +} +exports.updatePhase = updatePhase; +function initialCap(str) { + return str[0].toUpperCase() + str.substr(1); +} +function angNameToClassName(rawName) { + if (nameExceptions[rawName]) + return nameExceptions[rawName]; + var name = rawName.replace(/\]|\(|\)/g, ''); + var fileNameSections = name.split('.'); + var compNameSections = fileNameSections[0].split('-'); + var outCompName = ''; + for (var i = 0; i < compNameSections.length; i++) { + outCompName = outCompName + initialCap(compNameSections[i]); + } + var itemTypeIndicator = ''; + if (fileNameSections.length > 1) { + itemTypeIndicator = initialCap(fileNameSections[1]); + } + var finalName = outCompName + itemTypeIndicator; + return finalName; +} diff --git a/lib/config/DocProcessor/tools/tsInfo.ts b/lib/config/DocProcessor/tools/tsInfo.ts new file mode 100644 index 0000000000..d1aa85d45d --- /dev/null +++ b/lib/config/DocProcessor/tools/tsInfo.ts @@ -0,0 +1,247 @@ +import * as fs from "fs"; +import * as path from "path"; + +import * as replaceSection from "mdast-util-heading-range"; +import * as remark from "remark"; +import * as frontMatter from "remark-frontmatter"; + +import * as liquid from "liquidjs"; + +import { + Application, + ProjectReflection, + Reflection, + DeclarationReflection, + SignatureReflection, + ParameterReflection, + ReflectionKind, + TraverseProperty, + Decorator + } from "typedoc"; +import { CommentTag } from "typedoc/dist/lib/models"; + + +let libFolders = ["content-services"];//["core", "content-services", "process-services", "insights"]; +let templateFolder = path.resolve(".", "config", "DocProcessor", "templates"); + +let excludePatterns = [ + "**/*.spec.ts" +]; + + +let nameExceptions = { + "datatable.component": "DataTableComponent", + "tasklist.service": "TaskListService" +} + + +class PropInfo { + name: string; + type: string; + defaultValue: string; + docText: string; + isInput: boolean; + isOutput: boolean; + isDeprecated: boolean; + + constructor(rawProp: DeclarationReflection) { + this.name = rawProp.name; + this.docText = rawProp.comment ? rawProp.comment.shortText : ""; + this.docText = this.docText.replace(/[\n\r]+/g, " "); + this.defaultValue = rawProp.defaultValue || ""; + this.defaultValue = this.defaultValue.replace(/\|/, "\\|"); + this.type = rawProp.type ? rawProp.type.toString() : ""; + + if (rawProp.decorators) { + rawProp.decorators.forEach(dec => { + if (dec.name === "Input") + this.isInput = true; + + if (dec.name === "Output") + this.isOutput = true; + }); + } + + this.isDeprecated = rawProp.comment && rawProp.comment.hasTag("deprecated"); + } +}; + + +class ParamInfo { + name: string; + type: string; + defaultValue: string; + docText: string; + combined: string; + isOptional: boolean; + + constructor(rawParam: ParameterReflection) { + this.name = rawParam.name; + this.type = rawParam.type.toString(); + this.defaultValue = rawParam.defaultValue; + this.docText = rawParam.comment ? rawParam.comment.text : ""; + this.docText = this.docText.replace(/[\n\r]+/g, " "); + this.isOptional = rawParam.flags.isOptional; + + this.combined = this.name; + + if (this.isOptional) + this.combined += "?"; + + this.combined += `: ${this.type}`; + + if (this.defaultValue !== "") + this.combined += ` = ${this.defaultValue}`; + } +} + + +class MethodSigInfo { + name: string; + docText: string; + returnType: string; + signature: string; + params: ParamInfo[]; + isDeprecated: boolean; + + constructor(rawSig: SignatureReflection) { + this.name = rawSig.name; + this.docText = rawSig.hasComment() ? rawSig.comment.shortText + rawSig.comment.text : ""; + this.docText = this.docText.replace(/[\n\r]+/g, " "); + this.returnType = rawSig.type ? rawSig.type.toString() : ""; + this.isDeprecated = rawSig.comment && rawSig.comment.hasTag("deprecated"); + + this.params = []; + let paramStrings = []; + + if (rawSig.parameters) { + rawSig.parameters.forEach(rawParam => { + let param = new ParamInfo(rawParam); + this.params.push(param); + paramStrings.push(param.combined); + }); + } + + this.signature = "(" + paramStrings.join(", ") + ")"; + } +} + + +class ComponentInfo { + properties: PropInfo[]; + methods: MethodSigInfo[]; + hasInputs: boolean; + hasOutputs: boolean; + hasMethods: boolean; + + constructor(classRef: DeclarationReflection) { + let props = classRef.getChildrenByKind(ReflectionKind.Property); + + this.properties = props.map(item => { + return new PropInfo(item); + }); + + let methods = classRef.getChildrenByKind(ReflectionKind.Method); + + this.methods = []; + + methods.forEach(method =>{ + if (!(method.flags.isPrivate || method.flags.isProtected)) { + method.signatures.forEach(sig => { + this.methods.push(new MethodSigInfo(sig)); + }); + } + }); + + this.properties.forEach(prop => { + if (prop.isInput) + this.hasInputs = true; + + if (prop.isOutput) + this.hasOutputs = true; + }); + + this.hasMethods = methods.length > 0; + } +} + + +export function initPhase(aggData) { + let app = new Application({ + exclude: excludePatterns, + ignoreCompilerErrors: true + }); + + let sources = app.expandInputFiles(libFolders); + aggData.projData = app.convert(sources); + aggData.liq = liquid({ + root: templateFolder + }); +} + + +export function readPhase(tree, pathname, aggData) { +} + + +export function aggPhase(aggData) { +} + + +export function updatePhase(tree, pathname, aggData) { + let compName = angNameToClassName(path.basename(pathname, ".md")); + let classRef = aggData.projData.findReflectionByName(compName); + let compData = new ComponentInfo(classRef); + let classType = compName.match(/component|directive|service/i); + + if (classType) { + let templateName = classType[0] + ".liquid"; + + aggData.liq + .renderFile(templateName, compData) + .then(mdText => { + let newSection = remark().parse(mdText).children; + replaceSection(tree, "Class members", (before, section, after) => { + newSection.unshift(before); + newSection.push(after); + return newSection; + }); + + fs.writeFileSync(pathname, remark().use(frontMatter, {type: 'yaml', fence: '---'}).data("settings", {paddedTable: false}).stringify(tree)); + }); + } + + return false; +} + + +function initialCap(str: string) { + return str[0].toUpperCase() + str.substr(1); +} + + +function angNameToClassName(rawName: string) { + if (nameExceptions[rawName]) + return nameExceptions[rawName]; + + var name = rawName.replace(/\]|\(|\)/g, ''); + + var fileNameSections = name.split('.'); + var compNameSections = fileNameSections[0].split('-'); + + var outCompName = ''; + + for (var i = 0; i < compNameSections.length; i++) { + outCompName = outCompName + initialCap(compNameSections[i]); + } + + var itemTypeIndicator = ''; + + if (fileNameSections.length > 1) { + itemTypeIndicator = initialCap(fileNameSections[1]); + } + + var finalName = outCompName + itemTypeIndicator; + + return finalName; +}