Skip to content

Commit

Permalink
Expose displayPartsToMarkdown
Browse files Browse the repository at this point in the history
Closes #2115
  • Loading branch information
Gerrit0 committed Feb 26, 2023
1 parent 37fe883 commit 54c86d8
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 51 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@

- Added `Application.EVENT_VALIDATE_PROJECT` event for plugins which implement custom validation, #2183.
- Plugins may now return an object from external symbol resolvers, #2066.
- Expose `Comment.displayPartsToMarkdown` on for themes overwriting the `comment` helper, #2115.

### Bug Fixes

Expand Down
59 changes: 59 additions & 0 deletions src/lib/models/comments/comment.ts
Expand Up @@ -121,6 +121,65 @@ export class Comment {
return result;
}

/**
* Helper function to convert an array of comment display parts into markdown suitable for
* passing into Marked. `urlTo` will be used to resolve urls to any reflections linked to with
* `@link` tags.
*/
static displayPartsToMarkdown(
parts: readonly CommentDisplayPart[],
urlTo: (ref: Reflection) => string
) {
const result: string[] = [];

for (const part of parts) {
switch (part.kind) {
case "text":
case "code":
result.push(part.text);
break;
case "inline-tag":
switch (part.tag) {
case "@label":
case "@inheritdoc": // Shouldn't happen
break; // Not rendered.
case "@link":
case "@linkcode":
case "@linkplain": {
if (part.target) {
const url =
typeof part.target === "string"
? part.target
: urlTo(part.target);
const text =
part.tag === "@linkcode"
? `<code>${part.text}</code>`
: part.text;
result.push(
url
? `<a href="${url}">${text}</a>`
: part.text
);
} else {
result.push(part.text);
}
break;
}
default:
// Hmm... probably want to be able to render these somehow, so custom inline tags can be given
// special rendering rules. Future capability. For now, just render their text.
result.push(`{${part.tag} ${part.text}}`);
break;
}
break;
default:
assertNever(part);
}
}

return result.join("");
}

/**
* Helper utility to clone {@link Comment.summary} or {@link CommentTag.content}
*/
Expand Down
8 changes: 4 additions & 4 deletions src/lib/output/themes/default/DefaultThemeRenderContext.ts
@@ -1,11 +1,11 @@
import type { RendererHooks } from "../..";
import type {
import {
Comment,
CommentDisplayPart,
ReferenceType,
Reflection,
} from "../../../models";
import type { NeverIfInternal, Options } from "../../../utils";
import { displayPartsToMarkdown } from "../lib";
import type { DefaultTheme } from "./DefaultTheme";
import { defaultLayout } from "./layouts/default";
import { index } from "./partials";
Expand Down Expand Up @@ -62,14 +62,14 @@ export class DefaultThemeRenderContext {
return url ? this.theme.markedPlugin.getRelativeUrl(url) : url;
};

urlTo = (reflection: Reflection) => this.relativeURL(reflection.url);
urlTo = (reflection: Reflection) => this.relativeURL(reflection.url)!;

markdown = (
md: readonly CommentDisplayPart[] | NeverIfInternal<string | undefined>
) => {
if (md instanceof Array) {
return this.theme.markedPlugin.parseMarkdown(
displayPartsToMarkdown(md, this.urlTo)
Comment.displayPartsToMarkdown(md, this.urlTo)
);
}
return md ? this.theme.markedPlugin.parseMarkdown(md) : "";
Expand Down
48 changes: 1 addition & 47 deletions src/lib/output/themes/lib.tsx
@@ -1,14 +1,12 @@
import {
Comment,
CommentDisplayPart,
DeclarationReflection,
Reflection,
ReflectionFlags,
SignatureReflection,
TypeParameterReflection,
} from "../../models";
import { assertNever, JSX } from "../../utils";
import type { DefaultThemeRenderContext } from "./default/DefaultThemeRenderContext";
import { JSX } from "../../utils";

export function stringify(data: unknown) {
if (typeof data === "bigint") {
Expand Down Expand Up @@ -117,50 +115,6 @@ export function camelToTitleCase(text: string) {
return text.substring(0, 1).toUpperCase() + text.substring(1).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`);
}

export function displayPartsToMarkdown(
parts: readonly CommentDisplayPart[],
urlTo: DefaultThemeRenderContext["urlTo"]
) {
const result: string[] = [];

for (const part of parts) {
switch (part.kind) {
case "text":
case "code":
result.push(part.text);
break;
case "inline-tag":
switch (part.tag) {
case "@label":
case "@inheritdoc": // Shouldn't happen
break; // Not rendered.
case "@link":
case "@linkcode":
case "@linkplain": {
if (part.target) {
const url = typeof part.target === "string" ? part.target : urlTo(part.target);
const text = part.tag === "@linkcode" ? `<code>${part.text}</code>` : part.text;
result.push(url ? `<a href="${url}">${text}</a>` : part.text);
} else {
result.push(part.text);
}
break;
}
default:
// Hmm... probably want to be able to render these somehow, so custom inline tags can be given
// special rendering rules. Future capability. For now, just render their text.
result.push(`{${part.tag} ${part.text}}`);
break;
}
break;
default:
assertNever(part);
}
}

return result.join("");
}

/**
* Renders the reflection name with an additional `?` if optional.
*/
Expand Down

0 comments on commit 54c86d8

Please sign in to comment.