@irwinproject/storybook-addon-tsdoc
Version:
Generate mdx documentation from your typescript!
85 lines (84 loc) • 5.28 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.nodesig = exports.typeFromType = void 0;
const ts_morph_1 = require("ts-morph");
const decorators_1 = require("./decorators");
const constants_1 = require("./constants");
const TS_1 = __importDefault(require("./TS"));
const node_tools_1 = require("./node-tools");
const utils_1 = require("./utils");
const modifiers = (node) => ts_morph_1.Node.isModifierable(node) ? node.getModifiers().map(n => n.getText()).join(' ').wrap('', ' ') : '';
const name = (node) => ts_morph_1.Node.isNamed(node) ? (0, exports.nodesig)(node.getNameNode())
: ts_morph_1.Node.hasName(node) ? node.getName()
: '';
const typeFromTag = (node) => {
var _a, _b;
if (ts_morph_1.Node.isVariableDeclaration(node)) {
return typeFromTag(node.getVariableStatement());
}
if (!ts_morph_1.Node.isJSDocable(node))
return '';
const typeTag = (_b = (_a = (0, node_tools_1.getJsDocs)(node).flatMap(d => d.getTags()).find(t => t.getTagName() === 'type')) === null || _a === void 0 ? void 0 : _a.getTypeExpression()) === null || _b === void 0 ? void 0 : _b.getTypeNode();
if (!typeTag)
return '';
return (0, exports.nodesig)(typeTag);
};
const isPrimitiveType = (t) => t.isAny() || t.isBigInt() || t.isNever() || t.isNull() || t.isNumber() || t.isString() || t.isBoolean() || t.isUndefined();
const isPrimitiveLiteral = (t) => t.isBigIntLiteral() || t.isNumberLiteral() || t.isStringLiteral() || t.isTemplateLiteral() || t.isBooleanLiteral();
/**
* Diving down to the underlying type provides lower level access to the typing however ts-morph provides a wonderul interface via their Node class. Since it completely crawls the Source File it seems more suitable to get the dclaration that is being referenced
* @param t
* @returns
*/
const typeFromType = (t) => {
var _a, _b;
if (!t)
return '';
if (isPrimitiveType(t))
return (0, decorators_1.$type)(t.getText());
if (isPrimitiveLiteral(t))
return (0, decorators_1.$literal)((0, utils_1.escape)(t.getText()));
const args = t.getTypeArguments().map(exports.typeFromType).filter(n => !!n).join(', ').wrap('<', '>');
const symbol = (_a = t.getSymbol()) !== null && _a !== void 0 ? _a : t.getAliasSymbol();
const [dec] = (_b = symbol === null || symbol === void 0 ? void 0 : symbol.getDeclarations()) !== null && _b !== void 0 ? _b : [];
if (dec) {
return (ts_morph_1.Node.isExpression(dec) ? (ts_morph_1.Node.isNewExpression(dec) ? (0, decorators_1.$kd) `new` : '') + (0, decorators_1.$link)(dec.getParent()) : (0, decorators_1.$link)(dec)) + args;
}
return t.isUnion() ? t.getUnionTypes().map(exports.typeFromType).join(' | ')
: t.isTuple() ? t.getTupleElements().map(exports.typeFromType).join(', ').wrap('[', ']')
: t.isArray() ? (0, exports.typeFromType)(t.getArrayElementType()) + '[]'
: t.isIntersection() ? t.getIntersectionTypes().map(exports.typeFromType).join(' & ')
: '';
};
exports.typeFromType = typeFromType;
const typeFromInitializer = (node) => ((ts_morph_1.Node.isInitializerExpressionGetable(node) || ts_morph_1.Node.isInitializerExpressionable(node)) && (0, exports.nodesig)(node.getInitializer()))
|| ''; //dont return false
const typeParameters = (node) => ts_morph_1.Node.isTypeParametered(node) ? node.getTypeParameters().map(exports.nodesig).join(', ').wrap('<', '>') : '';
const typeArguments = (node) => ts_morph_1.Node.isTypeArgumented(node) ? node.getTypeArguments().map(exports.nodesig).join(', ').wrap('<', '>') : '';
const typing = (node) => (ts_morph_1.Node.isTyped(node) && (0, exports.nodesig)(node.getTypeNode()).wrap(': ', '')) //typenodes get precedence
|| typeFromTag(node) // then jsdocs can override initializers
|| typeFromInitializer(node) //Attempt to get the type from an initializer.
|| (0, exports.typeFromType)(node.getType()) //And if all else fails attempt to get the type from the Type interface.
|| '';
const nlog = (...args) => {
TS_1.default.log(...args);
return (strings, ...args) => {
var _a;
let str = '';
for (let i = 0; i < strings.length; i++) {
str += `${strings[i]}${(_a = args[i]) !== null && _a !== void 0 ? _a : ''}`;
}
return str;
};
};
const nodesig = (node) => ((0, node_tools_1.isKeyword)(node) && (0, decorators_1.$type)(node.getText()))
|| ((ts_morph_1.Node.isTypeLiteral(node) || ts_morph_1.Node.isObjectLiteralExpression(node)) && (0, decorators_1.$literal)(constants_1.typelit))
|| (ts_morph_1.Node.isArrayLiteralExpression(node) && node.getElements().map(exports.nodesig).join(', ').wrap('[', ']'))
|| (ts_morph_1.Node.isLiteralExpression(node) && (0, decorators_1.$literal)((0, utils_1.escape)(node.getText())))
|| (node && ts_morph_1.Node.hasName(node) && nlog(node.getKindName(), node.getName()) `${modifiers(node)}${typeArguments(node)}${name(node)}${typing(node).wrap(": ", "")}`)
|| (node && nlog(node.getKindName()) `No support`)
|| '';
exports.nodesig = nodesig;