mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-2969] Moved doc tools to new tools folder (#3314)
* [ADF-2969] Moved doc tools to new tools folder * [ADF-2969] Added files missing from schematic * [ADF-2969] Added missing files to schematic
This commit is contained in:
committed by
Eugenio Romano
parent
9d0ccff189
commit
60644d9917
@@ -1,27 +0,0 @@
|
||||
# Review checker guide
|
||||
|
||||
The review checker tool queries the Github repo to look for recent
|
||||
commits to the component source files. The dates of these commits
|
||||
are compared against against a review date stored in the Markdown doc
|
||||
file for each component. The time and the number of commits since the
|
||||
last review are then combined into a "score" that gives an indication
|
||||
of how urgently the doc file needs a review.
|
||||
|
||||
## Review date metadata
|
||||
|
||||
The review date is kept in the YAML metadata section at the top of each
|
||||
Markdown file. The key is "Last reviewed" and the date is in the form
|
||||
YYYY-MM-DD.
|
||||
|
||||
## Commit message stoplist
|
||||
|
||||
The checker will ignore any commits that match regular expressions stored
|
||||
in the `commitStoplist.json` file in the `DocProcessor` folder. You could
|
||||
use this, for example, to filter out JIRA tasks that don't involve any
|
||||
changes in functionality (and therefore don't need documenting).
|
||||
|
||||
## Output format
|
||||
|
||||
The script sends comma-separated text to the command line. You can copy/paste
|
||||
this into a spreadsheet or redirect the output to a text file with a ".csv"
|
||||
suffix.
|
@@ -1 +0,0 @@
|
||||
["ADF-1769"]
|
@@ -1,186 +0,0 @@
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var program = require("commander");
|
||||
|
||||
var remark = require("remark");
|
||||
var parse = require("remark-parse");
|
||||
var stringify = require("remark-stringify");
|
||||
var frontMatter = require("remark-frontmatter");
|
||||
|
||||
|
||||
// "Aggregate" data collected over the whole file set.
|
||||
var aggData = {};
|
||||
|
||||
var toolsFolderName = "tools";
|
||||
var configFileName = "doctool.config.json";
|
||||
var defaultFolder = path.resolve("..", "docs");
|
||||
|
||||
|
||||
function initPhase(aggData) {
|
||||
toolList.forEach(toolName => {
|
||||
toolModules[toolName].initPhase(aggData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function readPhase(filenames, aggData) {
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
var pathname = filenames[i];//path.resolve(srcFolder, filenames[i]);
|
||||
|
||||
var src = fs.readFileSync(pathname);
|
||||
var tree = remark().use(frontMatter, ["yaml"]).parse(src);
|
||||
|
||||
toolList.forEach(toolName => {
|
||||
toolModules[toolName].readPhase(tree, pathname, aggData);
|
||||
});
|
||||
}
|
||||
|
||||
//console.log(JSON.stringify(aggData.mdFileData));
|
||||
}
|
||||
|
||||
|
||||
function aggPhase(aggData) {
|
||||
toolList.forEach(toolName => {
|
||||
toolModules[toolName].aggPhase(aggData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updatePhase(filenames, aggData) {
|
||||
var errorMessages;
|
||||
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
errorMessages = [];
|
||||
var pathname = filenames[i]; // path.resolve(srcFolder, filenames[i]);
|
||||
|
||||
var src = fs.readFileSync(pathname);
|
||||
var tree = remark().use(frontMatter, ["yaml"]).parse(src)
|
||||
|
||||
var modified = false;
|
||||
|
||||
toolList.forEach(toolName => {
|
||||
modified |= toolModules[toolName].updatePhase(tree, pathname, aggData, errorMessages);
|
||||
});
|
||||
|
||||
if (errorMessages.length > 0) {
|
||||
showErrors(pathname, errorMessages);
|
||||
}
|
||||
|
||||
if (modified)
|
||||
fs.writeFileSync(filenames[i], remark().use(frontMatter, {type: 'yaml', fence: '---'}).data("settings", {paddedTable: false, gfm: false}).stringify(tree));
|
||||
|
||||
//console.log(JSON.stringify(tree));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function showErrors(filename, errorMessages) {
|
||||
console.log(filename);
|
||||
|
||||
errorMessages.forEach(message => {
|
||||
console.log(" " + message);
|
||||
});
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
|
||||
function loadToolModules() {
|
||||
var mods = {};
|
||||
var toolsFolderPath = path.resolve(__dirname, toolsFolderName);
|
||||
var modFiles = fs.readdirSync(toolsFolderPath);
|
||||
|
||||
for (var i = 0; i < modFiles.length; i++) {
|
||||
var modPath = path.resolve(toolsFolderPath, modFiles[i])
|
||||
|
||||
if (path.extname(modPath) === ".js") {
|
||||
var toolName = path.basename(modPath, ".js");
|
||||
mods[toolName] = require(modPath);
|
||||
}
|
||||
}
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
|
||||
function loadConfig() {
|
||||
var configFilePath = path.resolve(__dirname, configFileName)
|
||||
return JSON.parse(fs.readFileSync(configFilePath));
|
||||
}
|
||||
|
||||
|
||||
function getAllDocFilePaths(docFolder, files) {
|
||||
var items = fs.readdirSync(docFolder);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var itemPath = path.resolve(docFolder, items[i]);
|
||||
var itemInfo = fs.statSync(itemPath);
|
||||
|
||||
if (itemInfo.isFile()){
|
||||
files.push(itemPath);
|
||||
} else if (itemInfo.isDirectory()) {
|
||||
getAllDocFilePaths(itemPath, files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
program
|
||||
.usage("[options] <source>")
|
||||
.option("-p, --profile [profileName]", "Select named config profile", "index")
|
||||
.parse(process.argv);
|
||||
|
||||
var sourcePath;
|
||||
|
||||
if (program.args.length === 0) {
|
||||
sourcePath = path.resolve("..", "docs");
|
||||
} else {
|
||||
sourcePath = path.resolve(program.args[0]);
|
||||
}
|
||||
|
||||
var sourceInfo = fs.statSync(sourcePath);
|
||||
|
||||
var toolModules = loadToolModules();
|
||||
|
||||
var config = loadConfig();
|
||||
|
||||
var toolList;
|
||||
|
||||
if (config.profiles[program.profile]){
|
||||
toolList = config.profiles[program.profile];
|
||||
var toolListText = toolList.join(", ");
|
||||
console.log(`Using '${program.profile}' profile: ${toolListText}`);
|
||||
} else {
|
||||
console.log(`Aborting: unknown profile '${program.profile}`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var files = [];
|
||||
|
||||
if (sourceInfo.isDirectory()) {
|
||||
getAllDocFilePaths(sourcePath, files);
|
||||
} else if (sourceInfo.isFile()) {
|
||||
files = [ sourcePath ];
|
||||
}
|
||||
|
||||
files = files.filter(filename =>
|
||||
(path.extname(filename) === ".md") &&
|
||||
(filename !== "README.md")
|
||||
);
|
||||
|
||||
//files.forEach(element => console.log(element));
|
||||
|
||||
console.log("Initialising...");
|
||||
initPhase(aggData);
|
||||
|
||||
console.log("Analysing Markdown files...");
|
||||
readPhase(files, aggData);
|
||||
|
||||
console.log("Computing aggregate data...");
|
||||
aggPhase(aggData);
|
||||
|
||||
console.log("Updating Markdown files...");
|
||||
updatePhase(files, aggData);
|
||||
|
||||
|
||||
|
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"index": [
|
||||
"index",
|
||||
"versionIndex",
|
||||
"tutorialIndex"
|
||||
],
|
||||
"enhance": [
|
||||
"tsInfo",
|
||||
"toc"
|
||||
],
|
||||
"dev": [
|
||||
"tsInfo",
|
||||
"typeLinker"
|
||||
]
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
module.exports = searchLibraryRecursive;
|
||||
|
||||
var angFilenameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))\.ts/;
|
||||
var searchFolderOmitRegex = /(config)|(mock)|(i18n)|(assets)|(styles)/;
|
||||
|
||||
// Search source folders for .ts files to discover all components, directives, etc.
|
||||
function searchLibraryRecursive(srcData, folderPath) {
|
||||
var items = fs.readdirSync(folderPath);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var itemPath = path.resolve(folderPath, items[i]);
|
||||
var info = fs.statSync(itemPath);
|
||||
|
||||
if (info.isFile() && (items[i].match(angFilenameRegex))) {
|
||||
var nameNoSuffix = path.basename(items[i], '.ts');
|
||||
|
||||
var displayPath = itemPath.replace(/\\/g, '/');
|
||||
displayPath = displayPath.substr(displayPath.indexOf("lib") + 4);
|
||||
|
||||
// Type == "component", "directive", etc.
|
||||
var itemType = nameNoSuffix.split('.')[1];
|
||||
|
||||
srcData[nameNoSuffix] = { "path": displayPath, "type": itemType };
|
||||
} else if (info.isDirectory() && !items[i].match(searchFolderOmitRegex)) {
|
||||
searchLibraryRecursive(srcData, itemPath);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
module.exports = {
|
||||
"ngNameToDisplayName": ngNameToDisplayName,
|
||||
"dekebabifyName": dekebabifyName,
|
||||
"kebabifyClassName": kebabifyClassName,
|
||||
"classTypes": ["component", "directive", "model", "pipe", "service", "widget"]
|
||||
}
|
||||
|
||||
|
||||
function ngNameToDisplayName(ngName) {
|
||||
var mainSections = ngName.split(".");
|
||||
mainSections[0] = dekebabifyName(mainSections[0]);
|
||||
return mainSections.join(" ");
|
||||
}
|
||||
|
||||
|
||||
function displayNameToNgName(name) {
|
||||
var noSpaceName = ngName.replace(/ ([a-zA-Z])/, "$1".toUpperCase());
|
||||
return noSpaceName.substr(0, 1).toUpperCase() + noSpaceName.substr(1);
|
||||
}
|
||||
|
||||
|
||||
function dekebabifyName(name) {
|
||||
var result = name.replace(/-/g, " ");
|
||||
result = result.substr(0, 1).toUpperCase() + result.substr(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
function kebabifyClassName(name) {
|
||||
var result = name.replace(/(Component|Directive|Interface|Model|Pipe|Service|Widget)$/, match => {
|
||||
return "." + match.toLowerCase();
|
||||
});
|
||||
|
||||
result = result.replace(/([A-Z])/g, "-$1");
|
||||
return result.substr(1).toLowerCase();
|
||||
}
|
@@ -1,103 +0,0 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var process = require("process");
|
||||
var graphql_request_1 = require("graphql-request");
|
||||
var remark = require("remark");
|
||||
var frontMatter = require("remark-frontmatter");
|
||||
var yaml = require("js-yaml");
|
||||
var moment = require("moment");
|
||||
var Rx_1 = require("rxjs/Rx");
|
||||
var libsearch = require("./libsearch");
|
||||
var stoplist_1 = require("./stoplist");
|
||||
var adf20StartDate = "2017-11-20";
|
||||
var commitWeight = 0.1;
|
||||
var scoreTimeBase = 60;
|
||||
var rootFolder = ".";
|
||||
var stoplistFilePath = path.resolve("config", "DocProcessor", "commitStoplist.json");
|
||||
var angFilePattern = /(component)|(directive)|(model)|(pipe)|(service)|(widget)/;
|
||||
var srcData = {};
|
||||
var stoplist = new stoplist_1.Stoplist(stoplistFilePath);
|
||||
var docsFolderPath = path.resolve("..", "docs");
|
||||
var libFolders = ["core", "content-services", "process-services", "insights"];
|
||||
libsearch(srcData, path.resolve(rootFolder));
|
||||
/*
|
||||
let keys = Object.keys(srcData);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
console.log(keys[i]);
|
||||
}
|
||||
*/
|
||||
var authToken = process.env.graphAuthToken;
|
||||
var client = new graphql_request_1.GraphQLClient('https://api.github.com/graphql', {
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + authToken
|
||||
}
|
||||
});
|
||||
var query = "query commitHistory($path: String) {\n repository(name: \"alfresco-ng2-components\", owner: \"alfresco\") {\n ref(qualifiedName: \"development\") {\n target {\n ... on Commit {\n history(first: 15, path: $path) {\n nodes {\n pushedDate\n message\n }\n }\n }\n }\n }\n }\n}";
|
||||
var docFiles = getDocFilePaths(docsFolderPath);
|
||||
var docNames = Rx_1.Observable.from(docFiles);
|
||||
console.log("'Name','Review date','Commits since review','Score'");
|
||||
docNames.subscribe(function (x) {
|
||||
var key = path.basename(x, ".md");
|
||||
if (!srcData[key])
|
||||
return;
|
||||
var vars = {
|
||||
"path": "lib/" + srcData[key].path
|
||||
};
|
||||
client.request(query, vars).then(function (data) {
|
||||
var nodes = data["repository"].ref.target.history.nodes;
|
||||
var lastReviewDate = getDocReviewDate(x); //(key + ".md");
|
||||
var numUsefulCommits = extractCommitInfo(nodes, lastReviewDate, stoplist);
|
||||
var dateString = lastReviewDate.format("YYYY-MM-DD");
|
||||
var score = priorityScore(lastReviewDate, numUsefulCommits).toPrecision(3);
|
||||
console.log("'" + key + "','" + dateString + "','" + numUsefulCommits + "','" + score + "'");
|
||||
});
|
||||
});
|
||||
function priorityScore(reviewDate, numCommits) {
|
||||
var daysSinceReview = moment().diff(reviewDate, 'days');
|
||||
var commitScore = 2 + numCommits * commitWeight;
|
||||
return Math.pow(commitScore, daysSinceReview / scoreTimeBase);
|
||||
}
|
||||
function getDocReviewDate(docFileName) {
|
||||
var mdFilePath = path.resolve(docsFolderPath, docFileName);
|
||||
var mdText = fs.readFileSync(mdFilePath);
|
||||
var tree = remark().use(frontMatter, ["yaml"]).parse(mdText);
|
||||
var lastReviewDate = moment(adf20StartDate);
|
||||
if (tree.children[0].type == "yaml") {
|
||||
var metadata = yaml.load(tree.children[0].value);
|
||||
if (metadata["Last reviewed"])
|
||||
lastReviewDate = moment(metadata["Last reviewed"]);
|
||||
}
|
||||
return lastReviewDate;
|
||||
}
|
||||
function extractCommitInfo(commitNodes, cutOffDate, stoplist) {
|
||||
var numUsefulCommits = 0;
|
||||
commitNodes.forEach(function (element) {
|
||||
if (!stoplist.isRejected(element.message)) {
|
||||
var abbr = element.message.substr(0, 15);
|
||||
var commitDate = moment(element.pushedDate);
|
||||
if (commitDate.isAfter(cutOffDate)) {
|
||||
numUsefulCommits++;
|
||||
}
|
||||
}
|
||||
});
|
||||
return numUsefulCommits;
|
||||
}
|
||||
function getDocFilePaths(folderPath) {
|
||||
var result = [];
|
||||
libFolders.forEach(function (element) {
|
||||
var libPath = path.resolve(folderPath, element);
|
||||
var files = fs.readdirSync(libPath);
|
||||
files = files.filter(function (filename) {
|
||||
return (path.extname(filename) === ".md") &&
|
||||
(filename !== "README.md") &&
|
||||
(filename.match(angFilePattern));
|
||||
});
|
||||
files.forEach(function (element) {
|
||||
result.push(path.join(libPath, element));
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
@@ -1,164 +0,0 @@
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import * as process from "process"
|
||||
|
||||
import { GraphQLClient } from "graphql-request";
|
||||
import * as remark from "remark";
|
||||
import * as frontMatter from "remark-frontmatter";
|
||||
import * as yaml from "js-yaml";
|
||||
import * as moment from "moment";
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import * as libsearch from "./libsearch";
|
||||
import { Stoplist } from "./stoplist";
|
||||
import { last } from "rxjs/operator/last";
|
||||
|
||||
|
||||
const adf20StartDate = "2017-11-20";
|
||||
|
||||
const commitWeight = 0.1;
|
||||
const scoreTimeBase = 60;
|
||||
|
||||
const rootFolder = ".";
|
||||
const stoplistFilePath = path.resolve("config", "DocProcessor", "commitStoplist.json");
|
||||
|
||||
const angFilePattern = /(component)|(directive)|(model)|(pipe)|(service)|(widget)/;
|
||||
|
||||
let srcData = {};
|
||||
let stoplist = new Stoplist(stoplistFilePath);
|
||||
|
||||
let docsFolderPath = path.resolve("..", "docs");
|
||||
|
||||
let libFolders = ["core", "content-services", "process-services", "insights"];
|
||||
|
||||
libsearch(srcData, path.resolve(rootFolder));
|
||||
|
||||
/*
|
||||
let keys = Object.keys(srcData);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
console.log(keys[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
const authToken = process.env.graphAuthToken;
|
||||
|
||||
const client = new GraphQLClient('https://api.github.com/graphql', {
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + authToken
|
||||
}
|
||||
});
|
||||
|
||||
const query = `query commitHistory($path: String) {
|
||||
repository(name: "alfresco-ng2-components", owner: "alfresco") {
|
||||
ref(qualifiedName: "development") {
|
||||
target {
|
||||
... on Commit {
|
||||
history(first: 15, path: $path) {
|
||||
nodes {
|
||||
pushedDate
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
let docFiles = getDocFilePaths(docsFolderPath);
|
||||
|
||||
let docNames = Observable.from(docFiles);
|
||||
|
||||
console.log("'Name','Review date','Commits since review','Score'");
|
||||
|
||||
docNames.subscribe(x => {
|
||||
let key = path.basename(x, ".md");
|
||||
|
||||
if (!srcData[key])
|
||||
return;
|
||||
|
||||
let vars = {
|
||||
"path": "lib/" + srcData[key].path
|
||||
};
|
||||
|
||||
client.request(query, vars).then(data => {
|
||||
let nodes = data["repository"].ref.target.history.nodes;
|
||||
|
||||
let lastReviewDate = getDocReviewDate(x);//(key + ".md");
|
||||
|
||||
let numUsefulCommits = extractCommitInfo(nodes, lastReviewDate, stoplist);
|
||||
let dateString = lastReviewDate.format("YYYY-MM-DD");
|
||||
let score = priorityScore(lastReviewDate, numUsefulCommits).toPrecision(3);
|
||||
|
||||
console.log(`'${key}','${dateString}','${numUsefulCommits}','${score}'`);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function priorityScore(reviewDate, numCommits) {
|
||||
let daysSinceReview = moment().diff(reviewDate, 'days');
|
||||
let commitScore = 2 + numCommits * commitWeight;
|
||||
return Math.pow(commitScore, daysSinceReview / scoreTimeBase);
|
||||
}
|
||||
|
||||
|
||||
function getDocReviewDate(docFileName) {
|
||||
let mdFilePath = path.resolve(docsFolderPath, docFileName);
|
||||
|
||||
let mdText = fs.readFileSync(mdFilePath);
|
||||
let tree = remark().use(frontMatter, ["yaml"]).parse(mdText);
|
||||
|
||||
let lastReviewDate = moment(adf20StartDate);
|
||||
|
||||
if (tree.children[0].type == "yaml") {
|
||||
let metadata = yaml.load(tree.children[0].value);
|
||||
|
||||
if (metadata["Last reviewed"])
|
||||
lastReviewDate = moment(metadata["Last reviewed"]);
|
||||
}
|
||||
|
||||
return lastReviewDate;
|
||||
}
|
||||
|
||||
|
||||
function extractCommitInfo(commitNodes, cutOffDate, stoplist) {
|
||||
let numUsefulCommits = 0;
|
||||
|
||||
commitNodes.forEach(element => {
|
||||
if (!stoplist.isRejected(element.message)) {
|
||||
let abbr = element.message.substr(0, 15);
|
||||
|
||||
let commitDate = moment(element.pushedDate);
|
||||
|
||||
if (commitDate.isAfter(cutOffDate)) {
|
||||
numUsefulCommits++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return numUsefulCommits;
|
||||
}
|
||||
|
||||
|
||||
function getDocFilePaths(folderPath) {
|
||||
let result = [];
|
||||
|
||||
libFolders.forEach(element => {
|
||||
let libPath = path.resolve(folderPath, element);
|
||||
let files = fs.readdirSync(libPath);
|
||||
|
||||
files = files.filter(filename =>
|
||||
(path.extname(filename) === ".md") &&
|
||||
(filename !== "README.md") &&
|
||||
(filename.match(angFilePattern))
|
||||
);
|
||||
|
||||
files.forEach(element => {
|
||||
result.push(path.join(libPath, element));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
return result;
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var fs = require("fs");
|
||||
/* "Stoplist" of regular expressions to match against strings. */
|
||||
var Stoplist = /** @class */ (function () {
|
||||
function Stoplist(slFilePath) {
|
||||
var listExpressions = JSON.parse(fs.readFileSync(slFilePath, 'utf8'));
|
||||
this.regexes = [];
|
||||
if (listExpressions) {
|
||||
for (var i = 0; i < listExpressions.length; i++) {
|
||||
this.regexes.push(new RegExp(listExpressions[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.regexes = [];
|
||||
}
|
||||
}
|
||||
// Check if an item is covered by the stoplist and reject it if so.
|
||||
Stoplist.prototype.isRejected = function (itemName) {
|
||||
for (var i = 0; i < this.regexes.length; i++) {
|
||||
if (this.regexes[i].test(itemName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return Stoplist;
|
||||
}());
|
||||
exports.Stoplist = Stoplist;
|
@@ -1,31 +0,0 @@
|
||||
import * as fs from "fs";
|
||||
|
||||
/* "Stoplist" of regular expressions to match against strings. */
|
||||
export class Stoplist {
|
||||
regexes: RegExp[];
|
||||
|
||||
constructor(slFilePath: string) {
|
||||
let listExpressions = JSON.parse(fs.readFileSync(slFilePath, 'utf8'));
|
||||
this.regexes = [];
|
||||
|
||||
if (listExpressions) {
|
||||
for (var i = 0; i < listExpressions.length; i++) {
|
||||
this.regexes.push(new RegExp(listExpressions[i]));
|
||||
}
|
||||
} else {
|
||||
this.regexes = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Check if an item is covered by the stoplist and reject it if so.
|
||||
isRejected(itemName: string) {
|
||||
for (var i = 0; i < this.regexes.length; i++) {
|
||||
if (this.regexes[i].test(itemName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
{% if hasInputs %}
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| -- | -- | -- | -- |
|
||||
{% each properties as prop %}
|
||||
{% if prop.isInput %}
|
||||
| {{{prop.name}}} | `{{{prop.type}}}` | {{{prop.defaultValue}}} | {{{prop.docText}}} |
|
||||
{% endif %}
|
||||
{% endeach %}
|
||||
{% endif %}
|
||||
{% if hasOutputs%}
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| -- | -- | -- |
|
||||
{% each properties as prop %}
|
||||
{% if prop.isOutput %}
|
||||
| {{prop.name}} | `{{{prop.type}}}` | {{{prop.docText}}} |
|
||||
{% endif %}
|
||||
{% endeach %}
|
||||
{% endif %}
|
@@ -1,23 +0,0 @@
|
||||
{% if hasInputs %}
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| -- | -- | -- | -- |
|
||||
{% each properties as prop %}
|
||||
{% if prop.isInput %}
|
||||
| {{{prop.name}}} | `{{{prop.type}}}` | {{{prop.defaultValue}}} | {{{prop.docText}}} |
|
||||
{% endif %}
|
||||
{% endeach %}
|
||||
{% endif %}
|
||||
{% if hasOutputs%}
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| -- | -- | -- |
|
||||
{% each properties as prop %}
|
||||
{% if prop.isOutput %}
|
||||
| {{prop.name}} | `{{{prop.type}}}` | {{{prop.docText}}} |
|
||||
{% endif %}
|
||||
{% endeach %}
|
||||
{% endif %}
|
@@ -1,14 +0,0 @@
|
||||
|
||||
{% if hasMethods %}
|
||||
### Methods
|
||||
|
||||
{% each methods as meth %}- `{{meth.name}}{{{meth.signature}}{% if meth.returnsSomething %}: {{{meth.returnType}}}{% endif %}`<br/>
|
||||
{{meth.docText}}
|
||||
{% each meth.params as param %}
|
||||
- `{{{param.combined}}}` - {% if param.isOptional %}(Optional){% endif %}{{{param.docText}}}
|
||||
{% endeach %}
|
||||
{% if meth.returnsSomething %}
|
||||
- **Returns** `{{{meth.returnType}}}` - {{{meth.returnDocText}}}
|
||||
{% endif %}
|
||||
{% endeach %}
|
||||
{% endif %}
|
@@ -1,5 +0,0 @@
|
||||
| Name | Level | Abstract |
|
||||
| -- | -- | -- |
|
||||
{% each tuts as tut %}
|
||||
| [**{{tut.title}}**]({{tut.link}}) | {{tut.level}} | {{tut.briefDesc}} |
|
||||
{% endeach %}
|
@@ -1,3 +0,0 @@
|
||||
{% each items as item %}
|
||||
- [{{item.title}}]({{item.link}})
|
||||
{% endeach %}
|
@@ -1,401 +0,0 @@
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var remark = require("remark");
|
||||
var stringify = require("remark-stringify");
|
||||
var zone = require("mdast-zone");
|
||||
var yaml = require("js-yaml");
|
||||
|
||||
var unist = require("../unistHelpers");
|
||||
var ngHelpers = require("../ngHelpers");
|
||||
var searchLibraryRecursive = require("../libsearch");
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
}
|
||||
|
||||
var angFilenameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))\.ts/;
|
||||
var searchFolderOmitRegex = /(config)|(mock)|(i18n)|(assets)|(styles)/;
|
||||
|
||||
var docsFolderPath = path.resolve("..", "docs");
|
||||
var undocStoplistFileName = path.resolve(docsFolderPath, "undocStoplist.json");
|
||||
var rootFolder = ".";
|
||||
var indexMdFilePath = path.resolve(docsFolderPath, "README.md");
|
||||
|
||||
var guideFolderName = "user-guide";
|
||||
var guideSummaryFileName = path.resolve(docsFolderPath, guideFolderName, "summary.json");
|
||||
|
||||
var maxBriefDescLength = 180;
|
||||
|
||||
var adfLibNames = ["core", "content-services", "insights", "process-services"];
|
||||
|
||||
var deprecatedIconURL = "docassets/images/DeprecatedIcon.png";
|
||||
var experimentalIconURL = "docassets/images/ExperimentalIcon.png";
|
||||
|
||||
|
||||
function initPhase(aggData) {
|
||||
aggData.stoplist = makeStoplist(undocStoplistFileName);
|
||||
aggData.srcData = {};
|
||||
aggData.mdFileDesc = [];
|
||||
aggData.mdFileStatus = [];
|
||||
aggData.mdFilePath = [];
|
||||
searchLibraryRecursive(aggData.srcData, path.resolve(rootFolder));
|
||||
|
||||
//console.log(JSON.stringify(aggData.srcData));
|
||||
}
|
||||
|
||||
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
var itemName = path.basename(pathname, ".md");
|
||||
|
||||
// Look for the first paragraph in the file by skipping other items.
|
||||
// Should usually be at position 1 in the tree.
|
||||
var s;
|
||||
var briefDesc;
|
||||
|
||||
if (tree.children[0].type == "yaml")
|
||||
s = 1;
|
||||
else
|
||||
s = 0;
|
||||
|
||||
for (;
|
||||
(s < tree.children.length) && !unist.isParagraph(tree.children[s]);
|
||||
s++
|
||||
);
|
||||
|
||||
if (s < tree.children.length) {
|
||||
briefDesc = tree.children[s];
|
||||
}
|
||||
|
||||
aggData.mdFileDesc[itemName] = briefDesc;
|
||||
|
||||
if (tree.children[0].type == "yaml") {
|
||||
var metadata = yaml.load(tree.children[0].value);
|
||||
var status = metadata["Status"];
|
||||
|
||||
if (status) {
|
||||
var compName = path.basename(pathname, ".md");
|
||||
aggData.mdFileStatus[compName] = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var linkPath = pathname.replace(/\\/g, '/');
|
||||
linkPath = linkPath.substr(linkPath.indexOf("docs") + 5);
|
||||
aggData.mdFilePath[itemName] = linkPath;
|
||||
}
|
||||
|
||||
function aggPhase(aggData) {
|
||||
var sections = prepareIndexSections(aggData);
|
||||
//console.log(JSON.stringify(sections));
|
||||
|
||||
var indexFileText = fs.readFileSync(indexMdFilePath, "utf8");
|
||||
var indexFileTree = remark().parse(indexFileText);
|
||||
|
||||
for (var l = 0; l < adfLibNames.length; l++) {
|
||||
|
||||
var libName = adfLibNames[l];
|
||||
var libSection = sections[libName];
|
||||
|
||||
var md = makeLibSectionMD(libSection, false);
|
||||
|
||||
zone(indexFileTree, libName, (startComment, oldSection, endComment) => {
|
||||
md.unshift(startComment);
|
||||
md.push(endComment);
|
||||
return md;
|
||||
});
|
||||
|
||||
md = makeLibSectionMD(libSection, true);
|
||||
|
||||
var subIndexFilePath = path.resolve(docsFolderPath, libName, "README.md");
|
||||
var subIndexText = fs.readFileSync(subIndexFilePath, "utf8");
|
||||
var subIndexTree = remark().parse(subIndexText);
|
||||
|
||||
zone(subIndexTree, libName, (startComment, oldSection, endComment) => {
|
||||
md.unshift(startComment);
|
||||
md.push(endComment);
|
||||
return md;
|
||||
});
|
||||
|
||||
subIndexText = remark().data("settings", {paddedTable: false}).stringify(subIndexTree);
|
||||
fs.writeFileSync(subIndexFilePath, subIndexText);
|
||||
}
|
||||
|
||||
var guideSection = buildGuideSection(guideSummaryFileName, false);
|
||||
|
||||
zone(indexFileTree, "guide", (startComment, oldSection, endComment) => {
|
||||
return [
|
||||
startComment, guideSection, endComment
|
||||
]
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.resolve("..", "docs", "README.md"), remark().data("settings", {paddedTable: false}).stringify(indexFileTree));
|
||||
|
||||
guideSection = buildGuideSection(guideSummaryFileName, true);
|
||||
|
||||
subIndexFilePath = path.resolve(docsFolderPath, "user-guide", "README.md");
|
||||
subIndexText = fs.readFileSync(subIndexFilePath, "utf8");
|
||||
subIndexTree = remark().parse(subIndexText);
|
||||
|
||||
zone(subIndexTree, "guide", (startComment, oldSection, endComment) => {
|
||||
return [
|
||||
startComment, guideSection, endComment
|
||||
]
|
||||
});
|
||||
|
||||
subIndexText = remark().data("settings", {paddedTable: false}).stringify(subIndexTree);
|
||||
fs.writeFileSync(subIndexFilePath, subIndexText);
|
||||
|
||||
//fs.writeFileSync(indexMdFilePath, remark().stringify(indexFileTree));
|
||||
}
|
||||
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Create a stoplist of regular expressions.
|
||||
function makeStoplist(slFilePath) {
|
||||
var listExpressions = JSON.parse(fs.readFileSync(slFilePath, 'utf8'));
|
||||
|
||||
var result = [];
|
||||
|
||||
for (var i = 0; i < listExpressions.length; i++) {
|
||||
result.push(new RegExp(listExpressions[i]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if an item is covered by the stoplist and reject it if so.
|
||||
function rejectItemViaStoplist(stoplist, itemName) {
|
||||
for (var i = 0; i < stoplist.length; i++) {
|
||||
if (stoplist[i].test(itemName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function prepareIndexSections(aggData) {
|
||||
var srcNames = Object.keys(aggData.srcData);
|
||||
var sections = initEmptySections();
|
||||
|
||||
for (var i = 0; i < srcNames.length; i++) {
|
||||
var itemName = srcNames[i];
|
||||
var srcData = aggData.srcData[itemName];
|
||||
var libName = srcData.path.substr(0, srcData.path.indexOf("/"));
|
||||
|
||||
var briefDesc = aggData.mdFileDesc[itemName];
|
||||
|
||||
var displayName = ngHelpers.ngNameToDisplayName(itemName);
|
||||
var pathname = aggData.mdFilePath[itemName];
|
||||
|
||||
var status = "";
|
||||
|
||||
if (aggData.mdFileStatus[itemName])
|
||||
status = aggData.mdFileStatus[itemName];
|
||||
|
||||
if (briefDesc) {
|
||||
sections[libName][srcData.type].documented.push({
|
||||
"displayName": displayName,
|
||||
"mdName": itemName + ".md",
|
||||
"mdPath": pathname,
|
||||
"srcPath": srcData.path,
|
||||
"briefDesc": briefDesc,
|
||||
"status": status
|
||||
});
|
||||
} else if (!rejectItemViaStoplist(aggData.stoplist, itemName)) {
|
||||
sections[libName][srcData.type].undocumented.push({
|
||||
"displayName": displayName,
|
||||
"mdName": itemName + ".md",
|
||||
"srcPath": srcData.path
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
|
||||
function initEmptySections() {
|
||||
var result = {};
|
||||
|
||||
for (var l = 0; l < adfLibNames.length; l++) {
|
||||
var lib = result[adfLibNames[l]] = {};
|
||||
|
||||
for (var c = 0; c < ngHelpers.classTypes.length; c++) {
|
||||
var classType = lib[ngHelpers.classTypes[c]] = {};
|
||||
|
||||
classType.undocumented = [];
|
||||
classType.documented = [];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function buildMDDocumentedTable(docItems, forSubFolder) {
|
||||
var rows = [
|
||||
|
||||
];
|
||||
|
||||
for (var i = 0; i < docItems.length; i++) {
|
||||
rows.push(makeMDDocumentedTableRow(docItems[i], forSubFolder));
|
||||
}
|
||||
|
||||
return rows;
|
||||
//return unist.makeTable([null, null, null, null], rows);
|
||||
}
|
||||
|
||||
|
||||
function buildMDUndocumentedTable(docItems, forSubFolder) {
|
||||
var rows = [
|
||||
|
||||
];
|
||||
|
||||
for (var i = 0; i < docItems.length; i++) {
|
||||
rows.push(makeMDUndocumentedTableRow(docItems[i], forSubFolder));
|
||||
}
|
||||
|
||||
return rows;
|
||||
//return unist.makeTable([null, null, null, null], rows);
|
||||
}
|
||||
|
||||
|
||||
function makeMDDocumentedTableRow(docItem, forSubFolder) {
|
||||
var mdPath = docItem.mdPath;
|
||||
|
||||
if (forSubFolder) {
|
||||
mdPath = path.basename(mdPath);
|
||||
}
|
||||
|
||||
var mdFileLink = unist.makeLink(unist.makeText(docItem.displayName), mdPath);
|
||||
|
||||
var srcPath = "../lib/" + docItem.srcPath;
|
||||
|
||||
if (forSubFolder) {
|
||||
srcPath = "../" + srcPath;
|
||||
}
|
||||
|
||||
var srcFileLink = unist.makeLink(unist.makeText("Source"), srcPath);
|
||||
var desc = docItem.briefDesc;
|
||||
|
||||
var linkCellItems = [mdFileLink];
|
||||
|
||||
var finalDepIconURL = deprecatedIconURL;
|
||||
var finalExIconURL = experimentalIconURL;
|
||||
|
||||
if (forSubFolder) {
|
||||
finalDepIconURL = "../" + finalDepIconURL;
|
||||
finalExIconURL = "../" + finalExIconURL;
|
||||
}
|
||||
|
||||
if (docItem.status) {
|
||||
if (docItem.status === "Deprecated") {
|
||||
linkCellItems.push(unist.makeText(" "));
|
||||
linkCellItems.push(unist.makeImage(finalDepIconURL, "Deprecated"));
|
||||
} else if (docItem.status === "Experimental") {
|
||||
linkCellItems.push(unist.makeText(" "));
|
||||
linkCellItems.push(unist.makeImage(finalExIconURL, "Experimental"));
|
||||
}
|
||||
}
|
||||
|
||||
return unist.makeTableRow([
|
||||
unist.makeTableCell(linkCellItems),
|
||||
unist.makeTableCell([desc]),
|
||||
unist.makeTableCell([srcFileLink])
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function makeMDUndocumentedTableRow(docItem, forSubFolder) {
|
||||
var itemName = unist.makeText(docItem.displayName);
|
||||
var srcPath = "../lib/" + docItem.srcPath;
|
||||
|
||||
if (forSubFolder) {
|
||||
srcPath = "../" + srcPath;
|
||||
}
|
||||
|
||||
var srcFileLink = unist.makeLink(unist.makeText("Source"), srcPath);
|
||||
|
||||
return unist.makeTableRow([
|
||||
unist.makeTableCell([unist.makeEmphasis([itemName])]),
|
||||
unist.makeTableCell([unist.makeEmphasis([unist.makeText("Not currently documented")])]),
|
||||
unist.makeTableCell([srcFileLink])
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function makeLibSectionMD(libSection, forSubFolder){
|
||||
var md = [];
|
||||
|
||||
var libClassTypes = Object.keys(libSection);
|
||||
|
||||
for (var i = 0; i < libClassTypes.length; i++) {
|
||||
var classType = libClassTypes[i];
|
||||
|
||||
var classSection = libSection[classType];
|
||||
|
||||
if (!classSection)
|
||||
continue;
|
||||
|
||||
var displayNameNode;
|
||||
|
||||
if ((classSection.documented.length > 0) || (classSection.undocumented.length > 0)) {
|
||||
displayNameNode = unist.makeText(ngHelpers.dekebabifyName(classType + "s"));
|
||||
md.push(unist.makeHeading(displayNameNode, 2));
|
||||
|
||||
var tableRows = [
|
||||
unist.makeTableRow([
|
||||
unist.makeTableCell([unist.makeText("Name")]),
|
||||
unist.makeTableCell([unist.makeText("Description")]),
|
||||
unist.makeTableCell([unist.makeText("Source link")])
|
||||
])
|
||||
];
|
||||
|
||||
if (classSection.documented.length > 0) {
|
||||
//md.push(buildMDDocumentedSection(classSection.documented));
|
||||
tableRows = tableRows.concat(buildMDDocumentedTable(classSection.documented, forSubFolder));
|
||||
}
|
||||
|
||||
if (classSection.undocumented.length > 0) {
|
||||
// md.push(buildMDUndocumentedSection(classSection.undocumented));
|
||||
tableRows = tableRows.concat(buildMDUndocumentedTable(classSection.undocumented, forSubFolder));
|
||||
}
|
||||
|
||||
md.push(unist.makeTable([null, null, null, null], tableRows));
|
||||
}
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
|
||||
function buildGuideSection(guideJsonFilename, forSubFolder) {
|
||||
var summary = JSON.parse(fs.readFileSync(guideJsonFilename, "utf8"));
|
||||
|
||||
var listItems = [];
|
||||
|
||||
for (var i = 0; i < summary.length; i++) {
|
||||
var filePath = summary[i].file;
|
||||
|
||||
if (!forSubFolder) {
|
||||
filePath = guideFolderName + "/" + filePath;
|
||||
}
|
||||
|
||||
if (summary[i].title !== "Tutorials") {
|
||||
var link = unist.makeLink(unist.makeText(summary[i].title), filePath);
|
||||
listItems.push(unist.makeListItem(link));
|
||||
}
|
||||
}
|
||||
|
||||
return unist.makeListUnordered(listItems);
|
||||
}
|
@@ -1,175 +0,0 @@
|
||||
var path = require("path");
|
||||
var getSection = require("mdast-util-heading-range");
|
||||
|
||||
var unist = require("../unistHelpers");
|
||||
|
||||
var seeAlsoHeading = "See Also";
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
}
|
||||
|
||||
|
||||
function initPhase(aggData) {
|
||||
aggData.saGraph = {};
|
||||
aggData.saUpdateGraph = {};
|
||||
}
|
||||
|
||||
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
var saHeadingOffset = findSeeAlsoSection(tree);
|
||||
|
||||
var saNode = [];
|
||||
|
||||
if (saHeadingOffset !== -1) {
|
||||
// Skip over non-list parts.
|
||||
var s;
|
||||
|
||||
for (
|
||||
s = saHeadingOffset;
|
||||
(s < tree.children.length) && !unist.isListUnordered(tree.children[s]);
|
||||
s++
|
||||
);
|
||||
|
||||
if ((s < tree.children.length) && unist.isListUnordered(tree.children[s])) {
|
||||
var list = tree.children[s];
|
||||
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
var itemLink = getItemLinkInfo(list.children[i]);
|
||||
|
||||
if (itemLink) {
|
||||
saNode.push(itemLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aggData.saGraph[path.basename(pathname, ".md")] = saNode;
|
||||
}
|
||||
|
||||
|
||||
function aggPhase(aggData) {
|
||||
aggData.saUpdateGraph = tidyGraph(aggData.saGraph);
|
||||
}
|
||||
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
var currNodeName = path.basename(pathname, ".md");
|
||||
var currNodeArcs = aggData.saUpdateGraph[currNodeName];
|
||||
|
||||
if (currNodeArcs.length > 0) {
|
||||
var saListItems = [];
|
||||
|
||||
for (var i = 0; i < currNodeArcs.length; i++) {
|
||||
var linkText = graphKeyToLinkName(currNodeArcs[i]);
|
||||
var linkTarget = currNodeArcs[i] + ".md";
|
||||
var link = unist.makeLink(unist.makeText(linkText), linkTarget);
|
||||
saListItems.push(unist.makeListItem(link));
|
||||
}
|
||||
|
||||
var saHeadingOffset = findSeeAlsoSection(tree);
|
||||
|
||||
if (saHeadingOffset !== -1) {
|
||||
// Skip over non-list parts.
|
||||
var s;
|
||||
|
||||
for (
|
||||
s = saHeadingOffset;
|
||||
(s < tree.children.length) && !unist.isListUnordered(tree.children[s]);
|
||||
s++
|
||||
);
|
||||
|
||||
// Push all elements of the items array as if they were separate elements.
|
||||
Array.prototype.push.apply(tree.children[s].children, saListItems);
|
||||
} else {
|
||||
// This file doesn't currently have a See Also section, so add one at the end.
|
||||
tree.children.push(unist.makeHeading(unist.makeText(seeAlsoHeading), 2));
|
||||
tree.children.push(unist.makeListUnordered(saListItems));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function graphKeyToLinkName(key) {
|
||||
var mainSections = key.split(".");
|
||||
mainSections[0] = tidyName(mainSections[0]);
|
||||
return mainSections.join(" ");
|
||||
}
|
||||
|
||||
// Convert an Angular-style name (eg, "card-view") into one with correct spaces and uppercase (eg, "Card view").
|
||||
function tidyName(name) {
|
||||
var result = name.replace(/-/g, " ");
|
||||
result = result.substr(0, 1).toUpperCase() + result.substr(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function makeEmptySAList() {
|
||||
var result = [];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Makes link symmetrical between items (ie, if A links to B but not the other way
|
||||
// around then it adds the missing link).
|
||||
function tidyGraph(graph) {
|
||||
var nodeNames = Object.keys(graph);
|
||||
var result = {};
|
||||
|
||||
for (var n = 0; n < nodeNames.length; n++) {
|
||||
result[nodeNames[n]] = [];
|
||||
}
|
||||
|
||||
for (var n = 0; n < nodeNames.length; n++) {
|
||||
var currNodeName = nodeNames[n];
|
||||
|
||||
var currNodeArcs = graph[currNodeName];
|
||||
|
||||
for (var a = 0; a < currNodeArcs.length; a++) {
|
||||
var linkedNode = graph[currNodeArcs[a]];
|
||||
var resultNode = result[currNodeArcs[a]];
|
||||
|
||||
if (!linkedNode) {
|
||||
console.log(`Warning: item '${currNodeArcs[a]}' (in See Also section of '${currNodeName}') has no corresponding file`);
|
||||
} else if (linkedNode.indexOf(currNodeName) === -1) {
|
||||
linkedNode.push(currNodeName);
|
||||
resultNode.push(currNodeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function findSeeAlsoSection(tree) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < tree.children.length; i++) {
|
||||
var child = tree.children[i];
|
||||
|
||||
if (unist.isHeading(child) && (child.children[0].value.toLowerCase() === seeAlsoHeading.toLowerCase()))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function getItemLinkInfo(listItem) {
|
||||
var linkTarget = listItem.children[0].children[0].url;
|
||||
|
||||
if (linkTarget.startsWith("http:") ||
|
||||
linkTarget.startsWith("#") ||
|
||||
!linkTarget.endsWith(".md"))
|
||||
return null;
|
||||
else
|
||||
return path.basename(linkTarget, ".md");
|
||||
}
|
||||
|
@@ -1,93 +0,0 @@
|
||||
var remark = require("remark");
|
||||
var tocGenerator = require("mdast-util-toc");
|
||||
var replaceSection = require("mdast-util-heading-range");
|
||||
|
||||
var unist = require("../unistHelpers");
|
||||
|
||||
const contentsHeading = "Contents";
|
||||
const minHeadingsForToc = 8;
|
||||
const maxTocHeadingDepth = 3;
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
}
|
||||
|
||||
function initPhase(aggData) {}
|
||||
function readPhase(tree, pathname, aggData) {}
|
||||
function aggPhase(aggData) {}
|
||||
|
||||
|
||||
// Find an existing Contents section or add a new empty one if needed.
|
||||
// Returns true if section is present/needed, false if not needed.
|
||||
function establishContentsSection(mdTree) {
|
||||
var firstL2HeadingPos = -1;
|
||||
var numTocHeadings = 0;
|
||||
var foundContentsHeading = false;
|
||||
|
||||
for (var i = 0; i < mdTree.children.length; i++) {
|
||||
var child = mdTree.children[i];
|
||||
|
||||
// Look through all headings.
|
||||
if (child.type === "heading") {
|
||||
|
||||
if ((child.depth > 1) && (child.depth <= maxTocHeadingDepth)) {
|
||||
numTocHeadings++;
|
||||
}
|
||||
|
||||
if (child.depth === 2) {
|
||||
// Note where the first L2 heading is.
|
||||
if (firstL2HeadingPos === -1) {
|
||||
firstL2HeadingPos = i;
|
||||
}
|
||||
|
||||
// If it is also a Contents heading then we're done. We don't include the
|
||||
// Contents heading itself within the ToC, so decrement the count for that.
|
||||
if ((child.children[0].value === contentsHeading) && !foundContentsHeading) {
|
||||
foundContentsHeading = true;
|
||||
numTocHeadings--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here then a level 2 Contents heading was not found.
|
||||
// If there are enough headings for a ToC to be necessary then
|
||||
// add one in the right place.
|
||||
if (!foundContentsHeading) {
|
||||
var newContsHeading = unist.makeHeading(unist.makeText(contentsHeading), 2);
|
||||
|
||||
// If we found another L2 heading then add the Contents in just before it.
|
||||
if (firstL2HeadingPos != -1) {
|
||||
mdTree.children.splice(firstL2HeadingPos, 0, newContsHeading);
|
||||
} else {
|
||||
// Otherwise, the unlikely situation where a ToC is required but there
|
||||
// are no L2 headings! Add it as the second element in the document.
|
||||
mdTree.children.splice(1, 0, newContsHeading);
|
||||
}
|
||||
}
|
||||
|
||||
return numTocHeadings;
|
||||
}
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
// If we need a contents section then add one or update the existing one.
|
||||
var numTocHeadings = establishContentsSection(tree);
|
||||
|
||||
if (numTocHeadings >= minHeadingsForToc) {
|
||||
var newToc = tocGenerator(tree, {heading: contentsHeading, maxDepth: 3});
|
||||
|
||||
replaceSection(tree, contentsHeading, function(before, oldSection, after) {
|
||||
return [before, newToc.map, after];
|
||||
});
|
||||
} else {
|
||||
// Otherwise, we don't need one, so remove any existing one.
|
||||
replaceSection(tree, contentsHeading, function(before, oldSection, after) {
|
||||
return [after];
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@@ -1,275 +0,0 @@
|
||||
"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 combyne = require("combyne");
|
||||
var typedoc_1 = require("typedoc");
|
||||
var libFolders = ["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",
|
||||
"text-mask.component": "InputMaskDirective",
|
||||
"card-item-types.service": "CardItemTypeService"
|
||||
};
|
||||
var undocMethodNames = {
|
||||
"ngOnChanges": 1
|
||||
};
|
||||
var PropInfo = /** @class */ (function () {
|
||||
function PropInfo(rawProp) {
|
||||
var _this = this;
|
||||
this.errorMessages = [];
|
||||
this.name = rawProp.name;
|
||||
this.docText = rawProp.comment ? rawProp.comment.shortText : "";
|
||||
this.docText = this.docText.replace(/[\n\r]+/g, " ").trim();
|
||||
this.defaultValue = rawProp.defaultValue || "";
|
||||
this.defaultValue = this.defaultValue.replace(/\|/, "\\|");
|
||||
this.type = rawProp.type ? rawProp.type.toString() : "";
|
||||
this.isDeprecated = rawProp.comment && rawProp.comment.hasTag("deprecated");
|
||||
if (this.isDeprecated) {
|
||||
this.docText = "**Deprecated:** " + rawProp.comment.getTag("deprecated").text.replace(/[\n\r]+/g, " ").trim();
|
||||
}
|
||||
if (rawProp.decorators) {
|
||||
rawProp.decorators.forEach(function (dec) {
|
||||
//console.log(dec);
|
||||
if (dec.name === "Input") {
|
||||
_this.isInput = true;
|
||||
if (dec.arguments) {
|
||||
var bindingName = dec.arguments["bindingPropertyName"];
|
||||
if (bindingName && (bindingName !== ""))
|
||||
_this.name = bindingName.replace(/['"]/g, "");
|
||||
}
|
||||
if (!_this.docText && !_this.isDeprecated) {
|
||||
_this.errorMessages.push("Warning: Input \"" + rawProp.name + "\" has no doc text.");
|
||||
}
|
||||
}
|
||||
if (dec.name === "Output") {
|
||||
_this.isOutput = true;
|
||||
if (!_this.docText && !_this.isDeprecated) {
|
||||
_this.errorMessages.push("Warning: Output \"" + rawProp.name + "\" has no doc text.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Object.defineProperty(PropInfo.prototype, "errors", {
|
||||
get: function () {
|
||||
return this.errorMessages;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
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, " ").trim();
|
||||
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.errorMessages = [];
|
||||
this.name = rawSig.name;
|
||||
this.returnType = rawSig.type ? rawSig.type.toString() : "";
|
||||
this.returnsSomething = this.returnType != "void";
|
||||
if (rawSig.hasComment()) {
|
||||
this.docText = rawSig.comment.shortText + rawSig.comment.text;
|
||||
this.docText = this.docText.replace(/[\n\r]+/g, " ").trim();
|
||||
if (!this.docText) {
|
||||
this.errorMessages.push("Warning: method \"" + rawSig.name + "\" has no doc text.");
|
||||
}
|
||||
this.returnDocText = rawSig.comment.returns;
|
||||
this.returnDocText = this.returnDocText ? this.returnDocText.replace(/[\n\r]+/g, " ").trim() : "";
|
||||
if (this.returnDocText.toLowerCase() === "nothing") {
|
||||
this.returnsSomething = false;
|
||||
}
|
||||
if (this.returnsSomething && !this.returnDocText) {
|
||||
this.errorMessages.push("Warning: Return value of method \"" + rawSig.name + "\" has no doc text.");
|
||||
}
|
||||
this.isDeprecated = rawSig.comment.hasTag("deprecated");
|
||||
}
|
||||
this.params = [];
|
||||
var paramStrings = [];
|
||||
if (rawSig.parameters) {
|
||||
rawSig.parameters.forEach(function (rawParam) {
|
||||
if (!rawParam.comment || !rawParam.comment.text) {
|
||||
_this.errorMessages.push("Warning: parameter \"" + rawParam.name + "\" of method \"" + rawSig.name + "\" has no doc text.");
|
||||
}
|
||||
var param = new ParamInfo(rawParam);
|
||||
_this.params.push(param);
|
||||
paramStrings.push(param.combined);
|
||||
});
|
||||
}
|
||||
this.signature = "(" + paramStrings.join(", ") + ")";
|
||||
}
|
||||
Object.defineProperty(MethodSigInfo.prototype, "errors", {
|
||||
get: function () {
|
||||
return this.errorMessages;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return MethodSigInfo;
|
||||
}());
|
||||
var ComponentInfo = /** @class */ (function () {
|
||||
function ComponentInfo(classRef) {
|
||||
var _this = this;
|
||||
var props = classRef.getChildrenByKind(typedoc_1.ReflectionKind.Property);
|
||||
var accessors = classRef.getChildrenByKind(typedoc_1.ReflectionKind.Accessor);
|
||||
this.properties = props.concat(accessors).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 || undocMethodNames[method.name])) {
|
||||
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;
|
||||
}
|
||||
Object.defineProperty(ComponentInfo.prototype, "errors", {
|
||||
get: function () {
|
||||
var combinedErrors = [];
|
||||
this.methods.forEach(function (method) {
|
||||
method.errors.forEach(function (err) {
|
||||
combinedErrors.push(err);
|
||||
});
|
||||
});
|
||||
this.properties.forEach(function (prop) {
|
||||
prop.errors.forEach(function (err) {
|
||||
combinedErrors.push(err);
|
||||
});
|
||||
});
|
||||
return combinedErrors;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return ComponentInfo;
|
||||
}());
|
||||
function initPhase(aggData) {
|
||||
var app = new typedoc_1.Application({
|
||||
exclude: excludePatterns,
|
||||
ignoreCompilerErrors: true,
|
||||
experimentalDecorators: true,
|
||||
tsconfig: "tsconfig.json"
|
||||
});
|
||||
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, errorMessages) {
|
||||
var compName = angNameToClassName(path.basename(pathname, ".md"));
|
||||
var classRef = aggData.projData.findReflectionByName(compName);
|
||||
if (!classRef) {
|
||||
// A doc file with no corresponding class (eg, Document Library Model).
|
||||
return false;
|
||||
}
|
||||
var compData = new ComponentInfo(classRef);
|
||||
var classType = compName.match(/component|directive|service/i);
|
||||
if (classType) {
|
||||
var templateName = path.resolve(templateFolder, classType + ".combyne");
|
||||
var templateSource = fs.readFileSync(templateName, "utf8");
|
||||
var template = combyne(templateSource);
|
||||
var mdText = template.render(compData);
|
||||
mdText = mdText.replace(/^ +\|/mg, "|");
|
||||
var newSection_1 = remark().data("settings", { paddedTable: false, gfm: false }).parse(mdText.trim()).children;
|
||||
replaceSection(tree, "Class members", function (before, section, after) {
|
||||
newSection_1.unshift(before);
|
||||
newSection_1.push(after);
|
||||
return newSection_1;
|
||||
});
|
||||
compData.errors.forEach(function (err) {
|
||||
errorMessages.push(err);
|
||||
});
|
||||
/*
|
||||
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 true;
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
/*
|
||||
function renderInputs(comp: ComponentInfo): string {
|
||||
var result = "";
|
||||
|
||||
comp.properties.forEach(prop => {
|
||||
result += `| ${prop.name} | \`${prop.type}\` | ${prop.defaultValue} | ${prop.docText} |\n`;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
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;
|
||||
}
|
@@ -1,382 +0,0 @@
|
||||
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 stringify from "remark-stringify";
|
||||
import * as frontMatter from "remark-frontmatter";
|
||||
|
||||
import * as combyne from "combyne";
|
||||
|
||||
import {
|
||||
Application,
|
||||
ProjectReflection,
|
||||
Reflection,
|
||||
DeclarationReflection,
|
||||
SignatureReflection,
|
||||
ParameterReflection,
|
||||
ReflectionKind,
|
||||
TraverseProperty,
|
||||
Decorator
|
||||
} from "typedoc";
|
||||
import { CommentTag } from "typedoc/dist/lib/models";
|
||||
|
||||
|
||||
let libFolders = ["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",
|
||||
"text-mask.component": "InputMaskDirective",
|
||||
"card-item-types.service": "CardItemTypeService"
|
||||
}
|
||||
|
||||
|
||||
let undocMethodNames = {
|
||||
"ngOnChanges": 1
|
||||
};
|
||||
|
||||
|
||||
class PropInfo {
|
||||
name: string;
|
||||
type: string;
|
||||
typeLink: string;
|
||||
defaultValue: string;
|
||||
docText: string;
|
||||
isInput: boolean;
|
||||
isOutput: boolean;
|
||||
isDeprecated: boolean;
|
||||
|
||||
errorMessages: string[];
|
||||
|
||||
constructor(rawProp: DeclarationReflection) {
|
||||
this.errorMessages = [];
|
||||
this.name = rawProp.name;
|
||||
this.docText = rawProp.comment ? rawProp.comment.shortText : "";
|
||||
this.docText = this.docText.replace(/[\n\r]+/g, " ").trim();
|
||||
this.defaultValue = rawProp.defaultValue || "";
|
||||
this.defaultValue = this.defaultValue.replace(/\|/, "\\|");
|
||||
this.type = rawProp.type ? rawProp.type.toString() : "";
|
||||
|
||||
this.isDeprecated = rawProp.comment && rawProp.comment.hasTag("deprecated");
|
||||
|
||||
if (this.isDeprecated) {
|
||||
this.docText = "**Deprecated:** " + rawProp.comment.getTag("deprecated").text.replace(/[\n\r]+/g, " ").trim();
|
||||
}
|
||||
|
||||
if (rawProp.decorators) {
|
||||
rawProp.decorators.forEach(dec => {
|
||||
//console.log(dec);
|
||||
if (dec.name === "Input") {
|
||||
this.isInput = true;
|
||||
|
||||
if (dec.arguments) {
|
||||
let bindingName = dec.arguments["bindingPropertyName"];
|
||||
|
||||
if (bindingName && (bindingName !== ""))
|
||||
this.name = bindingName.replace(/['"]/g, "");
|
||||
}
|
||||
|
||||
if (!this.docText && !this.isDeprecated) {
|
||||
this.errorMessages.push(`Warning: Input "${rawProp.name}" has no doc text.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (dec.name === "Output") {
|
||||
this.isOutput = true;
|
||||
|
||||
if (!this.docText && !this.isDeprecated) {
|
||||
this.errorMessages.push(`Warning: Output "${rawProp.name}" has no doc text.`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get errors() {
|
||||
return this.errorMessages;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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, " ").trim();
|
||||
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;
|
||||
returnDocText: string;
|
||||
returnsSomething: boolean;
|
||||
signature: string;
|
||||
params: ParamInfo[];
|
||||
isDeprecated: boolean;
|
||||
|
||||
errorMessages: string[];
|
||||
|
||||
|
||||
constructor(rawSig: SignatureReflection) {
|
||||
this.errorMessages = [];
|
||||
this.name = rawSig.name;
|
||||
this.returnType = rawSig.type ? rawSig.type.toString() : "";
|
||||
this.returnsSomething = this.returnType != "void";
|
||||
|
||||
if (rawSig.hasComment()) {
|
||||
this.docText = rawSig.comment.shortText + rawSig.comment.text;
|
||||
this.docText = this.docText.replace(/[\n\r]+/g, " ").trim();
|
||||
|
||||
if (!this.docText) {
|
||||
this.errorMessages.push(`Warning: method "${rawSig.name}" has no doc text.`);
|
||||
}
|
||||
|
||||
this.returnDocText = rawSig.comment.returns;
|
||||
this.returnDocText = this.returnDocText ? this.returnDocText.replace(/[\n\r]+/g, " ").trim() : "";
|
||||
|
||||
if (this.returnDocText.toLowerCase() === "nothing") {
|
||||
this.returnsSomething = false;
|
||||
}
|
||||
|
||||
if (this.returnsSomething && !this.returnDocText) {
|
||||
this.errorMessages.push(`Warning: Return value of method "${rawSig.name}" has no doc text.`);
|
||||
}
|
||||
|
||||
this.isDeprecated = rawSig.comment.hasTag("deprecated");
|
||||
}
|
||||
|
||||
this.params = [];
|
||||
let paramStrings = [];
|
||||
|
||||
if (rawSig.parameters) {
|
||||
rawSig.parameters.forEach(rawParam => {
|
||||
if (!rawParam.comment || !rawParam.comment.text) {
|
||||
this.errorMessages.push(`Warning: parameter "${rawParam.name}" of method "${rawSig.name}" has no doc text.`);
|
||||
}
|
||||
|
||||
let param = new ParamInfo(rawParam);
|
||||
this.params.push(param);
|
||||
paramStrings.push(param.combined);
|
||||
});
|
||||
}
|
||||
|
||||
this.signature = "(" + paramStrings.join(", ") + ")";
|
||||
}
|
||||
|
||||
get errors() {
|
||||
return this.errorMessages;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ComponentInfo {
|
||||
properties: PropInfo[];
|
||||
methods: MethodSigInfo[];
|
||||
hasInputs: boolean;
|
||||
hasOutputs: boolean;
|
||||
hasMethods: boolean;
|
||||
|
||||
constructor(classRef: DeclarationReflection) {
|
||||
let props = classRef.getChildrenByKind(ReflectionKind.Property);
|
||||
let accessors = classRef.getChildrenByKind(ReflectionKind.Accessor);
|
||||
|
||||
this.properties = [...props, ...accessors].map(item => {
|
||||
return new PropInfo(item);
|
||||
});
|
||||
|
||||
let methods = classRef.getChildrenByKind(ReflectionKind.Method);
|
||||
|
||||
this.methods = [];
|
||||
|
||||
methods.forEach(method =>{
|
||||
if (!(method.flags.isPrivate || method.flags.isProtected || undocMethodNames[method.name])) {
|
||||
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;
|
||||
}
|
||||
|
||||
get errors() {
|
||||
let combinedErrors = [];
|
||||
|
||||
this.methods.forEach(method => {
|
||||
method.errors.forEach(err => {
|
||||
combinedErrors.push(err);
|
||||
})
|
||||
});
|
||||
|
||||
this.properties.forEach(prop => {
|
||||
prop.errors.forEach(err => {
|
||||
combinedErrors.push(err);
|
||||
});
|
||||
});
|
||||
|
||||
return combinedErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function initPhase(aggData) {
|
||||
let app = new Application({
|
||||
exclude: excludePatterns,
|
||||
ignoreCompilerErrors: true,
|
||||
experimentalDecorators: true,
|
||||
tsconfig: "tsconfig.json"
|
||||
});
|
||||
|
||||
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, errorMessages) {
|
||||
let compName = angNameToClassName(path.basename(pathname, ".md"));
|
||||
let classRef = aggData.projData.findReflectionByName(compName);
|
||||
|
||||
if (!classRef) {
|
||||
// A doc file with no corresponding class (eg, Document Library Model).
|
||||
return false;
|
||||
}
|
||||
|
||||
let compData = new ComponentInfo(classRef);
|
||||
let classType = compName.match(/component|directive|service/i);
|
||||
|
||||
if (classType) {
|
||||
let templateName = path.resolve(templateFolder, classType + ".combyne");
|
||||
let templateSource = fs.readFileSync(templateName, "utf8");
|
||||
let template = combyne(templateSource);
|
||||
|
||||
let mdText = template.render(compData);
|
||||
mdText = mdText.replace(/^ +\|/mg, "|");
|
||||
|
||||
let newSection = remark().data("settings", {paddedTable: false, gfm: false}).parse(mdText.trim()).children;
|
||||
|
||||
replaceSection(tree, "Class members", (before, section, after) => {
|
||||
newSection.unshift(before);
|
||||
newSection.push(after);
|
||||
return newSection;
|
||||
});
|
||||
|
||||
compData.errors.forEach(err => {
|
||||
errorMessages.push(err);
|
||||
})
|
||||
|
||||
/*
|
||||
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 true;
|
||||
}
|
||||
|
||||
/*
|
||||
function renderInputs(comp: ComponentInfo): string {
|
||||
var result = "";
|
||||
|
||||
comp.properties.forEach(prop => {
|
||||
result += `| ${prop.name} | \`${prop.type}\` | ${prop.defaultValue} | ${prop.docText} |\n`;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
@@ -1,357 +0,0 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var ts = require("typescript");
|
||||
var path = require("path");
|
||||
var heading = require("mdast-util-heading-range");
|
||||
var remark = require("remark");
|
||||
var unist = require("../unistHelpers");
|
||||
var typescript_1 = require("typescript");
|
||||
// Max number of characters in the text for the default value column.
|
||||
var maxDefaultTextLength = 20;
|
||||
var nameExceptions = {
|
||||
"datatable.component": "DataTableComponent",
|
||||
"tasklist.service": "TaskListService"
|
||||
};
|
||||
function initPhase(aggData) {
|
||||
}
|
||||
exports.initPhase = initPhase;
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
}
|
||||
exports.readPhase = readPhase;
|
||||
function aggPhase(aggData) {
|
||||
}
|
||||
exports.aggPhase = aggPhase;
|
||||
var PropData = /** @class */ (function () {
|
||||
function PropData() {
|
||||
}
|
||||
return PropData;
|
||||
}());
|
||||
var ParamData = /** @class */ (function () {
|
||||
function ParamData() {
|
||||
}
|
||||
ParamData.prototype.getSignature = function () {
|
||||
var sig = this.name;
|
||||
if (this.optional)
|
||||
sig += "?";
|
||||
if (this.type)
|
||||
sig += ": " + this.type;
|
||||
if (this.initializer)
|
||||
sig += " = " + this.initializer;
|
||||
return sig;
|
||||
};
|
||||
return ParamData;
|
||||
}());
|
||||
var MethodData = /** @class */ (function () {
|
||||
function MethodData() {
|
||||
this.params = [];
|
||||
}
|
||||
MethodData.prototype.getSignature = function () {
|
||||
var sig = this.name + "(";
|
||||
if (this.params.length > 0) {
|
||||
sig += this.params[0].getSignature();
|
||||
}
|
||||
for (var i = 1; i < this.params.length; i++) {
|
||||
sig += ", " + this.params[i].getSignature();
|
||||
}
|
||||
sig += ")";
|
||||
if (this.returnType !== "void") {
|
||||
sig += ": " + this.returnType;
|
||||
}
|
||||
return sig;
|
||||
};
|
||||
return MethodData;
|
||||
}());
|
||||
var ComponentDocAutoContent = /** @class */ (function () {
|
||||
function ComponentDocAutoContent() {
|
||||
this.inputs = [];
|
||||
this.outputs = [];
|
||||
}
|
||||
ComponentDocAutoContent.prototype.extractClassInfoFromSource = function (checker, classDec) {
|
||||
var sourceFile = classDec.getSourceFile();
|
||||
for (var i = 0; i < classDec.members.length; i++) {
|
||||
var member = classDec.members[i];
|
||||
if (ts.isPropertyDeclaration(member) ||
|
||||
ts.isGetAccessorDeclaration(member) ||
|
||||
ts.isSetAccessorDeclaration(member)) {
|
||||
var prop = member;
|
||||
var mods = ts.getCombinedModifierFlags(prop);
|
||||
var nonPrivate = (mods & ts.ModifierFlags.Private) === 0;
|
||||
var memSymbol = checker.getSymbolAtLocation(prop.name);
|
||||
if (nonPrivate && memSymbol && prop.decorators) {
|
||||
var name_1 = memSymbol.getName();
|
||||
var initializer = "";
|
||||
if (prop.initializer) {
|
||||
initializer = prop.initializer.getText(sourceFile);
|
||||
}
|
||||
var doc = ts.displayPartsToString(memSymbol.getDocumentationComment(checker));
|
||||
doc = doc.replace(/\r\n/g, " ");
|
||||
var propType = checker.typeToString(checker.getTypeOfSymbolAtLocation(memSymbol, memSymbol.valueDeclaration));
|
||||
var dec = prop.decorators[0].getText(sourceFile);
|
||||
if (dec.match(/@Input/)) {
|
||||
this.inputs.push({
|
||||
"name": name_1,
|
||||
"type": propType,
|
||||
"initializer": initializer,
|
||||
"docText": doc
|
||||
});
|
||||
}
|
||||
else if (dec.match(/@Output/)) {
|
||||
this.outputs.push({
|
||||
"name": name_1,
|
||||
"type": propType,
|
||||
"initializer": "",
|
||||
"docText": doc
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
ComponentDocAutoContent.prototype.addContentToDoc = function (tree) {
|
||||
var inTable = buildPropsTable(this.inputs);
|
||||
var outTable = buildPropsTable(this.outputs, false);
|
||||
if (inTable) {
|
||||
heading(tree, "Properties", function (before, section, after) {
|
||||
return [before, inTable, after];
|
||||
});
|
||||
}
|
||||
if (outTable) {
|
||||
heading(tree, "Events", function (before, section, after) {
|
||||
return [before, outTable, after];
|
||||
});
|
||||
}
|
||||
};
|
||||
return ComponentDocAutoContent;
|
||||
}());
|
||||
var ServiceDocAutoContent = /** @class */ (function () {
|
||||
function ServiceDocAutoContent() {
|
||||
this.props = [];
|
||||
this.methods = [];
|
||||
}
|
||||
ServiceDocAutoContent.prototype.extractClassInfoFromSource = function (checker, classDec) {
|
||||
var sourceFile = classDec.getSourceFile();
|
||||
for (var i = 0; i < classDec.members.length; i++) {
|
||||
var member = classDec.members[i];
|
||||
if (ts.isMethodDeclaration(member)) {
|
||||
var method = member;
|
||||
var mods = ts.getCombinedModifierFlags(method);
|
||||
var nonPrivate = (mods & ts.ModifierFlags.Private) === 0;
|
||||
var memSymbol = checker.getSymbolAtLocation(method.name);
|
||||
if (nonPrivate && memSymbol) {
|
||||
var methData = new MethodData();
|
||||
methData.name = memSymbol.getName();
|
||||
var doc = ts.displayPartsToString(memSymbol.getDocumentationComment());
|
||||
if (!doc)
|
||||
console.log("Warning: Method " + classDec.name.escapedText + "." + methData.name + " is not documented");
|
||||
methData.docText = doc.replace(/\r\n/g, " ");
|
||||
var sig = checker.getSignatureFromDeclaration(method);
|
||||
var returnType = sig.getReturnType();
|
||||
methData.returnType = checker.typeToString(returnType);
|
||||
var returnSymbol = returnType.getSymbol();
|
||||
var params = method.parameters;
|
||||
for (var p = 0; p < params.length; p++) {
|
||||
var pData = new ParamData();
|
||||
pData.name = params[p].name.getText();
|
||||
if (params[p].type)
|
||||
pData.type = params[p].type.getText();
|
||||
else
|
||||
pData.type = "";
|
||||
var paramSymbol = checker.getSymbolAtLocation(params[p].name);
|
||||
pData.docText = ts.displayPartsToString(paramSymbol.getDocumentationComment());
|
||||
if (!pData.docText)
|
||||
console.log("Warning: Parameter \"" + pData.name + "\" of " + classDec.name.escapedText + "." + methData.name + " is not documented");
|
||||
pData.optional = params[p].questionToken ? true : false;
|
||||
if (params[p].initializer) {
|
||||
var initText = params[p].initializer.getText();
|
||||
if (initText !== "undefined")
|
||||
pData.initializer = initText;
|
||||
}
|
||||
methData.params.push(pData);
|
||||
}
|
||||
this.methods.push(methData);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
ServiceDocAutoContent.prototype.addContentToDoc = function (tree) {
|
||||
var propsTable = buildPropsTable(this.props);
|
||||
var methodsList = buildMethodsList(this.methods);
|
||||
if (propsTable) {
|
||||
heading(tree, "Properties", function (before, section, after) {
|
||||
return [before, propsTable, after];
|
||||
});
|
||||
}
|
||||
if (methodsList) {
|
||||
heading(tree, "Methods", function (before, section, after) {
|
||||
return [before, methodsList, after];
|
||||
});
|
||||
}
|
||||
};
|
||||
return ServiceDocAutoContent;
|
||||
}());
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
var fileNameNoSuffix = path.basename(pathname, ".md");
|
||||
var itemType = fileNameNoSuffix.match(/component|directive|service/);
|
||||
if (itemType) {
|
||||
var srcData = aggData.srcData[fileNameNoSuffix];
|
||||
if (srcData) {
|
||||
var srcPath = srcData.path;
|
||||
var className = fixAngularFilename(fileNameNoSuffix);
|
||||
var classData = void 0;
|
||||
if ((itemType[0] === "component") || (itemType[0] === "directive")) {
|
||||
classData = new ComponentDocAutoContent();
|
||||
}
|
||||
else if (itemType[0] === "service") {
|
||||
classData = new ServiceDocAutoContent();
|
||||
}
|
||||
getDocSourceData(path.resolve(".", srcPath), className, classData);
|
||||
classData.addContentToDoc(tree);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
function initialCap(str) {
|
||||
return str[0].toUpperCase() + str.substr(1);
|
||||
}
|
||||
function fixAngularFilename(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;
|
||||
}
|
||||
function getDocSourceData(srcPath, docClassName, classData) {
|
||||
var prog = ts.createProgram([srcPath], {
|
||||
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
|
||||
});
|
||||
var sourceFiles = prog.getSourceFiles();
|
||||
var checker = prog.getTypeChecker();
|
||||
for (var i = 0; i < sourceFiles.length; i++) {
|
||||
if (!sourceFiles[i].isDeclarationFile)
|
||||
ts.forEachChild(sourceFiles[i], visit);
|
||||
}
|
||||
function visit(node) {
|
||||
if (!isNodeExported(node))
|
||||
return;
|
||||
if (ts.isClassDeclaration(node) && node.name) {
|
||||
var classDec = node;
|
||||
var sourceFile = classDec.getSourceFile();
|
||||
if (classDec.name.escapedText === docClassName) {
|
||||
getPropDataFromClassChain(checker, classDec, classData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get properties/events from main class and all inherited classes.
|
||||
function getPropDataFromClassChain(checker, classDec, classData) {
|
||||
// Main class
|
||||
classData.extractClassInfoFromSource(checker, classDec);
|
||||
// Inherited classes
|
||||
if (classDec.heritageClauses) {
|
||||
for (var _i = 0, _a = classDec.heritageClauses; _i < _a.length; _i++) {
|
||||
var hc = _a[_i];
|
||||
var hcType = checker.getTypeFromTypeNode(hc.types[0]);
|
||||
for (var _b = 0, _c = hcType.symbol.declarations; _b < _c.length; _b++) {
|
||||
var dec = _c[_b];
|
||||
if (typescript_1.isClassDeclaration(dec)) {
|
||||
getPropDataFromClassChain(checker, dec, classData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function buildPropsTable(props, includeInitializer) {
|
||||
if (includeInitializer === void 0) { includeInitializer = true; }
|
||||
if (props.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var headerCells = [
|
||||
unist.makeTableCell([unist.makeText("Name")]),
|
||||
unist.makeTableCell([unist.makeText("Type")])
|
||||
];
|
||||
if (includeInitializer)
|
||||
headerCells.push(unist.makeTableCell([unist.makeText("Default value")]));
|
||||
headerCells.push(unist.makeTableCell([unist.makeText("Description")]));
|
||||
var rows = [
|
||||
unist.makeTableRow(headerCells)
|
||||
];
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var pName = props[i].name;
|
||||
var pType = props[i].type;
|
||||
var pDesc = props[i].docText || "";
|
||||
if (pDesc) {
|
||||
pDesc = pDesc.replace(/[\n\r]+/, " ");
|
||||
}
|
||||
var descCellContent = remark().parse(pDesc).children;
|
||||
var pDefault = props[i].initializer || "";
|
||||
var defaultCellContent;
|
||||
if (pDefault) {
|
||||
if (pDefault.length > maxDefaultTextLength) {
|
||||
defaultCellContent = unist.makeText("See description");
|
||||
console.log("Warning: property \"" + pName + "\" default value substituted (> " + maxDefaultTextLength + " chars)");
|
||||
}
|
||||
else
|
||||
defaultCellContent = unist.makeInlineCode(pDefault);
|
||||
}
|
||||
else {
|
||||
defaultCellContent = unist.makeText("");
|
||||
}
|
||||
var cells = [
|
||||
unist.makeTableCell([unist.makeText(pName)]),
|
||||
unist.makeTableCell([unist.makeInlineCode(pType)])
|
||||
];
|
||||
if (includeInitializer)
|
||||
cells.push(unist.makeTableCell([defaultCellContent]));
|
||||
cells.push(unist.makeTableCell(descCellContent));
|
||||
rows.push(unist.makeTableRow(cells));
|
||||
}
|
||||
var spacers = [null, null, null];
|
||||
if (includeInitializer)
|
||||
spacers.push(null);
|
||||
return unist.makeTable(spacers, rows);
|
||||
}
|
||||
function buildMethodsList(methods) {
|
||||
if (methods.length === 0)
|
||||
return null;
|
||||
var listItems = [];
|
||||
for (var _i = 0, methods_1 = methods; _i < methods_1.length; _i++) {
|
||||
var method = methods_1[_i];
|
||||
var itemLines = [];
|
||||
itemLines.push(unist.makeInlineCode(method.getSignature()));
|
||||
itemLines.push(unist.makeBreak());
|
||||
itemLines.push(unist.makeParagraph(remark().parse(method.docText).children));
|
||||
itemLines.push(unist.makeBreak());
|
||||
var paramListItems = [];
|
||||
for (var _a = 0, _b = method.params; _a < _b.length; _a++) {
|
||||
var param = _b[_a];
|
||||
var currParamSections = [];
|
||||
if (param.docText !== "") {
|
||||
currParamSections.push(unist.makeInlineCode(param.name));
|
||||
var optionalPart = param.optional ? "(Optional) " : "";
|
||||
currParamSections.push(unist.makeText(" - " + optionalPart + param.docText));
|
||||
//currParamSections.push(unist.makeBreak());
|
||||
paramListItems.push(unist.makeListItem(unist.makeParagraph(currParamSections)));
|
||||
}
|
||||
}
|
||||
itemLines.push(unist.makeListUnordered(paramListItems));
|
||||
listItems.push(unist.makeListItem(unist.makeParagraph(itemLines)));
|
||||
}
|
||||
return unist.makeListUnordered(listItems);
|
||||
}
|
||||
function isNodeExported(node) {
|
||||
return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 || (!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile);
|
||||
}
|
@@ -1,498 +0,0 @@
|
||||
import * as ts from "typescript";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import * as heading from "mdast-util-heading-range";
|
||||
import * as remark from "remark";
|
||||
|
||||
import * as unist from "../unistHelpers";
|
||||
import { JsxEmit, isClassDeclaration, PropertyDeclaration } from "typescript";
|
||||
|
||||
|
||||
// Max number of characters in the text for the default value column.
|
||||
const maxDefaultTextLength = 20;
|
||||
|
||||
let nameExceptions = {
|
||||
"datatable.component": "DataTableComponent",
|
||||
"tasklist.service": "TaskListService"
|
||||
}
|
||||
|
||||
|
||||
export function initPhase(aggData) {
|
||||
}
|
||||
|
||||
export function readPhase(tree, pathname, aggData) {
|
||||
}
|
||||
|
||||
export function aggPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
interface NgDocAutoContent {
|
||||
extractClassInfoFromSource(checker: ts.TypeChecker, classDec: ts.ClassDeclaration);
|
||||
addContentToDoc(tree);
|
||||
}
|
||||
|
||||
class PropData {
|
||||
name: string;
|
||||
type: string;
|
||||
initializer: string;
|
||||
docText: string;
|
||||
}
|
||||
|
||||
class ParamData {
|
||||
name: string;
|
||||
type: string;
|
||||
docText: string;
|
||||
initializer: string;
|
||||
optional: boolean;
|
||||
|
||||
getSignature() {
|
||||
let sig = this.name;
|
||||
|
||||
if (this.optional)
|
||||
sig += "?";
|
||||
|
||||
if (this.type)
|
||||
sig += ": " + this.type;
|
||||
|
||||
if (this.initializer)
|
||||
sig += " = " + this.initializer;
|
||||
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
|
||||
class MethodData {
|
||||
name: string;
|
||||
docText: string;
|
||||
params: ParamData[];
|
||||
returnType: string;
|
||||
|
||||
constructor() {
|
||||
this.params = [];
|
||||
}
|
||||
|
||||
getSignature() {
|
||||
let sig = this.name + "(";
|
||||
|
||||
if (this.params.length > 0) {
|
||||
sig += this.params[0].getSignature();
|
||||
}
|
||||
|
||||
for (let i = 1; i < this.params.length; i++) {
|
||||
sig += ", " + this.params[i].getSignature();
|
||||
}
|
||||
|
||||
sig += ")";
|
||||
|
||||
if (this.returnType !== "void") {
|
||||
sig += ": " + this.returnType;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
|
||||
class ComponentDocAutoContent implements NgDocAutoContent {
|
||||
inputs: PropData[];
|
||||
outputs: PropData[];
|
||||
|
||||
constructor() {
|
||||
this.inputs = [];
|
||||
this.outputs = [];
|
||||
}
|
||||
|
||||
|
||||
extractClassInfoFromSource(checker: ts.TypeChecker, classDec: ts.ClassDeclaration) {
|
||||
let sourceFile = classDec.getSourceFile();
|
||||
|
||||
for (var i = 0; i < classDec.members.length; i++) {
|
||||
let member = classDec.members[i];
|
||||
|
||||
if (ts.isPropertyDeclaration(member) ||
|
||||
ts.isGetAccessorDeclaration(member) ||
|
||||
ts.isSetAccessorDeclaration(member)) {
|
||||
let prop: ts.PropertyDeclaration = member;
|
||||
|
||||
let mods = ts.getCombinedModifierFlags(prop);
|
||||
let nonPrivate = (mods & ts.ModifierFlags.Private) === 0;
|
||||
let memSymbol = checker.getSymbolAtLocation(prop.name);
|
||||
|
||||
if (nonPrivate && memSymbol && prop.decorators) {
|
||||
let name = memSymbol.getName();
|
||||
let initializer = "";
|
||||
|
||||
if (prop.initializer) {
|
||||
initializer = prop.initializer.getText(sourceFile);
|
||||
}
|
||||
|
||||
let doc = ts.displayPartsToString(memSymbol.getDocumentationComment(checker));
|
||||
doc = doc.replace(/\r\n/g, " ");
|
||||
|
||||
let propType = checker.typeToString(checker.getTypeOfSymbolAtLocation(memSymbol, memSymbol.valueDeclaration!));
|
||||
|
||||
let dec = prop.decorators[0].getText(sourceFile);
|
||||
|
||||
if (dec.match(/@Input/)) {
|
||||
this.inputs.push({
|
||||
"name": name,
|
||||
"type": propType,
|
||||
"initializer": initializer,
|
||||
"docText": doc
|
||||
});
|
||||
} else if (dec.match(/@Output/)) {
|
||||
this.outputs.push({
|
||||
"name": name,
|
||||
"type": propType,
|
||||
"initializer": "",
|
||||
"docText": doc
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addContentToDoc(tree) {
|
||||
let inTable = buildPropsTable(this.inputs);
|
||||
let outTable = buildPropsTable(this.outputs, false);
|
||||
|
||||
if (inTable) {
|
||||
heading(tree, "Properties", (before, section, after) => {
|
||||
return [before, inTable, after];
|
||||
});
|
||||
}
|
||||
|
||||
if (outTable) {
|
||||
heading(tree, "Events", (before, section, after) => {
|
||||
return [before, outTable, after];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ServiceDocAutoContent implements NgDocAutoContent {
|
||||
props: PropData[];
|
||||
methods: MethodData[];
|
||||
|
||||
constructor() {
|
||||
this.props = [];
|
||||
this.methods = [];
|
||||
}
|
||||
|
||||
|
||||
extractClassInfoFromSource(checker: ts.TypeChecker, classDec: ts.ClassDeclaration) {
|
||||
let sourceFile = classDec.getSourceFile();
|
||||
|
||||
for (var i = 0; i < classDec.members.length; i++) {
|
||||
let member = classDec.members[i];
|
||||
|
||||
if (ts.isMethodDeclaration(member)) {
|
||||
let method: ts.MethodDeclaration = member;
|
||||
|
||||
let mods = ts.getCombinedModifierFlags(method);
|
||||
let nonPrivate = (mods & ts.ModifierFlags.Private) === 0;
|
||||
let memSymbol = checker.getSymbolAtLocation(method.name);
|
||||
|
||||
if (nonPrivate && memSymbol) {
|
||||
let methData = new MethodData();
|
||||
|
||||
methData.name = memSymbol.getName();
|
||||
let doc = ts.displayPartsToString(memSymbol.getDocumentationComment());
|
||||
|
||||
if (!doc)
|
||||
console.log(`Warning: Method ${classDec.name.escapedText}.${methData.name} is not documented`);
|
||||
|
||||
methData.docText = doc.replace(/\r\n/g, " ");
|
||||
let sig = checker.getSignatureFromDeclaration(method);
|
||||
let returnType = sig.getReturnType();
|
||||
methData.returnType = checker.typeToString(returnType);
|
||||
let returnSymbol = returnType.getSymbol();
|
||||
|
||||
let params = method.parameters;
|
||||
|
||||
for (let p = 0; p < params.length; p++){
|
||||
let pData = new ParamData();
|
||||
pData.name = params[p].name.getText();
|
||||
|
||||
if (params[p].type)
|
||||
pData.type = params[p].type.getText();
|
||||
else
|
||||
pData.type = "";
|
||||
|
||||
let paramSymbol = checker.getSymbolAtLocation(params[p].name);
|
||||
pData.docText = ts.displayPartsToString(paramSymbol.getDocumentationComment());
|
||||
|
||||
if (!pData.docText)
|
||||
console.log(`Warning: Parameter "${pData.name}" of ${classDec.name.escapedText}.${methData.name} is not documented`);
|
||||
|
||||
pData.optional = params[p].questionToken ? true : false;
|
||||
|
||||
if (params[p].initializer) {
|
||||
let initText = params[p].initializer.getText();
|
||||
|
||||
if (initText !== "undefined")
|
||||
pData.initializer = initText;
|
||||
}
|
||||
|
||||
methData.params.push(pData);
|
||||
}
|
||||
|
||||
this.methods.push(methData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
addContentToDoc(tree) {
|
||||
let propsTable = buildPropsTable(this.props);
|
||||
let methodsList = buildMethodsList(this.methods);
|
||||
|
||||
if (propsTable) {
|
||||
heading(tree, "Properties", (before, section, after) => {
|
||||
return [before, propsTable, after];
|
||||
});
|
||||
}
|
||||
|
||||
if (methodsList) {
|
||||
heading(tree, "Methods", (before, section, after) => {
|
||||
return [before, methodsList, after];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function updatePhase(tree, pathname, aggData) {
|
||||
let fileNameNoSuffix = path.basename(pathname, ".md");
|
||||
|
||||
let itemType = fileNameNoSuffix.match(/component|directive|service/);
|
||||
|
||||
if (itemType) {
|
||||
let srcData = aggData.srcData[fileNameNoSuffix];
|
||||
|
||||
if (srcData) {
|
||||
let srcPath = srcData.path;
|
||||
let className = fixAngularFilename(fileNameNoSuffix);
|
||||
|
||||
let classData: NgDocAutoContent;
|
||||
|
||||
if ((itemType[0] === "component") || (itemType[0] === "directive")) {
|
||||
classData = new ComponentDocAutoContent();
|
||||
} else if (itemType[0] === "service") {
|
||||
classData = new ServiceDocAutoContent();
|
||||
}
|
||||
|
||||
getDocSourceData(path.resolve(".", srcPath), className, classData);
|
||||
classData.addContentToDoc(tree);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initialCap(str: string) {
|
||||
return str[0].toUpperCase() + str.substr(1);
|
||||
}
|
||||
|
||||
|
||||
function fixAngularFilename(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;
|
||||
}
|
||||
|
||||
|
||||
function getDocSourceData(srcPath: string, docClassName: string, classData: NgDocAutoContent) {
|
||||
let prog = ts.createProgram([srcPath], {
|
||||
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
|
||||
});
|
||||
|
||||
let sourceFiles = prog.getSourceFiles();
|
||||
let checker = prog.getTypeChecker();
|
||||
|
||||
for (var i = 0; i < sourceFiles.length; i++) {
|
||||
if (!sourceFiles[i].isDeclarationFile)
|
||||
ts.forEachChild(sourceFiles[i], visit);
|
||||
}
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (!isNodeExported(node))
|
||||
return;
|
||||
|
||||
if (ts.isClassDeclaration(node) && node.name) {
|
||||
let classDec: ts.ClassDeclaration = node;
|
||||
let sourceFile = classDec.getSourceFile();
|
||||
|
||||
if (classDec.name.escapedText === docClassName) {
|
||||
getPropDataFromClassChain(checker, classDec, classData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get properties/events from main class and all inherited classes.
|
||||
function getPropDataFromClassChain(
|
||||
checker: ts.TypeChecker,
|
||||
classDec: ts.ClassDeclaration,
|
||||
classData: NgDocAutoContent
|
||||
){
|
||||
// Main class
|
||||
classData.extractClassInfoFromSource(checker, classDec);
|
||||
|
||||
// Inherited classes
|
||||
if (classDec.heritageClauses) {
|
||||
for(const hc of classDec.heritageClauses) {
|
||||
let hcType = checker.getTypeFromTypeNode(hc.types[0]);
|
||||
|
||||
for (const dec of hcType.symbol.declarations) {
|
||||
if (isClassDeclaration(dec)) {
|
||||
getPropDataFromClassChain(checker, dec, classData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function buildPropsTable(props: PropData[], includeInitializer: boolean = true) {
|
||||
if (props.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var headerCells = [
|
||||
unist.makeTableCell([unist.makeText("Name")]),
|
||||
unist.makeTableCell([unist.makeText("Type")])
|
||||
];
|
||||
|
||||
if (includeInitializer)
|
||||
headerCells.push(unist.makeTableCell([unist.makeText("Default value")]));
|
||||
|
||||
headerCells.push(unist.makeTableCell([unist.makeText("Description")]));
|
||||
|
||||
var rows = [
|
||||
unist.makeTableRow(headerCells)
|
||||
];
|
||||
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var pName = props[i].name;
|
||||
var pType = props[i].type;
|
||||
var pDesc = props[i].docText || "";
|
||||
|
||||
if (pDesc) {
|
||||
pDesc = pDesc.replace(/[\n\r]+/, " ");
|
||||
}
|
||||
|
||||
var descCellContent = remark().parse(pDesc).children;
|
||||
|
||||
var pDefault = props[i].initializer || "";
|
||||
|
||||
var defaultCellContent;
|
||||
|
||||
if (pDefault) {
|
||||
if (pDefault.length > maxDefaultTextLength) {
|
||||
defaultCellContent = unist.makeText("See description");
|
||||
console.log(`Warning: property "${pName}" default value substituted (> ${maxDefaultTextLength} chars)`);
|
||||
} else
|
||||
defaultCellContent = unist.makeInlineCode(pDefault);
|
||||
} else {
|
||||
defaultCellContent = unist.makeText("");
|
||||
}
|
||||
|
||||
var cells = [
|
||||
unist.makeTableCell([unist.makeText(pName)]),
|
||||
unist.makeTableCell([unist.makeInlineCode(pType)])
|
||||
];
|
||||
|
||||
if (includeInitializer)
|
||||
cells.push(unist.makeTableCell([defaultCellContent]));
|
||||
|
||||
cells.push(unist.makeTableCell(descCellContent));
|
||||
|
||||
rows.push(unist.makeTableRow(cells));
|
||||
}
|
||||
|
||||
let spacers = [null, null, null];
|
||||
|
||||
if (includeInitializer)
|
||||
spacers.push(null);
|
||||
|
||||
return unist.makeTable(spacers, rows);
|
||||
}
|
||||
|
||||
|
||||
function buildMethodsList(methods: MethodData[]) {
|
||||
if (methods.length === 0)
|
||||
return null;
|
||||
|
||||
let listItems = [];
|
||||
|
||||
for (let method of methods) {
|
||||
let itemLines = [];
|
||||
|
||||
itemLines.push(unist.makeInlineCode(method.getSignature()));
|
||||
itemLines.push(unist.makeBreak());
|
||||
itemLines.push(unist.makeParagraph(remark().parse(method.docText).children));
|
||||
itemLines.push(unist.makeBreak());
|
||||
|
||||
let paramListItems = [];
|
||||
|
||||
for (let param of method.params) {
|
||||
let currParamSections = [];
|
||||
|
||||
if (param.docText !== "") {
|
||||
currParamSections.push(unist.makeInlineCode(param.name));
|
||||
|
||||
let optionalPart = param.optional ? "(Optional) " : "";
|
||||
|
||||
currParamSections.push(unist.makeText(" - " + optionalPart + param.docText));
|
||||
//currParamSections.push(unist.makeBreak());
|
||||
paramListItems.push(unist.makeListItem(unist.makeParagraph(currParamSections)));
|
||||
}
|
||||
}
|
||||
|
||||
itemLines.push(unist.makeListUnordered(paramListItems));
|
||||
|
||||
|
||||
listItems.push(unist.makeListItem(unist.makeParagraph(itemLines)));
|
||||
}
|
||||
|
||||
return unist.makeListUnordered(listItems);
|
||||
}
|
||||
|
||||
|
||||
function isNodeExported(node: ts.Node): boolean {
|
||||
return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 || (!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile);
|
||||
}
|
@@ -1,108 +0,0 @@
|
||||
"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 yaml = require("js-yaml");
|
||||
var combyne = require("combyne");
|
||||
var unist = require("../unistHelpers");
|
||||
var tutFolder = path.resolve("..", "docs", "tutorials");
|
||||
var templateFolder = path.resolve(".", "config", "DocProcessor", "templates");
|
||||
var userGuideFolder = path.resolve("..", "docs", "user-guide");
|
||||
function initPhase(aggData) { }
|
||||
exports.initPhase = initPhase;
|
||||
function readPhase(tree, pathname, aggData) { }
|
||||
exports.readPhase = readPhase;
|
||||
function aggPhase(aggData) {
|
||||
var indexDocData = getIndexDocData();
|
||||
var templateName = path.resolve(templateFolder, "tutIndex.combyne");
|
||||
var templateSource = fs.readFileSync(templateName, "utf8");
|
||||
var template = combyne(templateSource);
|
||||
var mdText = template.render(indexDocData);
|
||||
mdText = mdText.replace(/^ +\|/mg, "|");
|
||||
var newSection = remark().data("settings", { paddedTable: false, gfm: false }).parse(mdText.trim()).children;
|
||||
var tutIndexFile = path.resolve(tutFolder, "README.md");
|
||||
var tutIndexText = fs.readFileSync(tutIndexFile, "utf8");
|
||||
var tutIndexMD = remark().data("settings", { paddedTable: false, gfm: false }).parse(tutIndexText);
|
||||
replaceSection(tutIndexMD, "Tutorials", function (before, section, after) {
|
||||
newSection.unshift(before);
|
||||
newSection.push(after);
|
||||
return newSection;
|
||||
});
|
||||
fs.writeFileSync(tutIndexFile, remark().use(frontMatter, { type: 'yaml', fence: '---' }).data("settings", { paddedTable: false, gfm: false }).stringify(tutIndexMD));
|
||||
}
|
||||
exports.aggPhase = aggPhase;
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
function getIndexDocData() {
|
||||
var indexFile = path.resolve(userGuideFolder, "summary.json");
|
||||
var summaryArray = JSON.parse(fs.readFileSync(indexFile, "utf8"));
|
||||
var indexArray = [];
|
||||
summaryArray.forEach(function (element) {
|
||||
if (element["title"] === "Tutorials") {
|
||||
indexArray = element["children"];
|
||||
}
|
||||
});
|
||||
var result = {
|
||||
tuts: []
|
||||
};
|
||||
indexArray.forEach(function (element) {
|
||||
var tutData = { link: element["file"] };
|
||||
var tutFile = path.resolve(tutFolder, element["file"]);
|
||||
var tutFileText = fs.readFileSync(tutFile, "utf8");
|
||||
var tutMD = remark().use(frontMatter, ["yaml"]).parse(tutFileText);
|
||||
var metadata = getDocMetadata(tutMD);
|
||||
if (metadata["Level"]) {
|
||||
tutData["level"] = metadata["Level"];
|
||||
}
|
||||
else {
|
||||
tutData["level"] = "";
|
||||
}
|
||||
var briefDesc = getFirstParagraph(tutMD);
|
||||
var briefDescText = remark()
|
||||
.use(frontMatter, { type: 'yaml', fence: '---' })
|
||||
.data("settings", { paddedTable: false, gfm: false })
|
||||
.stringify(briefDesc);
|
||||
tutData["briefDesc"] = briefDescText;
|
||||
var title = getFirstHeading(tutMD);
|
||||
var titleText = remark()
|
||||
.use(frontMatter, { type: 'yaml', fence: '---' })
|
||||
.data("settings", { paddedTable: false, gfm: false })
|
||||
.stringify(title.children[0]);
|
||||
tutData["title"] = titleText;
|
||||
result.tuts.push(tutData);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function getDocMetadata(tree) {
|
||||
if (tree.children[0].type == "yaml") {
|
||||
return yaml.load(tree.children[0].value);
|
||||
}
|
||||
else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
function getFirstParagraph(tree) {
|
||||
var s = 0;
|
||||
for (; (s < tree.children.length) && !unist.isParagraph(tree.children[s]); s++) { }
|
||||
if (s < tree.children.length) {
|
||||
return tree.children[s];
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function getFirstHeading(tree) {
|
||||
var s = 0;
|
||||
for (; (s < tree.children.length) && !unist.isHeading(tree.children[s]); s++) { }
|
||||
if (s < tree.children.length) {
|
||||
return tree.children[s];
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,142 +0,0 @@
|
||||
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 stringify from "remark-stringify";
|
||||
import * as frontMatter from "remark-frontmatter";
|
||||
import * as yaml from "js-yaml";
|
||||
import * as combyne from "combyne";
|
||||
|
||||
import * as unist from "../unistHelpers";
|
||||
|
||||
const tutFolder = path.resolve("..", "docs", "tutorials");
|
||||
const templateFolder = path.resolve(".", "config", "DocProcessor", "templates");
|
||||
const userGuideFolder = path.resolve("..", "docs", "user-guide");
|
||||
|
||||
|
||||
export function initPhase(aggData) {}
|
||||
|
||||
export function readPhase(tree, pathname, aggData) {}
|
||||
|
||||
|
||||
export function aggPhase(aggData) {
|
||||
let indexDocData = getIndexDocData();
|
||||
|
||||
let templateName = path.resolve(templateFolder, "tutIndex.combyne");
|
||||
let templateSource = fs.readFileSync(templateName, "utf8");
|
||||
let template = combyne(templateSource);
|
||||
|
||||
let mdText = template.render(indexDocData);
|
||||
mdText = mdText.replace(/^ +\|/mg, "|");
|
||||
|
||||
let newSection = remark().data("settings", {paddedTable: false, gfm: false}).parse(mdText.trim()).children;
|
||||
|
||||
let tutIndexFile = path.resolve(tutFolder, "README.md");
|
||||
let tutIndexText = fs.readFileSync(tutIndexFile, "utf8");
|
||||
let tutIndexMD = remark().data("settings", {paddedTable: false, gfm: false}).parse(tutIndexText);
|
||||
|
||||
replaceSection(tutIndexMD, "Tutorials", (before, section, after) => {
|
||||
newSection.unshift(before);
|
||||
newSection.push(after);
|
||||
return newSection;
|
||||
});
|
||||
|
||||
fs.writeFileSync(tutIndexFile, remark().use(frontMatter, {type: 'yaml', fence: '---'}).data("settings", {paddedTable: false, gfm: false}).stringify(tutIndexMD));
|
||||
}
|
||||
|
||||
|
||||
export function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function getIndexDocData() {
|
||||
let indexFile = path.resolve(userGuideFolder, "summary.json");
|
||||
let summaryArray = JSON.parse(fs.readFileSync(indexFile, "utf8"));
|
||||
let indexArray = [];
|
||||
|
||||
summaryArray.forEach(element => {
|
||||
if (element["title"] === "Tutorials") {
|
||||
indexArray = element["children"];
|
||||
}
|
||||
});
|
||||
|
||||
let result = {
|
||||
tuts: []
|
||||
};
|
||||
|
||||
indexArray.forEach(element => {
|
||||
let tutData = { link: element["file"] };
|
||||
|
||||
let tutFile = path.resolve(tutFolder, element["file"]);
|
||||
let tutFileText = fs.readFileSync(tutFile, "utf8");
|
||||
let tutMD = remark().use(frontMatter, ["yaml"]).parse(tutFileText);
|
||||
|
||||
let metadata = getDocMetadata(tutMD);
|
||||
|
||||
if (metadata["Level"]){
|
||||
tutData["level"] = metadata["Level"];
|
||||
} else {
|
||||
tutData["level"] = "";
|
||||
}
|
||||
|
||||
let briefDesc = getFirstParagraph(tutMD);
|
||||
|
||||
let briefDescText = remark()
|
||||
.use(frontMatter, {type: 'yaml', fence: '---'})
|
||||
.data("settings", {paddedTable: false, gfm: false})
|
||||
.stringify(briefDesc);
|
||||
|
||||
tutData["briefDesc"] = briefDescText;
|
||||
|
||||
let title = getFirstHeading(tutMD);
|
||||
|
||||
let titleText = remark()
|
||||
.use(frontMatter, {type: 'yaml', fence: '---'})
|
||||
.data("settings", {paddedTable: false, gfm: false})
|
||||
.stringify(title.children[0]);
|
||||
|
||||
tutData["title"] = titleText;
|
||||
|
||||
result.tuts.push(tutData);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function getDocMetadata(tree) {
|
||||
if (tree.children[0].type == "yaml") {
|
||||
return yaml.load(tree.children[0].value);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getFirstParagraph(tree) {
|
||||
let s = 0;
|
||||
|
||||
for (;(s < tree.children.length) && !unist.isParagraph(tree.children[s]); s++) {}
|
||||
|
||||
if (s < tree.children.length) {
|
||||
return tree.children[s];
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstHeading(tree) {
|
||||
let s = 0;
|
||||
|
||||
for (;(s < tree.children.length) && !unist.isHeading(tree.children[s]); s++) {}
|
||||
|
||||
if (s < tree.children.length) {
|
||||
return tree.children[s];
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,289 +0,0 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var typedoc_1 = require("typedoc");
|
||||
var unist = require("../unistHelpers");
|
||||
var ngHelpers = require("../ngHelpers");
|
||||
var includedNodeTypes = [
|
||||
"root", "paragraph", "inlineCode", "list", "listItem",
|
||||
"table", "tableRow", "tableCell", "emphasis", "strong",
|
||||
"link", "text"
|
||||
];
|
||||
var docFolder = path.resolve("..", "docs");
|
||||
var adfLibNames = ["core", "content-services", "insights", "process-services"];
|
||||
function initPhase(aggData) {
|
||||
aggData.docFiles = {};
|
||||
aggData.nameLookup = new SplitNameLookup();
|
||||
adfLibNames.forEach(function (libName) {
|
||||
var libFolderPath = path.resolve(docFolder, libName);
|
||||
var files = fs.readdirSync(libFolderPath);
|
||||
files.forEach(function (file) {
|
||||
if (path.extname(file) === ".md") {
|
||||
var relPath = libFolderPath.substr(libFolderPath.indexOf("docs") + 5).replace(/\\/, "/") + "/" + file;
|
||||
var compName = path.basename(file, ".md");
|
||||
aggData.docFiles[compName] = relPath;
|
||||
}
|
||||
});
|
||||
});
|
||||
var classes = aggData.projData.getReflectionsByKind(typedoc_1.ReflectionKind.Class);
|
||||
classes.forEach(function (currClass) {
|
||||
if (currClass.name.match(/(Component|Directive|Interface|Model|Pipe|Service|Widget)$/)) {
|
||||
aggData.nameLookup.addName(currClass.name);
|
||||
}
|
||||
});
|
||||
//console.log(JSON.stringify(aggData.nameLookup));
|
||||
}
|
||||
exports.initPhase = initPhase;
|
||||
function readPhase(tree, pathname, aggData) { }
|
||||
exports.readPhase = readPhase;
|
||||
function aggPhase(aggData) {
|
||||
}
|
||||
exports.aggPhase = aggPhase;
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
traverseMDTree(tree);
|
||||
return true;
|
||||
function traverseMDTree(node) {
|
||||
if (!includedNodeTypes.includes(node.type)) {
|
||||
return;
|
||||
}
|
||||
if (node.type === "inlineCode") {
|
||||
var link = resolveTypeLink(aggData, node.value);
|
||||
if (link) {
|
||||
convertNodeToTypeLink(node, node.value, link);
|
||||
}
|
||||
}
|
||||
else if (node.type === "link") {
|
||||
if (node.children && ((node.children[0].type === "inlineCode") ||
|
||||
(node.children[0].type === "text"))) {
|
||||
var link = resolveTypeLink(aggData, node.children[0].value);
|
||||
if (link) {
|
||||
convertNodeToTypeLink(node, node.children[0].value, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node.type === "paragraph") {
|
||||
node.children.forEach(function (child, index) {
|
||||
if (child.type === "text") {
|
||||
var newNodes = handleLinksInBodyText(aggData, child.value);
|
||||
(_a = node.children).splice.apply(_a, [index, 1].concat(newNodes));
|
||||
}
|
||||
else {
|
||||
traverseMDTree(child);
|
||||
}
|
||||
var _a;
|
||||
});
|
||||
}
|
||||
else if (node.children) {
|
||||
node.children.forEach(function (child) {
|
||||
traverseMDTree(child);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
var SplitNameNode = /** @class */ (function () {
|
||||
function SplitNameNode(key, value) {
|
||||
if (key === void 0) { key = ""; }
|
||||
if (value === void 0) { value = ""; }
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.children = {};
|
||||
}
|
||||
SplitNameNode.prototype.addChild = function (child) {
|
||||
this.children[child.key] = child;
|
||||
};
|
||||
return SplitNameNode;
|
||||
}());
|
||||
var SplitNameMatchElement = /** @class */ (function () {
|
||||
function SplitNameMatchElement(node, textPos) {
|
||||
this.node = node;
|
||||
this.textPos = textPos;
|
||||
}
|
||||
return SplitNameMatchElement;
|
||||
}());
|
||||
var SplitNameMatchResult = /** @class */ (function () {
|
||||
function SplitNameMatchResult(value, startPos) {
|
||||
this.value = value;
|
||||
this.startPos = startPos;
|
||||
}
|
||||
return SplitNameMatchResult;
|
||||
}());
|
||||
var SplitNameMatcher = /** @class */ (function () {
|
||||
function SplitNameMatcher(root) {
|
||||
this.root = root;
|
||||
this.reset();
|
||||
}
|
||||
/* Returns all names that match when this word is added. */
|
||||
SplitNameMatcher.prototype.nextWord = function (word, textPos) {
|
||||
var result = [];
|
||||
this.matches.push(new SplitNameMatchElement(this.root, textPos));
|
||||
for (var i = this.matches.length - 1; i >= 0; i--) {
|
||||
if (this.matches[i].node.children) {
|
||||
var child = this.matches[i].node.children[word];
|
||||
if (child) {
|
||||
if (child.value) {
|
||||
/* Using unshift to add the match to the array means that
|
||||
* the longest matches will appear first in the array.
|
||||
* User can then just use the first array element if only
|
||||
* the longest match is needed.
|
||||
*/
|
||||
result.unshift(new SplitNameMatchResult(child.value, this.matches[i].textPos));
|
||||
this.matches.splice(i, 1);
|
||||
}
|
||||
else {
|
||||
this.matches[i] = new SplitNameMatchElement(child, this.matches[i].textPos);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.matches.splice(i, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.matches.splice(i, 1);
|
||||
}
|
||||
}
|
||||
if (result === []) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
};
|
||||
SplitNameMatcher.prototype.reset = function () {
|
||||
this.matches = [];
|
||||
};
|
||||
return SplitNameMatcher;
|
||||
}());
|
||||
var SplitNameLookup = /** @class */ (function () {
|
||||
function SplitNameLookup() {
|
||||
this.root = new SplitNameNode();
|
||||
}
|
||||
SplitNameLookup.prototype.addName = function (name) {
|
||||
var spacedName = name.replace(/([A-Z])/g, " $1");
|
||||
var segments = spacedName.trim().toLowerCase().split(" ");
|
||||
var currNode = this.root;
|
||||
segments.forEach(function (segment, index) {
|
||||
var value = "";
|
||||
if (index == (segments.length - 1)) {
|
||||
value = name;
|
||||
}
|
||||
var childNode = currNode.children[segment];
|
||||
if (!childNode) {
|
||||
childNode = new SplitNameNode(segment, value);
|
||||
currNode.addChild(childNode);
|
||||
}
|
||||
currNode = childNode;
|
||||
});
|
||||
};
|
||||
return SplitNameLookup;
|
||||
}());
|
||||
var WordScanner = /** @class */ (function () {
|
||||
function WordScanner(text) {
|
||||
this.text = text;
|
||||
this.separators = " \n\r\t.;:";
|
||||
this.index = 0;
|
||||
this.nextSeparator = 0;
|
||||
this.next();
|
||||
}
|
||||
WordScanner.prototype.finished = function () {
|
||||
return this.index >= this.text.length;
|
||||
};
|
||||
WordScanner.prototype.next = function () {
|
||||
this.advanceIndex();
|
||||
this.advanceNextSeparator();
|
||||
this.current = this.text.substring(this.index, this.nextSeparator);
|
||||
};
|
||||
WordScanner.prototype.advanceNextSeparator = function () {
|
||||
for (var i = this.index; i < this.text.length; i++) {
|
||||
if (this.separators.indexOf(this.text[i]) !== -1) {
|
||||
this.nextSeparator = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.nextSeparator = this.text.length;
|
||||
};
|
||||
WordScanner.prototype.advanceIndex = function () {
|
||||
for (var i = this.nextSeparator; i < this.text.length; i++) {
|
||||
if (this.separators.indexOf(this.text[i]) === -1) {
|
||||
this.index = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.index = this.text.length;
|
||||
};
|
||||
return WordScanner;
|
||||
}());
|
||||
function handleLinksInBodyText(aggData, text) {
|
||||
var result = [];
|
||||
var currTextStart = 0;
|
||||
var matcher = new SplitNameMatcher(aggData.nameLookup.root);
|
||||
for (var scanner = new WordScanner(text); !scanner.finished(); scanner.next()) {
|
||||
var word = scanner.current
|
||||
.replace(/'s$/, "")
|
||||
.replace(/^[;:,\."']+/g, "")
|
||||
.replace(/[;:,\."']+$/g, "");
|
||||
var link = resolveTypeLink(aggData, word);
|
||||
var matchStart = void 0;
|
||||
if (!link) {
|
||||
var match = matcher.nextWord(word.toLowerCase(), scanner.index);
|
||||
if (match && match[0]) {
|
||||
link = resolveTypeLink(aggData, match[0].value);
|
||||
matchStart = match[0].startPos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
matchStart = scanner.index;
|
||||
}
|
||||
if (link) {
|
||||
var linkText = text.substring(matchStart, scanner.nextSeparator);
|
||||
var linkNode = unist.makeLink(unist.makeText(linkText), link);
|
||||
var prevText = text.substring(currTextStart, matchStart);
|
||||
result.push(unist.makeText(prevText));
|
||||
result.push(linkNode);
|
||||
currTextStart = scanner.nextSeparator;
|
||||
matcher.reset();
|
||||
}
|
||||
}
|
||||
var remainingText = text.substring(currTextStart, text.length);
|
||||
if (remainingText) {
|
||||
result.push(unist.makeText(remainingText));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function resolveTypeLink(aggData, text) {
|
||||
var possTypeName = cleanTypeName(text);
|
||||
var ref = aggData.projData.findReflectionByName(possTypeName);
|
||||
if (ref && isLinkable(ref.kind)) {
|
||||
var kebabName = ngHelpers.kebabifyClassName(possTypeName);
|
||||
var possDocFile = aggData.docFiles[kebabName];
|
||||
var url = "../../lib/" + ref.sources[0].fileName;
|
||||
if (possDocFile) {
|
||||
url = "../" + possDocFile;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
function cleanTypeName(text) {
|
||||
var matches = text.match(/[a-zA-Z0-9_]+<([a-zA-Z0-9_]+)>/);
|
||||
if (matches) {
|
||||
return matches[1];
|
||||
}
|
||||
else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
function isLinkable(kind) {
|
||||
return (kind === typedoc_1.ReflectionKind.Class) ||
|
||||
(kind === typedoc_1.ReflectionKind.Interface) ||
|
||||
(kind === typedoc_1.ReflectionKind.Enum);
|
||||
}
|
||||
function convertNodeToTypeLink(node, text, url) {
|
||||
var linkDisplayText = unist.makeInlineCode(text);
|
||||
node.type = "link";
|
||||
node.url = url;
|
||||
node.children = [linkDisplayText];
|
||||
}
|
@@ -1,359 +0,0 @@
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
|
||||
import * as remark from "remark";
|
||||
import * as stringify from "remark-stringify";
|
||||
import * as frontMatter from "remark-frontmatter";
|
||||
|
||||
import {
|
||||
Application,
|
||||
ProjectReflection,
|
||||
Reflection,
|
||||
DeclarationReflection,
|
||||
SignatureReflection,
|
||||
ParameterReflection,
|
||||
ReflectionKind,
|
||||
TraverseProperty,
|
||||
Decorator
|
||||
} from "typedoc";
|
||||
import { CommentTag } from "typedoc/dist/lib/models";
|
||||
|
||||
import * as unist from "../unistHelpers";
|
||||
import * as ngHelpers from "../ngHelpers";
|
||||
|
||||
|
||||
const includedNodeTypes = [
|
||||
"root", "paragraph", "inlineCode", "list", "listItem",
|
||||
"table", "tableRow", "tableCell", "emphasis", "strong",
|
||||
"link", "text"
|
||||
];
|
||||
|
||||
const docFolder = path.resolve("..", "docs");
|
||||
const adfLibNames = ["core", "content-services", "insights", "process-services"];
|
||||
|
||||
|
||||
export function initPhase(aggData) {
|
||||
aggData.docFiles = {};
|
||||
aggData.nameLookup = new SplitNameLookup();
|
||||
|
||||
adfLibNames.forEach(libName => {
|
||||
let libFolderPath = path.resolve(docFolder, libName);
|
||||
|
||||
let files = fs.readdirSync(libFolderPath);
|
||||
|
||||
files.forEach(file => {
|
||||
if (path.extname(file) === ".md") {
|
||||
let relPath = libFolderPath.substr(libFolderPath.indexOf("docs") + 5).replace(/\\/, "/") + "/" + file;
|
||||
let compName = path.basename(file, ".md");
|
||||
aggData.docFiles[compName] = relPath;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let classes = aggData.projData.getReflectionsByKind(ReflectionKind.Class);
|
||||
|
||||
classes.forEach(currClass => {
|
||||
if (currClass.name.match(/(Component|Directive|Interface|Model|Pipe|Service|Widget)$/)) {
|
||||
aggData.nameLookup.addName(currClass.name);
|
||||
}
|
||||
});
|
||||
|
||||
//console.log(JSON.stringify(aggData.nameLookup));
|
||||
}
|
||||
|
||||
export function readPhase(tree, pathname, aggData) {}
|
||||
|
||||
|
||||
export function aggPhase(aggData) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function updatePhase(tree, pathname, aggData) {
|
||||
traverseMDTree(tree);
|
||||
return true;
|
||||
|
||||
|
||||
function traverseMDTree(node) {
|
||||
if (!includedNodeTypes.includes(node.type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.type === "inlineCode") {
|
||||
let link = resolveTypeLink(aggData, node.value);
|
||||
|
||||
if (link) {
|
||||
convertNodeToTypeLink(node, node.value, link);
|
||||
}
|
||||
|
||||
} else if (node.type === "link") {
|
||||
if (node.children && (
|
||||
(node.children[0].type === "inlineCode") ||
|
||||
(node.children[0].type === "text")
|
||||
)) {
|
||||
let link = resolveTypeLink(aggData, node.children[0].value);
|
||||
|
||||
if (link) {
|
||||
convertNodeToTypeLink(node, node.children[0].value, link);
|
||||
}
|
||||
}
|
||||
} else if (node.type === "paragraph") {
|
||||
node.children.forEach((child, index) => {
|
||||
if (child.type === "text") {
|
||||
let newNodes = handleLinksInBodyText(aggData, child.value);
|
||||
node.children.splice(index, 1, ...newNodes);
|
||||
} else {
|
||||
traverseMDTree(child);
|
||||
}
|
||||
});
|
||||
} else if (node.children) {
|
||||
node.children.forEach(child => {
|
||||
traverseMDTree(child);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SplitNameNode {
|
||||
children: {};
|
||||
|
||||
constructor(public key: string = "", public value: string = "") {
|
||||
this.children = {};
|
||||
}
|
||||
|
||||
addChild(child: SplitNameNode) {
|
||||
this.children[child.key] = child;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SplitNameMatchElement {
|
||||
constructor(public node: SplitNameNode, public textPos: number) {}
|
||||
}
|
||||
|
||||
|
||||
class SplitNameMatchResult {
|
||||
constructor(public value: string, public startPos: number) {}
|
||||
}
|
||||
|
||||
|
||||
class SplitNameMatcher {
|
||||
matches: SplitNameMatchElement[];
|
||||
|
||||
constructor(public root: SplitNameNode) {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
/* Returns all names that match when this word is added. */
|
||||
nextWord(word: string, textPos: number): SplitNameMatchResult[] {
|
||||
let result = [];
|
||||
|
||||
this.matches.push(new SplitNameMatchElement(this.root, textPos));
|
||||
|
||||
for (let i = this.matches.length - 1; i >= 0; i--) {
|
||||
if (this.matches[i].node.children) {
|
||||
let child = this.matches[i].node.children[word];
|
||||
|
||||
if (child) {
|
||||
if (child.value) {
|
||||
/* Using unshift to add the match to the array means that
|
||||
* the longest matches will appear first in the array.
|
||||
* User can then just use the first array element if only
|
||||
* the longest match is needed.
|
||||
*/
|
||||
result.unshift(new SplitNameMatchResult(child.value, this.matches[i].textPos));
|
||||
this.matches.splice(i, 1);
|
||||
} else {
|
||||
this.matches[i] = new SplitNameMatchElement(child, this.matches[i].textPos);
|
||||
}
|
||||
} else {
|
||||
this.matches.splice(i, 1);
|
||||
}
|
||||
} else {
|
||||
this.matches.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (result === []) {
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.matches = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SplitNameLookup {
|
||||
root: SplitNameNode;
|
||||
|
||||
constructor() {
|
||||
this.root = new SplitNameNode();
|
||||
}
|
||||
|
||||
addName(name: string) {
|
||||
let spacedName = name.replace(/([A-Z])/g, " $1");
|
||||
let segments = spacedName.trim().toLowerCase().split(" ");
|
||||
|
||||
let currNode = this.root;
|
||||
|
||||
segments.forEach((segment, index) => {
|
||||
let value = "";
|
||||
|
||||
if (index == (segments.length - 1)) {
|
||||
value = name;
|
||||
}
|
||||
|
||||
let childNode = currNode.children[segment];
|
||||
|
||||
if (!childNode) {
|
||||
childNode = new SplitNameNode(segment, value);
|
||||
currNode.addChild(childNode);
|
||||
}
|
||||
|
||||
currNode = childNode;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WordScanner {
|
||||
separators: string;
|
||||
index: number;
|
||||
nextSeparator: number;
|
||||
current: string;
|
||||
|
||||
constructor(public text: string) {
|
||||
this.separators = " \n\r\t.;:";
|
||||
this.index = 0;
|
||||
this.nextSeparator = 0;
|
||||
this.next();
|
||||
}
|
||||
|
||||
finished() {
|
||||
return this.index >= this.text.length;
|
||||
}
|
||||
|
||||
next(): void {
|
||||
this.advanceIndex();
|
||||
this.advanceNextSeparator();
|
||||
this.current = this.text.substring(this.index, this.nextSeparator);
|
||||
}
|
||||
|
||||
advanceNextSeparator() {
|
||||
for (let i = this.index; i < this.text.length; i++) {
|
||||
if (this.separators.indexOf(this.text[i]) !== -1) {
|
||||
this.nextSeparator = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.nextSeparator = this.text.length;
|
||||
}
|
||||
|
||||
advanceIndex() {
|
||||
for (let i = this.nextSeparator; i < this.text.length; i++) {
|
||||
if (this.separators.indexOf(this.text[i]) === -1) {
|
||||
this.index = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.index = this.text.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleLinksInBodyText(aggData, text: string): Node[] {
|
||||
let result = [];
|
||||
let currTextStart = 0;
|
||||
let matcher = new SplitNameMatcher(aggData.nameLookup.root);
|
||||
|
||||
for (let scanner = new WordScanner(text); !scanner.finished(); scanner.next()) {
|
||||
let word = scanner.current
|
||||
.replace(/'s$/, "")
|
||||
.replace(/^[;:,\."']+/g, "")
|
||||
.replace(/[;:,\."']+$/g, "");
|
||||
|
||||
let link = resolveTypeLink(aggData, word);
|
||||
let matchStart;
|
||||
|
||||
if (!link) {
|
||||
let match = matcher.nextWord(word.toLowerCase(), scanner.index);
|
||||
|
||||
if (match && match[0]) {
|
||||
link = resolveTypeLink(aggData, match[0].value);
|
||||
matchStart = match[0].startPos;
|
||||
}
|
||||
} else {
|
||||
matchStart = scanner.index
|
||||
}
|
||||
|
||||
if (link) {
|
||||
let linkText = text.substring(matchStart, scanner.nextSeparator);
|
||||
let linkNode = unist.makeLink(unist.makeText(linkText), link);
|
||||
let prevText = text.substring(currTextStart, matchStart);
|
||||
result.push(unist.makeText(prevText));
|
||||
result.push(linkNode);
|
||||
currTextStart = scanner.nextSeparator;
|
||||
matcher.reset();
|
||||
}
|
||||
}
|
||||
|
||||
let remainingText = text.substring(currTextStart, text.length);
|
||||
|
||||
if (remainingText) {
|
||||
result.push(unist.makeText(remainingText));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function resolveTypeLink(aggData, text): string {
|
||||
let possTypeName = cleanTypeName(text);
|
||||
let ref: Reflection = aggData.projData.findReflectionByName(possTypeName);
|
||||
|
||||
if (ref && isLinkable(ref.kind)) {
|
||||
let kebabName = ngHelpers.kebabifyClassName(possTypeName);
|
||||
let possDocFile = aggData.docFiles[kebabName];
|
||||
let url = "../../lib/" + ref.sources[0].fileName;
|
||||
|
||||
if (possDocFile) {
|
||||
url = "../" + possDocFile;
|
||||
}
|
||||
|
||||
return url;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cleanTypeName(text) {
|
||||
let matches = text.match(/[a-zA-Z0-9_]+<([a-zA-Z0-9_]+)>/);
|
||||
|
||||
if (matches) {
|
||||
return matches[1];
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isLinkable(kind: ReflectionKind) {
|
||||
return (kind === ReflectionKind.Class) ||
|
||||
(kind === ReflectionKind.Interface) ||
|
||||
(kind === ReflectionKind.Enum);
|
||||
}
|
||||
|
||||
function convertNodeToTypeLink(node, text, url) {
|
||||
let linkDisplayText = unist.makeInlineCode(text);
|
||||
node.type = "link";
|
||||
node.url = url;
|
||||
node.children = [linkDisplayText];
|
||||
}
|
@@ -1,128 +0,0 @@
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var yaml = require("js-yaml");
|
||||
|
||||
var remark = require("remark");
|
||||
var stringify = require("remark-stringify");
|
||||
var zone = require("mdast-zone");
|
||||
var frontMatter = require("remark-frontmatter");
|
||||
|
||||
var combyne = require("combyne");
|
||||
|
||||
var unist = require("../unistHelpers");
|
||||
var ngHelpers = require("../ngHelpers");
|
||||
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
}
|
||||
|
||||
var angFilenameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))\.ts/;
|
||||
|
||||
var docsFolderPath = path.resolve("..", "docs");
|
||||
var histFilePath = path.resolve(docsFolderPath, "versionIndex.md");
|
||||
|
||||
var histSectionName = "history";
|
||||
var initialVersion = "v2.0.0";
|
||||
|
||||
var templateFolder = path.resolve(".", "config", "DocProcessor", "templates");
|
||||
|
||||
function initPhase(aggData) {
|
||||
aggData.versions = { "v2.0.0":[] };
|
||||
}
|
||||
|
||||
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
var compName = pathname;
|
||||
var angNameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))/;
|
||||
|
||||
if (!compName.match(angNameRegex))
|
||||
return;
|
||||
|
||||
if (compName.match(/boilerplate/))
|
||||
return;
|
||||
|
||||
if (tree.children[0].type == "yaml") {
|
||||
var metadata = yaml.load(tree.children[0].value);
|
||||
var version = metadata["Added"];
|
||||
|
||||
if (version) {
|
||||
if (aggData.versions[version]) {
|
||||
aggData.versions[version].push(compName);
|
||||
} else {
|
||||
aggData.versions[version] = [compName];
|
||||
}
|
||||
} else {
|
||||
aggData.versions[initialVersion].push(compName);
|
||||
}
|
||||
} else {
|
||||
aggData.versions[initialVersion].push(compName);
|
||||
}
|
||||
}
|
||||
|
||||
function aggPhase(aggData) {
|
||||
var histFileText = fs.readFileSync(histFilePath, "utf8");
|
||||
var histFileTree = remark().data("settings", {paddedTable: false, gfm: false}).parse(histFileText);
|
||||
|
||||
var keys = Object.keys(aggData.versions);
|
||||
keys.sort((a, b) => {
|
||||
if (a > b)
|
||||
return -1;
|
||||
else if (b > a)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
});
|
||||
|
||||
var templateName = path.resolve(templateFolder, "versIndex.combyne");
|
||||
var templateSource = fs.readFileSync(templateName, "utf8");
|
||||
var template = combyne(templateSource);
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var version = keys[i];
|
||||
var versionItems = aggData.versions[version];
|
||||
versionItems.sort((a, b) => {
|
||||
var aa = path.basename(a, ".md");
|
||||
var bb = path.basename(b, ".md");
|
||||
|
||||
return aa.localeCompare(bb);
|
||||
});
|
||||
|
||||
var versionTemplateData = {items: []};
|
||||
|
||||
for (var v = 0; v < versionItems.length; v++) {
|
||||
var displayName = ngHelpers.ngNameToDisplayName(path.basename(versionItems[v], ".md"));
|
||||
var pageLink = versionItems[v];// + ".md";
|
||||
pageLink = pageLink.replace(/\\/g, '/');
|
||||
pageLink = pageLink.substr(pageLink.indexOf("docs") + 5);
|
||||
|
||||
versionTemplateData.items.push({
|
||||
title: displayName,
|
||||
link: pageLink
|
||||
});
|
||||
}
|
||||
|
||||
var mdText = template.render(versionTemplateData);
|
||||
mdText = mdText.replace(/^ +-/mg, "-");
|
||||
|
||||
var newSection = remark().data("settings", {paddedTable: false, gfm: false}).parse(mdText.trim()).children;
|
||||
|
||||
var versSectionName = version.replace(/\./g, "");;
|
||||
|
||||
zone(histFileTree, versSectionName, (startComment, oldSection, endComment) => {
|
||||
newSection.unshift(startComment);
|
||||
newSection.push(endComment);
|
||||
return newSection;
|
||||
});
|
||||
}
|
||||
|
||||
fs.writeFileSync(histFilePath, remark().use(frontMatter, {type: 'yaml', fence: '---'}).data("settings", {paddedTable: false, gfm: false}).stringify(histFileTree));
|
||||
}
|
||||
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
module.exports = {
|
||||
|
||||
makeRoot: function (children) {
|
||||
return {
|
||||
"type": "root",
|
||||
"children": children
|
||||
};
|
||||
},
|
||||
|
||||
makeText: function (textVal) {
|
||||
return {
|
||||
"type": "text",
|
||||
"value": textVal
|
||||
};
|
||||
},
|
||||
|
||||
makeEmphasis: function (content) {
|
||||
return {
|
||||
"type": "emphasis",
|
||||
"children": content
|
||||
};
|
||||
},
|
||||
|
||||
makeStrong: function (content) {
|
||||
return {
|
||||
"type": "strong",
|
||||
"children": content
|
||||
};
|
||||
},
|
||||
|
||||
makeHeading: function (caption, depth) {
|
||||
return {
|
||||
"type": "heading",
|
||||
"depth": depth,
|
||||
"children": [caption]
|
||||
};
|
||||
},
|
||||
|
||||
makeLink: function (caption, url) {
|
||||
return {
|
||||
"type": "link",
|
||||
"url": url,
|
||||
"children": [ caption ]
|
||||
};
|
||||
},
|
||||
|
||||
makeListItem: function (itemValue) {
|
||||
return {
|
||||
"type": "listItem",
|
||||
"loose": false,
|
||||
"children": [ itemValue ]
|
||||
};
|
||||
},
|
||||
|
||||
makeListUnordered: function (itemsArray) {
|
||||
return {
|
||||
"type": "list",
|
||||
"ordered": false,
|
||||
"children": itemsArray,
|
||||
"loose": false
|
||||
};
|
||||
},
|
||||
|
||||
makeParagraph: function (itemsArray) {
|
||||
return {
|
||||
"type": "paragraph",
|
||||
"children": itemsArray
|
||||
}
|
||||
},
|
||||
|
||||
makeTable: function (colAlignArray, rowArray) {
|
||||
return {
|
||||
"type": "table",
|
||||
"align": colAlignArray,
|
||||
"children": rowArray
|
||||
};
|
||||
},
|
||||
|
||||
makeTableRow: function (cellArray) {
|
||||
return {
|
||||
"type": "tableRow",
|
||||
"children": cellArray
|
||||
};
|
||||
},
|
||||
|
||||
makeTableCell: function (content) {
|
||||
return {
|
||||
"type": "tableCell",
|
||||
"children": content
|
||||
};
|
||||
},
|
||||
|
||||
makeInlineCode: function (codeText) {
|
||||
return {
|
||||
"type": "inlineCode",
|
||||
"value": codeText
|
||||
}
|
||||
},
|
||||
|
||||
makeHTML: function (htmlText) {
|
||||
return {
|
||||
"type": "html",
|
||||
"value": htmlText
|
||||
};
|
||||
},
|
||||
|
||||
makeBreak: function () {
|
||||
return {
|
||||
"type": "break"
|
||||
}
|
||||
},
|
||||
|
||||
makeImage: function (url, alt) {
|
||||
return {
|
||||
"type": "image",
|
||||
"url": url,
|
||||
"alt": alt
|
||||
}
|
||||
},
|
||||
|
||||
isHeading: function (node) {
|
||||
return node.type === "heading";
|
||||
},
|
||||
|
||||
isListUnordered: function (node) {
|
||||
return (node.type === "list") && !node.ordered;
|
||||
},
|
||||
|
||||
isParagraph: function (node) {
|
||||
return node.type === "paragraph";
|
||||
},
|
||||
|
||||
isText: function (node) {
|
||||
return node.type === "text";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user