Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More control delegated for external link resolvers #2066

Merged
merged 13 commits into from Feb 24, 2023
2 changes: 2 additions & 0 deletions src/index.ts
Expand Up @@ -13,6 +13,8 @@ export {
type ComponentPath,
type Meaning,
type MeaningKeyword,
type ExternalResolveAttempt,
type ExternalResolveResult,
captain-torch marked this conversation as resolved.
Show resolved Hide resolved
} from "./lib/converter";

export {
Expand Down
35 changes: 28 additions & 7 deletions src/lib/converter/comments/linkResolver.ts
Expand Up @@ -16,12 +16,19 @@ import { resolveDeclarationReference } from "./declarationReferenceResolver";
const urlPrefix = /^(http|ftp)s?:\/\//;
const brackets = /\[\[(?!include:)([^\]]+)\]\]/g;

export type ExternalResolveResult = { target: string; caption: string };
export type ExternalResolveAttempt = (
ref: DeclarationReference,
part: CommentDisplayPart,
refl: Reflection
) => ExternalResolveResult | string | undefined;

export function resolveLinks(
comment: Comment,
reflection: Reflection,
validation: ValidationOptions,
logger: Logger,
attemptExternalResolve: (ref: DeclarationReference) => string | undefined
attemptExternalResolve: ExternalResolveAttempt
) {
let warned = false;
const warn = () => {
Expand Down Expand Up @@ -70,7 +77,7 @@ export function resolvePartLinks(
warn: () => void,
validation: ValidationOptions,
logger: Logger,
attemptExternalResolve: (ref: DeclarationReference) => string | undefined
attemptExternalResolve: ExternalResolveAttempt
): CommentDisplayPart[] {
return parts.flatMap((part) =>
processPart(
Expand All @@ -90,7 +97,7 @@ function processPart(
warn: () => void,
validation: ValidationOptions,
logger: Logger,
attemptExternalResolve: (ref: DeclarationReference) => string | undefined
attemptExternalResolve: ExternalResolveAttempt
): CommentDisplayPart | CommentDisplayPart[] {
if (part.kind === "text" && brackets.test(part.text)) {
warn();
Expand Down Expand Up @@ -122,7 +129,7 @@ function processPart(
function resolveLinkTag(
reflection: Reflection,
part: InlineTagDisplayPart,
attemptExternalResolve: (ref: DeclarationReference) => string | undefined,
attemptExternalResolve: ExternalResolveAttempt,
warn: (message: string) => void
) {
let pos = 0;
Expand All @@ -146,9 +153,23 @@ function resolveLinkTag(
defaultDisplayText = target.name;
} else {
// If we didn't find a link, it might be a @link tag to an external symbol, check that next.
target = attemptExternalResolve(declRef[0]);
if (target) {
defaultDisplayText = part.text.substring(0, pos);
let externalResolveResult = attemptExternalResolve(
declRef[0],
part,
reflection
);

switch (typeof externalResolveResult) {
case "string":
target = externalResolveResult as string;
defaultDisplayText = part.text.substring(0, pos);
break;
case "object":
externalResolveResult =
externalResolveResult as ExternalResolveResult;
part.target = externalResolveResult.target;
part.text = externalResolveResult.caption;
return part;
captain-torch marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
18 changes: 13 additions & 5 deletions src/lib/converter/converter.ts
Expand Up @@ -78,7 +78,11 @@ export class Converter extends ChildableComponent<

private _config?: CommentParserConfig;
private _externalSymbolResolvers: Array<
(ref: DeclarationReference) => string | undefined
(
ref: DeclarationReference,
part?: CommentDisplayPart,
refl?: Reflection
) => string | undefined
> = [];

get config(): CommentParserConfig {
Expand Down Expand Up @@ -274,9 +278,13 @@ export class Converter extends ChildableComponent<
}

/** @internal */
resolveExternalLink(ref: DeclarationReference): string | undefined {
resolveExternalLink(
Gerrit0 marked this conversation as resolved.
Show resolved Hide resolved
ref: DeclarationReference,
part?: CommentDisplayPart,
refl?: Reflection
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these be non-optional, given your changes the array type above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was made optional because of usage of this function in LinkResolverPlugin (line 53). I didn't catch the purpose of using this function there, and for safety decided to change resolveExternalLink signature in order to avoid modifying of this code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is for links to types declared outside of the project, e.g.:

import { Bar } from "external-lib"
export function foo(bar: Bar) {}

): string | undefined {
for (const resolver of this._externalSymbolResolvers) {
const resolved = resolver(ref);
const resolved = resolver(ref, part, refl);
if (resolved) return resolved;
}
}
Expand All @@ -296,7 +304,7 @@ export class Converter extends ChildableComponent<
owner,
this.validation,
this.owner.logger,
(ref) => this.resolveExternalLink(ref)
(ref, part, refl) => this.resolveExternalLink(ref, part, refl)
);
} else {
let warned = false;
Expand All @@ -315,7 +323,7 @@ export class Converter extends ChildableComponent<
warn,
this.validation,
this.owner.logger,
(ref) => this.resolveExternalLink(ref)
(ref, part, refl) => this.resolveExternalLink(ref, part, refl)
);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/converter/index.ts
Expand Up @@ -9,5 +9,9 @@ export type {
Meaning,
MeaningKeyword,
} from "./comments/declarationReference";
export type {
ExternalResolveAttempt,
ExternalResolveResult,
} from "./comments/linkResolver";

import "./plugins/index";