From 611b3af79685559540e778d768b70ee05004ee2e Mon Sep 17 00:00:00 2001 From: Steve Landey Date: Thu, 5 Sep 2024 08:41:08 -0700 Subject: [PATCH] Link resolution is more predictable and less overall stupid (#47) * Link resolution is more predictable and less overall stupid * Update typedoc link mapping * Go back to resolving hashed mapped links correctly * Fixes for mapped links --- docs/out/gfm/features/typedoc.md | 2 +- docs/out/gfm/typescript_link_mapping.json | 87 +++++-- docs/src/typescript_link_mapping.json | 87 +++++-- src/plugins/linkRewritingPlugin.test.ts | 48 +++- src/plugins/linkRewritingPlugin.ts | 289 +++++++++++++--------- 5 files changed, 359 insertions(+), 154 deletions(-) diff --git a/docs/out/gfm/features/typedoc.md b/docs/out/gfm/features/typedoc.md index ecf5be8..1567dea 100644 --- a/docs/out/gfm/features/typedoc.md +++ b/docs/out/gfm/features/typedoc.md @@ -32,7 +32,7 @@ Djockey can integrate with [TypeDoc](https://typedoc.org) to create an integrated documentation experience that combines the authoring power of Djockey with rich API references. For example, here in the Djockey docs, we can type `[](:ts:DjockeyPlugin)` and get -[DjockeyPlugin](../api//interfaces/DjockeyPlugin.html). +[DjockeyPlugin](../api/interfaces/DjockeyPlugin.html). The core concept is to render TypeDoc normally inside your docs directory, treat its output as static files, and then create convenient diff --git a/docs/out/gfm/typescript_link_mapping.json b/docs/out/gfm/typescript_link_mapping.json index 69cb4f9..3b95571 100644 --- a/docs/out/gfm/typescript_link_mapping.json +++ b/docs/out/gfm/typescript_link_mapping.json @@ -106,6 +106,16 @@ "relativeURL": "classes/LogCollector.html#label", "defaultLabel": "label" }, + { + "linkDestination": "LogCollector.hasWarningsOrErrors", + "relativeURL": "classes/LogCollector.html#hasWarningsOrErrors", + "defaultLabel": "hasWarningsOrErrors" + }, + { + "linkDestination": "hasWarningsOrErrors", + "relativeURL": "classes/LogCollector.html#hasWarningsOrErrors", + "defaultLabel": "hasWarningsOrErrors" + }, { "linkDestination": "LogCollector.debug", "relativeURL": "classes/LogCollector.html#debug", @@ -146,6 +156,16 @@ "relativeURL": "classes/LogCollector.html#fail", "defaultLabel": "fail" }, + { + "linkDestination": "LogCollector.getChild", + "relativeURL": "classes/LogCollector.html#getChild", + "defaultLabel": "getChild" + }, + { + "linkDestination": "getChild", + "relativeURL": "classes/LogCollector.html#getChild", + "defaultLabel": "getChild" + }, { "linkDestination": "LogCollector.info", "relativeURL": "classes/LogCollector.html#info", @@ -431,16 +451,6 @@ "relativeURL": "interfaces/DjockeyDoc.html", "defaultLabel": "DjockeyDoc" }, - { - "linkDestination": "DjockeyDoc.absolutePath", - "relativeURL": "interfaces/DjockeyDoc.html#absolutePath", - "defaultLabel": "absolutePath" - }, - { - "linkDestination": "absolutePath", - "relativeURL": "interfaces/DjockeyDoc.html#absolutePath", - "defaultLabel": "absolutePath" - }, { "linkDestination": "DjockeyDoc.data", "relativeURL": "interfaces/DjockeyDoc.html#data", @@ -481,6 +491,16 @@ "relativeURL": "interfaces/DjockeyDoc.html#frontMatter", "defaultLabel": "frontMatter" }, + { + "linkDestination": "DjockeyDoc.fsPath", + "relativeURL": "interfaces/DjockeyDoc.html#fsPath", + "defaultLabel": "fsPath" + }, + { + "linkDestination": "fsPath", + "relativeURL": "interfaces/DjockeyDoc.html#fsPath", + "defaultLabel": "fsPath" + }, { "linkDestination": "DjockeyDoc.neighbors", "relativeURL": "interfaces/DjockeyDoc.html#neighbors", @@ -502,14 +522,14 @@ "defaultLabel": "originalExtension" }, { - "linkDestination": "DjockeyDoc.relativePath", - "relativeURL": "interfaces/DjockeyDoc.html#relativePath", - "defaultLabel": "relativePath" + "linkDestination": "DjockeyDoc.refPath", + "relativeURL": "interfaces/DjockeyDoc.html#refPath", + "defaultLabel": "refPath" }, { - "linkDestination": "relativePath", - "relativeURL": "interfaces/DjockeyDoc.html#relativePath", - "defaultLabel": "relativePath" + "linkDestination": "refPath", + "relativeURL": "interfaces/DjockeyDoc.html#refPath", + "defaultLabel": "refPath" }, { "linkDestination": "DjockeyDoc.title", @@ -626,6 +646,16 @@ "relativeURL": "interfaces/DjockeyPlugin.html#getNodeReservations", "defaultLabel": "getNodeReservations" }, + { + "linkDestination": "DjockeyPlugin.getStaticFiles", + "relativeURL": "interfaces/DjockeyPlugin.html#getStaticFiles", + "defaultLabel": "getStaticFiles" + }, + { + "linkDestination": "getStaticFiles", + "relativeURL": "interfaces/DjockeyPlugin.html#getStaticFiles", + "defaultLabel": "getStaticFiles" + }, { "linkDestination": "DjockeyPlugin.name", "relativeURL": "interfaces/DjockeyPlugin.html#name", @@ -706,6 +736,31 @@ "relativeURL": "interfaces/DjockeyPluginNodeReservation.html#match", "defaultLabel": "match" }, + { + "linkDestination": "DjockeyStaticFileFromPlugin", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html", + "defaultLabel": "DjockeyStaticFileFromPlugin" + }, + { + "linkDestination": "DjockeyStaticFileFromPlugin.contents", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#contents", + "defaultLabel": "contents" + }, + { + "linkDestination": "contents", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#contents", + "defaultLabel": "contents" + }, + { + "linkDestination": "DjockeyStaticFileFromPlugin.path", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#path", + "defaultLabel": "path" + }, + { + "linkDestination": "path", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#path", + "defaultLabel": "path" + }, { "linkDestination": "LinkMappingConfig", "relativeURL": "interfaces/LinkMappingConfig.html", diff --git a/docs/src/typescript_link_mapping.json b/docs/src/typescript_link_mapping.json index 69cb4f9..3b95571 100644 --- a/docs/src/typescript_link_mapping.json +++ b/docs/src/typescript_link_mapping.json @@ -106,6 +106,16 @@ "relativeURL": "classes/LogCollector.html#label", "defaultLabel": "label" }, + { + "linkDestination": "LogCollector.hasWarningsOrErrors", + "relativeURL": "classes/LogCollector.html#hasWarningsOrErrors", + "defaultLabel": "hasWarningsOrErrors" + }, + { + "linkDestination": "hasWarningsOrErrors", + "relativeURL": "classes/LogCollector.html#hasWarningsOrErrors", + "defaultLabel": "hasWarningsOrErrors" + }, { "linkDestination": "LogCollector.debug", "relativeURL": "classes/LogCollector.html#debug", @@ -146,6 +156,16 @@ "relativeURL": "classes/LogCollector.html#fail", "defaultLabel": "fail" }, + { + "linkDestination": "LogCollector.getChild", + "relativeURL": "classes/LogCollector.html#getChild", + "defaultLabel": "getChild" + }, + { + "linkDestination": "getChild", + "relativeURL": "classes/LogCollector.html#getChild", + "defaultLabel": "getChild" + }, { "linkDestination": "LogCollector.info", "relativeURL": "classes/LogCollector.html#info", @@ -431,16 +451,6 @@ "relativeURL": "interfaces/DjockeyDoc.html", "defaultLabel": "DjockeyDoc" }, - { - "linkDestination": "DjockeyDoc.absolutePath", - "relativeURL": "interfaces/DjockeyDoc.html#absolutePath", - "defaultLabel": "absolutePath" - }, - { - "linkDestination": "absolutePath", - "relativeURL": "interfaces/DjockeyDoc.html#absolutePath", - "defaultLabel": "absolutePath" - }, { "linkDestination": "DjockeyDoc.data", "relativeURL": "interfaces/DjockeyDoc.html#data", @@ -481,6 +491,16 @@ "relativeURL": "interfaces/DjockeyDoc.html#frontMatter", "defaultLabel": "frontMatter" }, + { + "linkDestination": "DjockeyDoc.fsPath", + "relativeURL": "interfaces/DjockeyDoc.html#fsPath", + "defaultLabel": "fsPath" + }, + { + "linkDestination": "fsPath", + "relativeURL": "interfaces/DjockeyDoc.html#fsPath", + "defaultLabel": "fsPath" + }, { "linkDestination": "DjockeyDoc.neighbors", "relativeURL": "interfaces/DjockeyDoc.html#neighbors", @@ -502,14 +522,14 @@ "defaultLabel": "originalExtension" }, { - "linkDestination": "DjockeyDoc.relativePath", - "relativeURL": "interfaces/DjockeyDoc.html#relativePath", - "defaultLabel": "relativePath" + "linkDestination": "DjockeyDoc.refPath", + "relativeURL": "interfaces/DjockeyDoc.html#refPath", + "defaultLabel": "refPath" }, { - "linkDestination": "relativePath", - "relativeURL": "interfaces/DjockeyDoc.html#relativePath", - "defaultLabel": "relativePath" + "linkDestination": "refPath", + "relativeURL": "interfaces/DjockeyDoc.html#refPath", + "defaultLabel": "refPath" }, { "linkDestination": "DjockeyDoc.title", @@ -626,6 +646,16 @@ "relativeURL": "interfaces/DjockeyPlugin.html#getNodeReservations", "defaultLabel": "getNodeReservations" }, + { + "linkDestination": "DjockeyPlugin.getStaticFiles", + "relativeURL": "interfaces/DjockeyPlugin.html#getStaticFiles", + "defaultLabel": "getStaticFiles" + }, + { + "linkDestination": "getStaticFiles", + "relativeURL": "interfaces/DjockeyPlugin.html#getStaticFiles", + "defaultLabel": "getStaticFiles" + }, { "linkDestination": "DjockeyPlugin.name", "relativeURL": "interfaces/DjockeyPlugin.html#name", @@ -706,6 +736,31 @@ "relativeURL": "interfaces/DjockeyPluginNodeReservation.html#match", "defaultLabel": "match" }, + { + "linkDestination": "DjockeyStaticFileFromPlugin", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html", + "defaultLabel": "DjockeyStaticFileFromPlugin" + }, + { + "linkDestination": "DjockeyStaticFileFromPlugin.contents", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#contents", + "defaultLabel": "contents" + }, + { + "linkDestination": "contents", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#contents", + "defaultLabel": "contents" + }, + { + "linkDestination": "DjockeyStaticFileFromPlugin.path", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#path", + "defaultLabel": "path" + }, + { + "linkDestination": "path", + "relativeURL": "interfaces/DjockeyStaticFileFromPlugin.html#path", + "defaultLabel": "path" + }, { "linkDestination": "LinkMappingConfig", "relativeURL": "interfaces/LinkMappingConfig.html", diff --git a/src/plugins/linkRewritingPlugin.test.ts b/src/plugins/linkRewritingPlugin.test.ts index 07acac3..2677ba7 100644 --- a/src/plugins/linkRewritingPlugin.test.ts +++ b/src/plugins/linkRewritingPlugin.test.ts @@ -1,7 +1,47 @@ -import { resolveRelativePath } from "./linkRewritingPlugin.js"; +import { Doc } from "@djot/djot"; +import { + MappableLinkTarget, + resolveRelativeRefPath, +} from "./linkRewritingPlugin.js"; test("Resolves explicit relative links", () => { - expect(resolveRelativePath("a/b/c.txt", "./d.txt")).toEqual("/a/b/d.txt"); - expect(resolveRelativePath("a/b/c.txt", "./../d.txt")).toEqual("/a/d.txt"); - expect(resolveRelativePath("a/b/c.txt", "../d.txt")).toEqual("/a/d.txt"); + expect(resolveRelativeRefPath("a/b/c.txt", "./d.txt")).toEqual("/a/b/d.txt"); + expect(resolveRelativeRefPath("a/b/c.txt", "./../d.txt")).toEqual("/a/d.txt"); + expect(resolveRelativeRefPath("a/b/c.txt", "../d.txt")).toEqual("/a/d.txt"); +}); + +test("MappableLinkTarget has expected values", () => { + const stubDoc: Doc = { + tag: "doc", + references: {}, + autoReferences: {}, + footnotes: {}, + children: [], + }; + const t = new MappableLinkTarget( + { + docs: { + content: stubDoc, + }, + title: "The Doc", + titleAST: [], + originalExtension: ".djot", + fsPath: "/fsroot/input/subdir/the_doc.djot", + refPath: "subdir/the_doc", + filename: "the_doc", + frontMatter: {}, + data: {}, + }, + "the-hash" + ); + + expect(t.aliases).toEqual([ + "#the-hash", + "the_doc#the-hash", + "the_doc.djot#the-hash", + "subdir/the_doc#the-hash", + "subdir/the_doc.djot#the-hash", + "/subdir/the_doc#the-hash", + "/subdir/the_doc.djot#the-hash", + ]); }); diff --git a/src/plugins/linkRewritingPlugin.ts b/src/plugins/linkRewritingPlugin.ts index 09e91d7..1764495 100644 --- a/src/plugins/linkRewritingPlugin.ts +++ b/src/plugins/linkRewritingPlugin.ts @@ -11,17 +11,12 @@ import { import { applyFilter } from "../engine/djotFiltersPlus.js"; import { pushToListIfNotPresent } from "../utils/collectionUtils.js"; import { LogCollector } from "../utils/logUtils.js"; -import { - fsjoin, - urlsplit, - URL_SEPARATOR, - CANONICAL_SEPARATOR, -} from "../utils/pathUtils.js"; +import { fsjoin, CANONICAL_SEPARATOR, refsplit } from "../utils/pathUtils.js"; export class LinkRewritingPlugin implements DjockeyPlugin { name = "Link Rewriter"; - private _linkTargets: Record = {}; + private _linkTargets: Record = {}; private _mappedLinkDestinations: Record = {}; private _defaultLinkLabels: Record = {}; @@ -39,7 +34,7 @@ export class LinkRewritingPlugin implements DjockeyPlugin { for (const mapping of data.linkMappings) { for (const ns of data.namespaces) { const dest = `:${ns}:${mapping.linkDestination}`; - const url = `${urlRoot}/${mapping.relativeURL}`; + const url = `/${urlRoot}${mapping.relativeURL}`; if ( this._mappedLinkDestinations[dest] && // Silently ignore duplicate entries of the same thing @@ -57,7 +52,7 @@ export class LinkRewritingPlugin implements DjockeyPlugin { onPass_read(args: { doc: DjockeyDoc }) { const { doc } = args; - const registerLinkTarget = (t: LinkTarget) => { + const registerLinkTarget = (t: MappableLinkTarget) => { t.aliases.forEach((alias) => pushToListIfNotPresent(this._linkTargets, alias, t, (a, b) => a.equals(b) @@ -65,7 +60,7 @@ export class LinkRewritingPlugin implements DjockeyPlugin { ); }; - registerLinkTarget(new LinkTarget(doc, null)); + registerLinkTarget(new MappableLinkTarget(doc, null)); for (const djotDoc of Object.values(doc.docs)) { applyFilter(djotDoc, () => ({ @@ -73,7 +68,7 @@ export class LinkRewritingPlugin implements DjockeyPlugin { const attrs = { ...node.autoAttributes, ...node.attributes }; if (!attrs.id) return; - registerLinkTarget(new LinkTarget(doc, attrs.id)); + registerLinkTarget(new MappableLinkTarget(doc, attrs.id)); }, })); } @@ -119,93 +114,150 @@ export class LinkRewritingPlugin implements DjockeyPlugin { sourcePath: string; inputRoot: string; unresolvedNodeDestination: string; - renderArgs: Parameters[0]; - preventRecursion?: boolean; + renderArgs: Parameters[0]; }): string { - const { - sourcePath, - inputRoot, - unresolvedNodeDestination, - renderArgs, - preventRecursion, - } = args; - // Don't transform ordinary URLs - if (isURL(unresolvedNodeDestination)) { - return unresolvedNodeDestination; - } - - const nodeDestination = this._mappedLinkDestinations[ - unresolvedNodeDestination - ] - ? this._mappedLinkDestinations[unresolvedNodeDestination] - : resolveRelativePath(sourcePath, unresolvedNodeDestination); - - const values = this._linkTargets[nodeDestination]; - if (!values || !values.length) { - const prefixlessNodeDestinationWithHash = nodeDestination.startsWith( - URL_SEPARATOR - ) - ? nodeDestination.slice(1) - : nodeDestination; - - const prefixlessNodeDestination = - prefixlessNodeDestinationWithHash.split("#")[0]; - const anchorWithoutHash = - prefixlessNodeDestination === prefixlessNodeDestinationWithHash - ? null - : prefixlessNodeDestinationWithHash.slice( - prefixlessNodeDestination.length + 1 + const { sourcePath, inputRoot, unresolvedNodeDestination, renderArgs } = + args; + + const parsedLink = parseLink(unresolvedNodeDestination); + + switch (parsedLink.kind) { + case "url": + return parsedLink.original; + case "direct": + const maybeDirectLink = resolveDirectLink( + parsedLink, + sourcePath, + inputRoot, + this._linkTargets, + renderArgs + ); + if (maybeDirectLink) { + return maybeDirectLink; + } else { + renderArgs.logCollector.warning( + `Unable to resolve direct link ${unresolvedNodeDestination} in ${renderArgs.sourcePath}` + ); + return unresolvedNodeDestination; + } + case "unknown": + const maybeMappedLinkDestination = + this._mappedLinkDestinations[parsedLink.path]; + const maybeLinkTargets = + this._linkTargets[maybeAddHash(parsedLink.path, parsedLink.hash)]; + + const maybeDirectLink2 = resolveDirectLink( + { + kind: "direct", + path: `./${parsedLink.path}`, + hash: parsedLink.hash, + original: `./${parsedLink.original}`, + }, + sourcePath, + inputRoot, + this._linkTargets, + renderArgs + ); + + if (maybeDirectLink2) { + return maybeDirectLink2; + } else if (maybeMappedLinkDestination) { + // Easy case: a link map contains this string. + // Interpret it as a static file. + const parsedMappedLink = parseLink(maybeMappedLinkDestination); + if (parsedMappedLink.kind !== "direct") { + renderArgs.logCollector.warning( + "Mapped links should only point to static files" ); - - const possibleStaticFileFSPath = fsjoin([ - inputRoot, - ...urlsplit(prefixlessNodeDestination), - ]); - if (fs.existsSync(possibleStaticFileFSPath)) { - return renderArgs.renderer.transformLink({ - config: renderArgs.config, - sourcePath: renderArgs.sourcePath, - anchorWithoutHash, - docOriginalExtension: path.parse(nodeDestination).ext, - // We can use the destination as-is without modification - docRefPath: prefixlessNodeDestination, - isLinkToStaticFile: true, - logCollector: renderArgs.logCollector, - }); - } else { - if ( - !preventRecursion && - !unresolvedNodeDestination.startsWith(`.${CANONICAL_SEPARATOR}`) - ) { - return this.transformNodeDestination({ + return unresolvedNodeDestination; + } + const resolvedMappedLink = resolveDirectLink( + parsedMappedLink, sourcePath, inputRoot, - unresolvedNodeDestination: `.${CANONICAL_SEPARATOR}${unresolvedNodeDestination}`, - renderArgs, - preventRecursion: true, - }); - } else { - renderArgs.logCollector.warning( - `Not sure what to do with link ${nodeDestination} in ${renderArgs.sourcePath}` + this._linkTargets, + renderArgs ); + if (!resolvedMappedLink) { + renderArgs.logCollector.warning( + `Couldn't find a static file mapped to ${unresolvedNodeDestination} on ${sourcePath}` + ); + return unresolvedNodeDestination; + } + return resolvedMappedLink; + } else if (maybeLinkTargets && maybeLinkTargets.length) { + if (maybeLinkTargets.length > 1) { + renderArgs.logCollector.warning( + `Multiple possible destinations for ${parsedLink.original} in ${renderArgs.sourcePath}: ${maybeLinkTargets}` + ); + } + return maybeLinkTargets[0].renderDestination(renderArgs); + } else { renderArgs.logCollector.warning( - ` Looked for but did not find a static file at ${possibleStaticFileFSPath}` + `Not sure what to do with link ${unresolvedNodeDestination} in ${renderArgs.sourcePath}` ); + return unresolvedNodeDestination; } - } - return nodeDestination; } + } +} - if (values.length > 1) { - renderArgs.logCollector.warning( - `Multiple possible destinations for ${nodeDestination} in ${renderArgs.sourcePath}: ${values}` - ); +export function maybeAddHash(path_: string, hash: string | null): string { + if (hash) { + return `${path_}#${hash}`; + } else { + return path_; + } +} + +export function resolveDirectLink( + link: DirectLink, + sourceRefPath: string, + inputRoot: string, + linkTargets: Record, + renderArgs: Parameters[0] +): string | null { + const resolvedRelativePath = resolveRelativeRefPath(sourceRefPath, link.path); + for (const k of [ + maybeAddHash(resolvedRelativePath, link.hash), + resolvedRelativePath, + ]) { + const maybeLinkTargets = linkTargets[k]; + if (maybeLinkTargets) { + return maybeLinkTargets[0].renderDestination(renderArgs); } - return values[0].renderDestination(renderArgs); + } + + // Look for a static file + const staticFileRefPath = resolvedRelativePath.slice(1); + const staticFilePathParts = refsplit(staticFileRefPath); + const staticFileFSPath = fsjoin([inputRoot, ...staticFilePathParts]); + renderArgs.logCollector.info( + `Looking for a static file at ${staticFileFSPath} based on ${link.original}` + ); + if ( + fs.existsSync(staticFileFSPath) && + !fs.statSync(staticFileFSPath).isDirectory() + ) { + return renderArgs.renderer.transformLink({ + config: renderArgs.config, + sourcePath: renderArgs.sourcePath, + anchorWithoutHash: link.hash, + docOriginalExtension: path.parse(link.original).ext, + // We can use the destination as-is without modification + docRefPath: staticFileRefPath, + isLinkToStaticFile: true, + logCollector: renderArgs.logCollector, + }); + } else { + return null; } } -export function resolveRelativePath(sourcePath: string, path_: string): string { +export function resolveRelativeRefPath( + sourcePath: string, + path_: string +): string { if (!path_.startsWith("./") && !path_.startsWith("../")) return path_; let pathParts = path_.split("/"); const sourceParts = sourcePath.split("/"); @@ -234,40 +286,43 @@ function isURL(s: string): boolean { } } -function getStaticFileLink(args: { - inputRoot: string; - nodeDestination: string; - prefixlessNodeDestination: string; - anchorWithoutHash: string; - renderArgs: Parameters[0]; -}): null | string { - const { - inputRoot, - nodeDestination, - prefixlessNodeDestination, - anchorWithoutHash, - renderArgs, - } = args; - const possibleStaticFileFSPath = fsjoin([ - inputRoot, - ...urlsplit(prefixlessNodeDestination), - ]); - if (!fs.existsSync(possibleStaticFileFSPath)) { - return null; +interface URLLink { + kind: "url"; + original: string; +} + +interface DirectLink { + kind: "direct"; + original: string; + path: string; + hash: string | null; +} + +interface UnknownLink_MappedOrRelative { + kind: "unknown"; + original: string; + path: string; + hash: string | null; +} + +type ParsedLink = URLLink | DirectLink | UnknownLink_MappedOrRelative; + +function parseLink(original: string): ParsedLink { + if (isURL(original)) { + return { kind: "url", original }; + } + + const path = original.split("#")[0]; + const hash = original.slice(path.length + 1); + + if (path.startsWith(".") || path.startsWith("/")) { + return { kind: "direct", original, path, hash }; + } else { + return { kind: "unknown", original, path, hash }; } - return renderArgs.renderer.transformLink({ - config: renderArgs.config, - sourcePath: renderArgs.sourcePath, - anchorWithoutHash, - docOriginalExtension: path.parse(nodeDestination).ext, - // We can use the destination as-is without modification - docRefPath: prefixlessNodeDestination, - isLinkToStaticFile: true, - logCollector: renderArgs.logCollector, - }); } -export class LinkTarget { +export class MappableLinkTarget { public docOriginalExtension: string; public docRefPath: string; @@ -276,7 +331,7 @@ export class LinkTarget { this.docRefPath = doc.refPath; } - equals(other: LinkTarget) { + equals(other: MappableLinkTarget) { return ( this.docOriginalExtension === other.docOriginalExtension && this.docRefPath == other.docRefPath && @@ -287,7 +342,7 @@ export class LinkTarget { toString(): string { const hash = this.anchorWithoutHash ? `#${this.anchorWithoutHash}` : ""; const aliases = this.aliases.join("\n "); - return `LinkTarget(${this.docRefPath}${this.docOriginalExtension}${hash}) [\n ${aliases}\n]`; + return `MappableLinkTarget(${this.docRefPath}${this.docOriginalExtension}${hash}) [\n ${aliases}\n]`; } /**