typedoc
Version:
Create api documentation for TypeScript projects.
84 lines (83 loc) • 4.1 kB
JavaScript
import { i18n } from "#utils";
import { ReflectionKind, ReflectionSymbolId, } from "../models/index.js";
const linkTags = ["@link", "@linkcode", "@linkplain"];
function getBrokenPartLinks(parts) {
const links = [];
for (const part of parts) {
if (part.kind === "inline-tag" &&
linkTags.includes(part.tag) &&
(!part.target || part.target instanceof ReflectionSymbolId)) {
links.push(part.text.trim());
}
}
return links;
}
function getBrokenLinks(comment) {
if (!comment)
return [];
const links = [...getBrokenPartLinks(comment.summary)];
for (const tag of comment.blockTags) {
links.push(...getBrokenPartLinks(tag.content));
}
return links;
}
export function validateLinks(project, logger) {
for (const id in project.reflections) {
checkReflection(project.reflections[id], logger);
}
if (!(project.id in project.reflections)) {
checkReflection(project, logger);
}
}
function checkReflection(reflection, logger) {
if (reflection.isProject() || reflection.isDeclaration()) {
for (const broken of getBrokenPartLinks(reflection.readme || [])) {
// #2360, "@" is a future reserved character in TSDoc component paths
// If a link starts with it, and doesn't include a module source indicator "!"
// then the user probably is trying to link to a package containing "@" with an absolute link.
if (broken.startsWith("@") && !broken.includes("!")) {
logger.warn(i18n.failed_to_resolve_link_to_0_in_readme_for_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
}
else {
logger.warn(i18n.failed_to_resolve_link_to_0_in_readme_for_1(broken, reflection.getFriendlyFullName()));
}
}
}
if (reflection.isDocument()) {
for (const broken of getBrokenPartLinks(reflection.content)) {
// #2360, "@" is a future reserved character in TSDoc component paths
// If a link starts with it, and doesn't include a module source indicator "!"
// then the user probably is trying to link to a package containing "@" with an absolute link.
if (broken.startsWith("@") && !broken.includes("!")) {
logger.warn(i18n.failed_to_resolve_link_to_0_in_document_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
}
else {
logger.warn(i18n.failed_to_resolve_link_to_0_in_document_1(broken, reflection.getFriendlyFullName()));
}
}
}
for (const broken of getBrokenLinks(reflection.comment)) {
// #2360, "@" is a future reserved character in TSDoc component paths
// If a link starts with it, and doesn't include a module source indicator "!"
// then the user probably is trying to link to a package containing "@" with an absolute link.
if (broken.startsWith("@") && !broken.includes("!")) {
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
}
else {
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1(broken, reflection.getFriendlyFullName()));
}
}
if (reflection.isDeclaration() &&
reflection.kindOf(ReflectionKind.TypeAlias) &&
reflection.type?.type === "union" &&
reflection.type.elementSummaries) {
for (const broken of reflection.type.elementSummaries.flatMap(getBrokenPartLinks)) {
if (broken.startsWith("@") && !broken.includes("!")) {
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
}
else {
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1(broken, reflection.getFriendlyFullName()));
}
}
}
}