@storybook/addon-docs
Version:
Document component usage and properties in Markdown
229 lines (177 loc) • 5.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parseJsDoc = void 0;
require("core-js/modules/es.array.includes.js");
require("core-js/modules/es.string.includes.js");
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.function.name.js");
require("core-js/modules/es.string.replace.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.array.map.js");
require("core-js/modules/es.array.concat.js");
require("core-js/modules/es.array.join.js");
var _doctrine = _interopRequireDefault(require("doctrine"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function containsJsDoc(value) {
return value != null && value.includes('@');
}
function parse(content, tags) {
var ast;
try {
ast = _doctrine.default.parse(content, {
tags: tags,
sloppy: true
});
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
throw new Error('Cannot parse JSDoc tags.');
}
return ast;
}
var DEFAULT_OPTIONS = {
tags: ['param', 'arg', 'argument', 'returns', 'ignore']
};
var parseJsDoc = function parseJsDoc(value) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_OPTIONS;
if (!containsJsDoc(value)) {
return {
includesJsDoc: false,
ignore: false
};
}
var jsDocAst = parse(value, options.tags);
var extractedTags = extractJsDocTags(jsDocAst);
if (extractedTags.ignore) {
// There is no point in doing other stuff since this prop will not be rendered.
return {
includesJsDoc: true,
ignore: true
};
}
return {
includesJsDoc: true,
ignore: false,
// Always use the parsed description to ensure JSDoc is removed from the description.
description: jsDocAst.description,
extractedTags: extractedTags
};
};
exports.parseJsDoc = parseJsDoc;
function extractJsDocTags(ast) {
var extractedTags = {
params: null,
returns: null,
ignore: false
};
for (var i = 0; i < ast.tags.length; i += 1) {
var tag = ast.tags[i];
if (tag.title === 'ignore') {
extractedTags.ignore = true; // Once we reach an @ignore tag, there is no point in parsing the other tags since we will not render the prop.
break;
} else {
switch (tag.title) {
// arg & argument are aliases for param.
case 'param':
case 'arg':
case 'argument':
{
var paramTag = extractParam(tag);
if (paramTag != null) {
if (extractedTags.params == null) {
extractedTags.params = [];
}
extractedTags.params.push(paramTag);
}
break;
}
case 'returns':
{
var returnsTag = extractReturns(tag);
if (returnsTag != null) {
extractedTags.returns = returnsTag;
}
break;
}
default:
break;
}
}
}
return extractedTags;
}
function extractParam(tag) {
var paramName = tag.name; // When the @param doesn't have a name but have a type and a description, "null-null" is returned.
if (paramName != null && paramName !== 'null-null') {
return {
name: tag.name,
type: tag.type,
description: tag.description,
getPrettyName: function getPrettyName() {
if (paramName.includes('null')) {
// There is a few cases in which the returned param name contains "null".
// - @param {SyntheticEvent} event- Original SyntheticEvent
// - @param {SyntheticEvent} event.\n@returns {string}
return paramName.replace('-null', '').replace('.null', '');
}
return tag.name;
},
getTypeName: function getTypeName() {
return tag.type != null ? extractTypeName(tag.type) : null;
}
};
}
return null;
}
function extractReturns(tag) {
if (tag.type != null) {
return {
type: tag.type,
description: tag.description,
getTypeName: function getTypeName() {
return extractTypeName(tag.type);
}
};
}
return null;
}
function extractTypeName(type) {
if (type.type === 'NameExpression') {
return type.name;
}
if (type.type === 'RecordType') {
var recordFields = type.fields.map(function (field) {
if (field.value != null) {
var valueTypeName = extractTypeName(field.value);
return "".concat(field.key, ": ").concat(valueTypeName);
}
return field.key;
});
return "({".concat(recordFields.join(', '), "})");
}
if (type.type === 'UnionType') {
var unionElements = type.elements.map(extractTypeName);
return "(".concat(unionElements.join('|'), ")");
} // Only support untyped array: []. Might add more support later if required.
if (type.type === 'ArrayType') {
return '[]';
}
if (type.type === 'TypeApplication') {
if (type.expression != null) {
if (type.expression.name === 'Array') {
var arrayType = extractTypeName(type.applications[0]);
return "".concat(arrayType, "[]");
}
}
}
if (type.type === 'NullableType' || type.type === 'NonNullableType' || type.type === 'OptionalType') {
return extractTypeName(type.expression);
}
if (type.type === 'AllLiteral') {
return 'any';
}
return null;
}
;