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
27
tools/doc/ReviewCheckerGuide.md
Normal file
27
tools/doc/ReviewCheckerGuide.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 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
tools/doc/commitStoplist.json
Normal file
1
tools/doc/commitStoplist.json
Normal file
@@ -0,0 +1 @@
|
||||
["ADF-1769"]
|
186
tools/doc/docProcessor.js
Normal file
186
tools/doc/docProcessor.js
Normal file
@@ -0,0 +1,186 @@
|
||||
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", "default")
|
||||
.parse(process.argv);
|
||||
|
||||
var sourcePath;
|
||||
|
||||
if (program.args.length === 0) {
|
||||
sourcePath = defaultFolder;
|
||||
} 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);
|
||||
|
||||
|
||||
|
24
tools/doc/doctool.config.json
Normal file
24
tools/doc/doctool.config.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"profiles": {
|
||||
"default": [
|
||||
"index",
|
||||
"versionIndex",
|
||||
"tutorialIndex",
|
||||
"tsInfo",
|
||||
"toc"
|
||||
],
|
||||
"index": [
|
||||
"index",
|
||||
"versionIndex",
|
||||
"tutorialIndex"
|
||||
],
|
||||
"enhance": [
|
||||
"tsInfo",
|
||||
"toc"
|
||||
],
|
||||
"dev": [
|
||||
"tsInfo",
|
||||
"typeLinker"
|
||||
]
|
||||
}
|
||||
}
|
31
tools/doc/libsearch.js
Normal file
31
tools/doc/libsearch.js
Normal file
@@ -0,0 +1,31 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
35
tools/doc/ngHelpers.js
Normal file
35
tools/doc/ngHelpers.js
Normal file
@@ -0,0 +1,35 @@
|
||||
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();
|
||||
}
|
103
tools/doc/reviewChecker.js
Normal file
103
tools/doc/reviewChecker.js
Normal file
@@ -0,0 +1,103 @@
|
||||
"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("..", "tools", "doc", "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;
|
||||
}
|
164
tools/doc/reviewChecker.ts
Normal file
164
tools/doc/reviewChecker.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
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("..", "tools", "doc", "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;
|
||||
}
|
29
tools/doc/stoplist.js
Normal file
29
tools/doc/stoplist.js
Normal file
@@ -0,0 +1,29 @@
|
||||
"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;
|
31
tools/doc/stoplist.ts
Normal file
31
tools/doc/stoplist.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
23
tools/doc/templates/component.combyne
vendored
Normal file
23
tools/doc/templates/component.combyne
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{% 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 %}
|
23
tools/doc/templates/directive.combyne
vendored
Normal file
23
tools/doc/templates/directive.combyne
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{% 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 %}
|
14
tools/doc/templates/service.combyne
vendored
Normal file
14
tools/doc/templates/service.combyne
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
{% 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 %}
|
5
tools/doc/templates/tutIndex.combyne
vendored
Normal file
5
tools/doc/templates/tutIndex.combyne
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
| Name | Level | Abstract |
|
||||
| -- | -- | -- |
|
||||
{% each tuts as tut %}
|
||||
| [**{{tut.title}}**]({{tut.link}}) | {{tut.level}} | {{tut.briefDesc}} |
|
||||
{% endeach %}
|
3
tools/doc/templates/versIndex.combyne
vendored
Normal file
3
tools/doc/templates/versIndex.combyne
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{% each items as item %}
|
||||
- [{{item.title}}]({{item.link}})
|
||||
{% endeach %}
|
401
tools/doc/tools/index.js
Normal file
401
tools/doc/tools/index.js
Normal file
@@ -0,0 +1,401 @@
|
||||
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 = "lib";
|
||||
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);
|
||||
}
|
175
tools/doc/tools/seealso.js
Normal file
175
tools/doc/tools/seealso.js
Normal file
@@ -0,0 +1,175 @@
|
||||
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");
|
||||
}
|
||||
|
93
tools/doc/tools/toc.js
Normal file
93
tools/doc/tools/toc.js
Normal file
@@ -0,0 +1,93 @@
|
||||
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;
|
||||
}
|
277
tools/doc/tools/tsInfo.js
Normal file
277
tools/doc/tools/tsInfo.js
Normal file
@@ -0,0 +1,277 @@
|
||||
"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("tools", "doc", "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.map(function (folder) {
|
||||
return path.resolve("lib", folder);
|
||||
}));
|
||||
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;
|
||||
}
|
385
tools/doc/tools/tsInfo.ts
Normal file
385
tools/doc/tools/tsInfo.ts
Normal file
@@ -0,0 +1,385 @@
|
||||
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("tools", "doc", "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.map(folder => {
|
||||
return path.resolve("lib", folder);
|
||||
}));
|
||||
|
||||
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;
|
||||
}
|
357
tools/doc/tools/tscProps.js
Normal file
357
tools/doc/tools/tscProps.js
Normal file
@@ -0,0 +1,357 @@
|
||||
"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);
|
||||
}
|
498
tools/doc/tools/tscProps.ts
Normal file
498
tools/doc/tools/tscProps.ts
Normal file
@@ -0,0 +1,498 @@
|
||||
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);
|
||||
}
|
108
tools/doc/tools/tutorialIndex.js
Normal file
108
tools/doc/tools/tutorialIndex.js
Normal file
@@ -0,0 +1,108 @@
|
||||
"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("tools", "doc", "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;
|
||||
}
|
||||
}
|
142
tools/doc/tools/tutorialIndex.ts
Normal file
142
tools/doc/tools/tutorialIndex.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
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("tools", "doc", "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;
|
||||
}
|
||||
}
|
289
tools/doc/tools/typeLinker.js
Normal file
289
tools/doc/tools/typeLinker.js
Normal file
@@ -0,0 +1,289 @@
|
||||
"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];
|
||||
}
|
359
tools/doc/tools/typeLinker.ts
Normal file
359
tools/doc/tools/typeLinker.ts
Normal file
@@ -0,0 +1,359 @@
|
||||
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];
|
||||
}
|
128
tools/doc/tools/versionIndex.js
Normal file
128
tools/doc/tools/versionIndex.js
Normal file
@@ -0,0 +1,128 @@
|
||||
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("tools", "doc", "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;
|
||||
}
|
136
tools/doc/unistHelpers.js
Normal file
136
tools/doc/unistHelpers.js
Normal file
@@ -0,0 +1,136 @@
|
||||
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";
|
||||
}
|
||||
}
|
18
tools/schematics/adf/.gitignore
vendored
Normal file
18
tools/schematics/adf/.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Outputs
|
||||
src/**/*.js
|
||||
src/**/*.js.map
|
||||
src/**/*.d.ts
|
||||
|
||||
# IDEs
|
||||
.idea/
|
||||
jsconfig.json
|
||||
.vscode/
|
||||
|
||||
# Misc
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Mac OSX Finder files.
|
||||
**/.DS_Store
|
||||
.DS_Store
|
3
tools/schematics/adf/.npmignore
Normal file
3
tools/schematics/adf/.npmignore
Normal file
@@ -0,0 +1,3 @@
|
||||
# Ignores TypeScript files, but keeps definitions.
|
||||
*.ts
|
||||
!*.d.ts
|
34
tools/schematics/adf/README.md
Normal file
34
tools/schematics/adf/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# ADF doc generator schematic
|
||||
|
||||
**Caution:** Although this tool should not be able to do any harm, it is still at the
|
||||
experimental stage. Check the results if you use it for anything "serious".
|
||||
|
||||
This [schematic](https://github.com/angular/devkit/tree/master/packages/angular_devkit/schematics)
|
||||
works with [Angular CLI](https://cli.angular.io/) to make it easier to generate new
|
||||
component doc files for ADF.
|
||||
|
||||
## Setup
|
||||
|
||||
The schematic uses Angular CLI, so you must first install this tool using the instructions
|
||||
on their [GitHub page](https://github.com/angular/angular-cli), if you have not already done so.
|
||||
|
||||
To set up the schematic itself for use, `cd` into the root `alfresco-ng2-components` folder and type:
|
||||
|
||||
npm link tools\schematics\adf
|
||||
|
||||
## Usage
|
||||
|
||||
The schematic works with the `ng generate` command. The name of the schematic is `adf:docpage` and
|
||||
it also requires the library name and filename as parameters. The general format is:
|
||||
|
||||
ng generate adf:docpage lib/comp-name.type.md
|
||||
|
||||
Here, `lib` is one of the ADF libraries (`content-services`, `core`, `process-services`
|
||||
or `insights`). The `type` portion refers to the class type the doc page refers to
|
||||
(component, service, model, etc). So,
|
||||
|
||||
ng generate adf:docpage core/arc-reactor.service.md
|
||||
|
||||
...will generate a page for the Arc Reactor service in the core library. Note that the name of the
|
||||
doc file should match the name of the Typescript file where the class is defined
|
||||
(arc-reactor.service.ts, in this case).
|
600
tools/schematics/adf/package-lock.json
generated
Normal file
600
tools/schematics/adf/package-lock.json
generated
Normal file
@@ -0,0 +1,600 @@
|
||||
{
|
||||
"name": "adf",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.5.9.tgz",
|
||||
"integrity": "sha512-SH2/tvs9IGzfDDaUZ1uqLlNPTzaidPWdcT3AA3lYi4hS6ZU8zF1kGw+8Xa9CZR/3JhjMAxmNoqtIcTzt2WmlqQ==",
|
||||
"requires": {
|
||||
"ajv": "6.4.0",
|
||||
"chokidar": "1.7.0",
|
||||
"rxjs": "6.0.0",
|
||||
"source-map": "0.5.7"
|
||||
}
|
||||
},
|
||||
"@angular-devkit/schematics": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.5.9.tgz",
|
||||
"integrity": "sha512-4DSjQUFthXqoDlZ5+ml2UvxlP29fv08FeVRbkKgofNSqC3N4QiCn/8I2PksGzcdHAXTiBGmBcgXwGbDb5zTkqA==",
|
||||
"requires": {
|
||||
"@angular-devkit/core": "0.5.9",
|
||||
"@ngtools/json-schema": "1.1.0",
|
||||
"rxjs": "6.0.0"
|
||||
}
|
||||
},
|
||||
"@ngtools/json-schema": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.1.0.tgz",
|
||||
"integrity": "sha1-w6DFRNYjkqzCgTpCyKDcb1j4aSI="
|
||||
},
|
||||
"@types/jasmine": {
|
||||
"version": "2.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz",
|
||||
"integrity": "sha512-clg9raJTY0EOo5pVZKX3ZlMjlYzVU73L71q5OV1jhE2Uezb7oF94jh4CvwrW6wInquQAdhOxJz5VDF2TLUGmmA=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "8.10.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.10.tgz",
|
||||
"integrity": "sha512-p3W/hFzQs76RlYRIZsZc5a9bht6m0TspmWYYbKhRswmLnwj9fsE40EbuGifeu/XWR/c0UJQ1DDbvTxIsm/OOAA=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz",
|
||||
"integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=",
|
||||
"requires": {
|
||||
"fast-deep-equal": "1.1.0",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"json-schema-traverse": "0.3.1",
|
||||
"uri-js": "3.0.2"
|
||||
}
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
|
||||
"integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
|
||||
"requires": {
|
||||
"micromatch": "2.3.11",
|
||||
"normalize-path": "2.1.1"
|
||||
}
|
||||
},
|
||||
"arr-diff": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
|
||||
"integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
|
||||
"requires": {
|
||||
"arr-flatten": "1.1.0"
|
||||
}
|
||||
},
|
||||
"arr-flatten": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
|
||||
"integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
|
||||
},
|
||||
"array-unique": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
|
||||
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
|
||||
},
|
||||
"async-each": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
|
||||
"integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
|
||||
"integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
|
||||
"integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
|
||||
"requires": {
|
||||
"expand-range": "1.8.2",
|
||||
"preserve": "0.2.0",
|
||||
"repeat-element": "1.1.2"
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
|
||||
"integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
|
||||
"requires": {
|
||||
"anymatch": "1.3.2",
|
||||
"async-each": "1.0.1",
|
||||
"glob-parent": "2.0.0",
|
||||
"inherits": "2.0.3",
|
||||
"is-binary-path": "1.0.1",
|
||||
"is-glob": "2.0.1",
|
||||
"path-is-absolute": "1.0.1",
|
||||
"readdirp": "2.1.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"ejs": {
|
||||
"version": "2.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz",
|
||||
"integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ=="
|
||||
},
|
||||
"exit": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
"integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
|
||||
"integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
|
||||
"requires": {
|
||||
"is-posix-bracket": "0.1.1"
|
||||
}
|
||||
},
|
||||
"expand-range": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
|
||||
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
|
||||
"requires": {
|
||||
"fill-range": "2.2.3"
|
||||
}
|
||||
},
|
||||
"extglob": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
|
||||
"integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
|
||||
"requires": {
|
||||
"is-extglob": "1.0.0"
|
||||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"filename-regex": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
|
||||
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
|
||||
"integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
|
||||
"requires": {
|
||||
"is-number": "2.1.0",
|
||||
"isobject": "2.1.0",
|
||||
"randomatic": "1.1.7",
|
||||
"repeat-element": "1.1.2",
|
||||
"repeat-string": "1.6.1"
|
||||
}
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
|
||||
},
|
||||
"for-own": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
|
||||
"integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
|
||||
"requires": {
|
||||
"for-in": "1.0.2"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"requires": {
|
||||
"fs.realpath": "1.0.0",
|
||||
"inflight": "1.0.6",
|
||||
"inherits": "2.0.3",
|
||||
"minimatch": "3.0.4",
|
||||
"once": "1.4.0",
|
||||
"path-is-absolute": "1.0.1"
|
||||
}
|
||||
},
|
||||
"glob-base": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
|
||||
"integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
|
||||
"requires": {
|
||||
"glob-parent": "2.0.0",
|
||||
"is-glob": "2.0.1"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
|
||||
"integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
|
||||
"requires": {
|
||||
"is-glob": "2.0.1"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "1.4.0",
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
||||
"integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
|
||||
"requires": {
|
||||
"binary-extensions": "1.11.0"
|
||||
}
|
||||
},
|
||||
"is-buffer": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
},
|
||||
"is-dotfile": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
|
||||
"integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="
|
||||
},
|
||||
"is-equal-shallow": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
|
||||
"integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
|
||||
"requires": {
|
||||
"is-primitive": "2.0.0"
|
||||
}
|
||||
},
|
||||
"is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
|
||||
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
|
||||
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
|
||||
"requires": {
|
||||
"is-extglob": "1.0.0"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
|
||||
"integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
|
||||
"requires": {
|
||||
"kind-of": "3.2.2"
|
||||
}
|
||||
},
|
||||
"is-posix-bracket": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
|
||||
"integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="
|
||||
},
|
||||
"is-primitive": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
|
||||
"integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isobject": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
|
||||
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
|
||||
"requires": {
|
||||
"isarray": "1.0.0"
|
||||
}
|
||||
},
|
||||
"jasmine": {
|
||||
"version": "2.99.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.99.0.tgz",
|
||||
"integrity": "sha1-jKctEC5jm4Z8ZImFbg4YqceqQrc=",
|
||||
"requires": {
|
||||
"exit": "0.1.2",
|
||||
"glob": "7.1.2",
|
||||
"jasmine-core": "2.99.1"
|
||||
}
|
||||
},
|
||||
"jasmine-core": {
|
||||
"version": "2.99.1",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
|
||||
"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
||||
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
|
||||
"requires": {
|
||||
"is-buffer": "1.1.6"
|
||||
}
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "2.3.11",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
|
||||
"integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
|
||||
"requires": {
|
||||
"arr-diff": "2.0.0",
|
||||
"array-unique": "0.2.1",
|
||||
"braces": "1.8.5",
|
||||
"expand-brackets": "0.1.5",
|
||||
"extglob": "0.3.2",
|
||||
"filename-regex": "2.0.1",
|
||||
"is-extglob": "1.0.0",
|
||||
"is-glob": "2.0.1",
|
||||
"kind-of": "3.2.2",
|
||||
"normalize-path": "2.1.1",
|
||||
"object.omit": "2.0.1",
|
||||
"parse-glob": "3.0.4",
|
||||
"regex-cache": "0.4.4"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "1.1.11"
|
||||
}
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
|
||||
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
|
||||
"requires": {
|
||||
"remove-trailing-separator": "1.1.0"
|
||||
}
|
||||
},
|
||||
"object.omit": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
|
||||
"integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
|
||||
"requires": {
|
||||
"for-own": "0.1.5",
|
||||
"is-extendable": "0.1.1"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"parse-glob": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
|
||||
"integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
|
||||
"requires": {
|
||||
"glob-base": "0.3.0",
|
||||
"is-dotfile": "1.0.3",
|
||||
"is-extglob": "1.0.0",
|
||||
"is-glob": "2.0.1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"preserve": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
|
||||
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz",
|
||||
"integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0="
|
||||
},
|
||||
"randomatic": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
|
||||
"integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
|
||||
"requires": {
|
||||
"is-number": "3.0.0",
|
||||
"kind-of": "4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-number": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
||||
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
|
||||
"requires": {
|
||||
"kind-of": "3.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"kind-of": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
||||
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
|
||||
"requires": {
|
||||
"is-buffer": "1.1.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
|
||||
"integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
|
||||
"requires": {
|
||||
"is-buffer": "1.1.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "1.0.0",
|
||||
"process-nextick-args": "2.0.0",
|
||||
"safe-buffer": "5.1.2",
|
||||
"string_decoder": "1.1.1",
|
||||
"util-deprecate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
|
||||
"integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
|
||||
"requires": {
|
||||
"graceful-fs": "4.1.11",
|
||||
"minimatch": "3.0.4",
|
||||
"readable-stream": "2.3.6",
|
||||
"set-immediate-shim": "1.0.1"
|
||||
}
|
||||
},
|
||||
"regex-cache": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
|
||||
"integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
|
||||
"requires": {
|
||||
"is-equal-shallow": "0.1.3"
|
||||
}
|
||||
},
|
||||
"remove-trailing-separator": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
|
||||
},
|
||||
"repeat-element": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
|
||||
"integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo="
|
||||
},
|
||||
"repeat-string": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.0.0.tgz",
|
||||
"integrity": "sha512-2MgLQr1zvks8+Kip4T6hcJdiBhV+SIvxguoWjhwtSpNPTp/5e09HJbgclCwR/nW0yWzhubM+6Q0prl8G5RuoBA==",
|
||||
"requires": {
|
||||
"tslib": "1.9.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"set-immediate-shim": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
|
||||
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
|
||||
"integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz",
|
||||
"integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw=="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz",
|
||||
"integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=",
|
||||
"requires": {
|
||||
"punycode": "2.1.0"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
}
|
24
tools/schematics/adf/package.json
Normal file
24
tools/schematics/adf/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "adf",
|
||||
"version": "0.0.0",
|
||||
"description": "A blank schematics",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"test": "npm run build && jasmine **/*_spec.js"
|
||||
},
|
||||
"keywords": [
|
||||
"schematics"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"schematics": "./src/collection.json",
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "^0.5.8",
|
||||
"@angular-devkit/schematics": "^0.5.8",
|
||||
"@types/jasmine": "^2.6.0",
|
||||
"@types/node": "^8.0.31",
|
||||
"ejs": "^2.5.9",
|
||||
"jasmine": "^2.8.0",
|
||||
"typescript": "^2.5.2"
|
||||
}
|
||||
}
|
2
tools/schematics/adf/src/adf/index.d.ts
vendored
Normal file
2
tools/schematics/adf/src/adf/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { Rule } from '@angular-devkit/schematics';
|
||||
export declare function docpage(options: any): Rule;
|
33
tools/schematics/adf/src/adf/index.js
Normal file
33
tools/schematics/adf/src/adf/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const schematics_1 = require("@angular-devkit/schematics");
|
||||
function docpage(options) {
|
||||
let nameParts = options.name.match(/([a-zA-Z-0-9_\-]+)\.(component|directive|interface|model|pipe|service|widget)/);
|
||||
if (!nameParts) {
|
||||
throw new schematics_1.SchematicsException('Doc filename in wrong format. Must be "lib-name/file-name.type.md"');
|
||||
}
|
||||
let libFolder = options.path.match(/\/([a-zA-Z-0-9_\-]+)/)[1];
|
||||
if (!libFolder.match(/content-services|core|process-services|insights/)) {
|
||||
throw new schematics_1.SchematicsException(`Folder "${libFolder}" is not a valid ADF library (must be "content-services", "core", "process-services" or "insights".`);
|
||||
}
|
||||
let templateContext = {
|
||||
"name": options.name,
|
||||
"basename": nameParts[1],
|
||||
"displayName": dekebabifyName(nameParts[1]),
|
||||
"type": nameParts[2]
|
||||
};
|
||||
const templateSource = schematics_1.apply(schematics_1.url('./templates'), [
|
||||
schematics_1.template(templateContext),
|
||||
schematics_1.move("docs/" + libFolder)
|
||||
]);
|
||||
return schematics_1.chain([
|
||||
schematics_1.mergeWith(templateSource)
|
||||
]);
|
||||
}
|
||||
exports.docpage = docpage;
|
||||
function dekebabifyName(name) {
|
||||
var result = name.replace(/-/g, " ");
|
||||
result = result.substr(0, 1).toUpperCase() + result.substr(1);
|
||||
return result;
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
1
tools/schematics/adf/src/adf/index.js.map
Normal file
1
tools/schematics/adf/src/adf/index.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;AAAA,2DAGoC;AAIpC,iBAAwB,OAAY;IAClC,IAAI,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,+EAA+E,CAAC,CAAC;IAEpH,IAAI,CAAC,SAAS,EAAE;QACd,MAAM,IAAI,gCAAmB,CAAC,oEAAoE,CAAC,CAAC;KACrG;IAED,IAAI,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,iDAAiD,CAAC,EAAE;QACvE,MAAM,IAAI,gCAAmB,CAAC,WAAW,SAAS,qGAAqG,CAAC,CAAC;KAC1J;IAED,IAAI,eAAe,GAAG;QAClB,MAAM,EAAE,OAAO,CAAC,IAAI;QACpB,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QACxB,aAAa,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;KACvB,CAAA;IAED,MAAM,cAAc,GAAG,kBAAK,CAAC,gBAAG,CAAC,aAAa,CAAC,EAAE;QAC/C,qBAAQ,CAAC,eAAe,CAAC;QACzB,iBAAI,CAAC,OAAO,GAAG,SAAS,CAAC;KAC1B,CAAC,CAAC;IAEH,OAAO,kBAAK,CAAC;QACX,sBAAS,CAAC,cAAc,CAAC;KAC1B,CAAC,CAAC;AAEL,CAAC;AA7BD,0BA6BC;AAGD,wBAAwB,IAAY;IAClC,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
1
tools/schematics/adf/src/adf/index_spec.d.ts
vendored
Normal file
1
tools/schematics/adf/src/adf/index_spec.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
14
tools/schematics/adf/src/adf/index_spec.js
Normal file
14
tools/schematics/adf/src/adf/index_spec.js
Normal file
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const schematics_1 = require("@angular-devkit/schematics");
|
||||
const testing_1 = require("@angular-devkit/schematics/testing");
|
||||
const path = require("path");
|
||||
const collectionPath = path.join(__dirname, '../collection.json');
|
||||
describe('adf', () => {
|
||||
it('works', () => {
|
||||
const runner = new testing_1.SchematicTestRunner('schematics', collectionPath);
|
||||
const tree = runner.runSchematic('adf', {}, schematics_1.Tree.empty());
|
||||
expect(tree.files).toEqual([]);
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=index_spec.js.map
|
1
tools/schematics/adf/src/adf/index_spec.js.map
Normal file
1
tools/schematics/adf/src/adf/index_spec.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index_spec.js","sourceRoot":"","sources":["index_spec.ts"],"names":[],"mappings":";;AAAA,2DAAkD;AAClD,gEAAyE;AACzE,6BAA6B;AAG7B,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAGlE,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;IACnB,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACf,MAAM,MAAM,GAAG,IAAI,6BAAmB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,iBAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAE1D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
@@ -0,0 +1,34 @@
|
||||
---
|
||||
Added: v2.4.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# <%= displayName + " " + type %>
|
||||
|
||||
One-line description for the index page goes here.
|
||||
|
||||

|
||||
|
||||
## Basic usage
|
||||
|
||||
Typescript and/or HTML usage sample goes here. Delete this section if you
|
||||
don't need it.
|
||||
|
||||
## Class members
|
||||
|
||||
Don't add anything here. Use "npm run docbuild" from the "lib"
|
||||
folder to generate property and method tables from the JSDocs.
|
||||
|
||||
## Details
|
||||
|
||||
Main text goes here.
|
||||
|
||||
### Subsection
|
||||
|
||||
Use level 3 subsections within the Details section to introduce
|
||||
topics.
|
||||
|
||||
## See also
|
||||
|
||||
- [Delete this section](link1.md)
|
||||
- [if you don't need it](link2.md)
|
9
tools/schematics/adf/src/collection.json
Normal file
9
tools/schematics/adf/src/collection.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
|
||||
"schematics": {
|
||||
"docpage": {
|
||||
"description": "Creates a new documentation file for an ADF component.",
|
||||
"factory": "./adf/index#docpage"
|
||||
}
|
||||
}
|
||||
}
|
34
tools/schematics/adf/tsconfig.json
Normal file
34
tools/schematics/adf/tsconfig.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "tsconfig",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"declaration": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUnusedLocals": true,
|
||||
"rootDir": "src/",
|
||||
"skipDefaultLibCheck": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strictNullChecks": true,
|
||||
"target": "es6",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/*/files/**/*"
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user