linkExtension

tcmts.site.linkExtension · #o3crtvcw · function · runs anywhere

A definition in a page, by name, as a doc comment links to one (@link, or @linkcode, with its own text after the name or not): tcm checked it when the page was saved, and it follows renames. Shown as its name (or its text), and linked to its page in the code browser, href(name), when there is one: that isn't the docs app's (rel="external"). Not in code, where it's written to be read as it is.

import { esc } from "#codebase/tcmts/site";
import type { TokenizerAndRendererExtension } from "marked";

export function linkExtension(
  href: (name: string) => string | undefined,
): TokenizerAndRendererExtension {
  return {
    name: "tcmLink",
    level: "inline",
    start: (src: string) => src.indexOf("{@link"),
    tokenizer(src: string) {
      const m = /^\{@link(code|plain)?\s+([\w$.-]+)(?:\s*\|\s*|\s+)?([^}]*)\}/.exec(src);
      return m
        ? {
            type: "tcmLink",
            raw: m[0],
            code: m[1] === "code",
            name: m[2]!,
            label: m[3]!.trim(),
          }
        : undefined;
    },
    renderer(token) {
      const { code, name, label } = token as unknown as {
        code: boolean;
        name: string;
        label: string;
      };
      const shown = label ? esc(label) : esc(name.slice(name.lastIndexOf(".") + 1));
      const inner = code || !label ? `<code>${shown}</code>` : shown;
      const to = href(name);
      if (to === undefined) return inner;
      return `<a href="${esc(to)}" rel="external" title="${esc(name)}">${inner}</a>`;
    },
  };
}

uses

used by