mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-2764] Added tool to add links to type names in Markdown files (#3226)
* [ADF-2764] Added basic type linker tool * [ADF-2764] Support for class links in body text * [ADF-2764] Started support for multi-word class names (not working yet) * [ADF-2764] Updated script to handle English component names
This commit is contained in:
committed by
Eugenio Romano
parent
b580efb7f6
commit
8f27cd1758
@@ -8,6 +8,10 @@
|
||||
"enhance": [
|
||||
"tsInfo",
|
||||
"toc"
|
||||
],
|
||||
"dev": [
|
||||
"tsInfo",
|
||||
"typeLinker"
|
||||
]
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
module.exports = {
|
||||
"ngNameToDisplayName": ngNameToDisplayName,
|
||||
"dekebabifyName": dekebabifyName,
|
||||
"kebabifyClassName": kebabifyClassName,
|
||||
"classTypes": ["component", "directive", "model", "pipe", "service", "widget"]
|
||||
}
|
||||
|
||||
@@ -12,8 +13,23 @@ function ngNameToDisplayName(ngName) {
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
289
lib/config/DocProcessor/tools/typeLinker.js
Normal file
289
lib/config/DocProcessor/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
lib/config/DocProcessor/tools/typeLinker.ts
Normal file
359
lib/config/DocProcessor/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];
|
||||
}
|
Reference in New Issue
Block a user