[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/python/python-insider-blog/main/src/plugins/remark-python-refs.ts [Back]  [Original]

/**
 * remark-python-refs
 *
 * A remark plugin that detects Python ecosystem URLs in Markdown links
 * and transforms them into styled inline badges.
 *
 * Detected patterns:
 *   - PEP links  (by URL pattern OR link text matching "PEP NNN")
 *   - CPython docs (docs.python.org/...)
 *   - PyPI links (pypi.org/project/NAME/)
 *   - GitHub issues/PRs (github.com/OWNER/REPO/issues|pull/NNN)
 *   - GitHub repos (github.com/OWNER/REPO  exactly 2 path segments)
 *   - GitHub users/orgs (github.com/NAME  exactly 1 segment, not reserved)
 *   - CVE references (nvd.nist.gov/vuln/detail/CVE-YYYY-NNNNN)
 *   - Python releases (python.org/downloads/release/python-XXXX/)
 */
import type { Root, Link, Paragraph, PhrasingContent } from "mdast";
import { visit } from "unist-util-visit";
import {
  pythonIcon,
  docsIcon,
  githubIcon,
  packageIcon,
  issueIcon,
  shieldIcon,
  downloadIcon,
  externalIcon,
} from "../components/references/_icons.js";

//  URL matchers 

const PEP_OLD = /^https?:\/\/(?:www\.)?python\.org\/dev\/peps\/pep-(\d+)\/?/i;
const PEP_NEW = /^https?:\/\/peps\.python\.org\/pep-(\d+)\/?/i;
const DOCS = /^https?:\/\/docs\.python\.org\//i;
const PYPI = /^https?:\/\/pypi\.org\/project\/([^/]+)\/?/i;
const GH_ISSUE = /^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/(issues|pull)\/(\d+)\/?/i;
const CVE = /^https?:\/\/nvd\.nist\.gov\/vuln\/detail\/(CVE-[\d-]+)\/?/i;
const PY_RELEASE = /^https?:\/\/(?:www\.)?python\.org\/downloads\/release\/(python-[\w.]+)\/?/i;
const GITHUB =
  /^https?:\/\/github\.com\/([\w.-]+)(?:\/([\w.-]+))?\/?$/i;

/** GitHub top-level paths that are NOT user/org profiles */
const GH_RESERVED = new Set([
  "about",
  "collections",
  "contact",
  "customer-stories",
  "enterprise",
  "events",
  "explore",
  "features",
  "issues",
  "login",
  "marketplace",
  "new",
  "nonprofit",
  "notifications",
  "open-source",
  "organizations",
  "orgs",
  "pricing",
  "pulls",
  "readme",
  "search",
  "security",
  "settings",
  "site",
  "sponsors",
  "team",
  "topics",
  "trending",
]);

//  Helpers 

type RefType = "pep" | "docs" | "pypi" | "gh-repo" | "gh-user" | "gh-issue" | "cve" | "py-release";

interface Match {
  type: RefType;
  icon: string;
  label: string; // author's original link text  preserved
  url: string;
}

function extractText(children: PhrasingContent[]): string {
  return children
    .map((c) => {
      if (c.type === "text" || c.type === "inlineCode") return c.value;
      if ("children" in c) return extractText(c.children as PhrasingContent[]);
      return "";
    })
    .join("");
}

/** Match by link text  catches "PEP 649", "PEP 649," etc. */
const PEP_TEXT = /^PEP\s+\d+$/i;

function classify(url: string, linkText?: string): Omit | null {
  let m: RegExpMatchArray | null;

  // URL-based PEP detection
  if ((m = url.match(PEP_OLD)) || (m = url.match(PEP_NEW))) {
    return { type: "pep", icon: pythonIcon };
  }

  // Text-based PEP detection  catches links like [PEP 799](https://docs.python.org/...)
  if (linkText && PEP_TEXT.test(linkText.trim())) {
    return { type: "pep", icon: pythonIcon };
  }

  // CPython docs  checked after PEP text so [PEP NNN](docs.python.org/...) stays a PEP badge
  if (DOCS.test(url)) {
    return { type: "docs", icon: docsIcon };
  }

  if ((m = url.match(PYPI))) {
    return { type: "pypi", icon: packageIcon };
  }

  if ((m = url.match(GH_ISSUE))) {
    return { type: "gh-issue", icon: issueIcon };
  }

  if ((m = url.match(CVE))) {
    return { type: "cve", icon: shieldIcon };
  }

  if ((m = url.match(PY_RELEASE))) {
    return { type: "py-release", icon: downloadIcon };
  }

  if ((m = url.match(GITHUB))) {
    const [, owner, repo] = m;
    if (repo) {
      return { type: "gh-repo", icon: githubIcon };
    }
    if (!GH_RESERVED.has(owner.toLowerCase())) {
      return { type: "gh-user", icon: githubIcon };
    }
  }

  return null;
}

function buildBadgeHtml(match: Match): string {
  const cls = `ref-badge ref-${match.type}`;
  // Escape HTML in label
  const safeLabel = match.label
    .replace(/&/g, "&")
    .replace(//g, ">")
    .replace(/"/g, """);
  return (
    `` +
    `${match.icon}` +
    `${safeLabel}` +
    `${externalIcon}` +
    ``
  );
}

//  Markdoc tag handling 
// Keystatic serializes inline components as Markdoc tags:
//   {% Pep number=649 /%}  or  {% Pep number=649 %}PEP 649{% /Pep %}

const MARKDOC_TAG =
  /\{%\s*(Pep|Docs|PyPi|GhRepo|GhUser)\s+([\s\S]*?)\s*(?:\/%\}|%\}[\s\S]*?\{%\s*\/\1\s*%\})/g;

const ATTR_RE = /(\w+)=(?:"([^"]*?)"|(\S+))/g;

function parseAttrs(str: string): Record {
  const attrs: Record = {};
  let m: RegExpExecArray | null;
  while ((m = ATTR_RE.exec(str)) !== null) {
    attrs[m[1]] = m[2] ?? m[3];
  }
  ATTR_RE.lastIndex = 0;
  return attrs;
}

function markdocTagToBadge(tag: string, attrs: Record): string | null {
  switch (tag) {
    case "Pep": {
      const num = attrs.number;
      if (!num) return null;
      const padded = String(num).padStart(4, "0");
      return buildBadgeHtml({
        type: "pep",
        icon: pythonIcon,
        label: `PEP ${num}`,
        url: `https://peps.python.org/pep-${padded}/`,
      });
    }
    case "Docs": {
      const path = attrs.path;
      if (!path) return null;
      const label = attrs.label ?? path.replace(/^\//, "").replace(/\.html$/, "").split("/").pop()!;
      return buildBadgeHtml({
        type: "docs",
        icon: docsIcon,
        label,
        url: `https://docs.python.org/${path.replace(/^\//, "")}`,
      });
    }
    case "PyPi": {
      const name = attrs.name;
      if (!name) return null;
      return buildBadgeHtml({
        type: "pypi",
        icon: packageIcon,
        label: name,
        url: `https://pypi.org/project/${name}/`,
      });
    }
    case "GhRepo": {
      const repo = attrs.repo;
      if (!repo) return null;
      return buildBadgeHtml({
        type: "gh-repo",
        icon: githubIcon,
        label: repo.split("/").pop()!,
        url: `https://github.com/${repo}`,
      });
    }
    case "GhUser": {
      const name = attrs.name;
      if (!name) return null;
      return buildBadgeHtml({
        type: "gh-user",
        icon: githubIcon,
        label: `@${name}`,
        url: `https://github.com/${name}`,
      });
    }
    default:
      return null;
  }
}

/** Split a text value on Markdoc tags, returning text + html nodes. */
function splitMarkdocTags(value: string): Array {
  const parts: Array = [];
  let lastIndex = 0;

  MARKDOC_TAG.lastIndex = 0;
  let m: RegExpExecArray | null;
  while ((m = MARKDOC_TAG.exec(value)) !== null) {
    if (m.index > lastIndex) {
      parts.push({ type: "text", value: value.slice(lastIndex, m.index) });
    }
    const html = markdocTagToBadge(m[1], parseAttrs(m[2]));
    if (html) {
      parts.push({ type: "html", value: html });
    } else {
      parts.push({ type: "text", value: m[0] });
    }
    lastIndex = m.index + m[0].length;
  }

  if (lastIndex < value.length) {
    parts.push({ type: "text", value: value.slice(lastIndex) });
  }

  return parts;
}

//  Plugin 

export default function remarkPythonRefs() {
  return (tree: Root, file: any) => {
    // Collect unique references for the post footer
    const seen = new Set();
    const refs: Array = [];

    function collectRef(type: RefType, label: string, url: string) {
      const key = `${type}:${url}`;
      if (!seen.has(key)) {
        seen.add(key);
        refs.push({ type, label, url });
      }
    }

    // Pass 1: Transform matching links  badges
    visit(tree, "link", (node: Link, index, parent) => {
      if (index == null || !parent) return;

      const rawLabel = extractText(node.children);
      const info = classify(node.url, rawLabel);
      if (!info) return;

      // For autolinked bare URLs, drop the protocol, leading "www.",
      // and trailing slash so the badge reads "python.org/downloads/..."
      // rather than the full "https://www.python.org/.../" form.
      const label = rawLabel.startsWith("http")
        ? rawLabel.replace(/^https?:\/\/(?:www\.)?/i, "").replace(/\/$/, "")
        : rawLabel;

      collectRef(info.type, label, node.url);
      const html = buildBadgeHtml({ ...info, label, url: node.url });

      // Replace the link node with a raw HTML node
      (parent.children as any)[index] = {
        type: "html",
        value: html,
      };
    });

    // Pass 2: Transform Markdoc inline tags (from Keystatic)  badges
    visit(tree, "paragraph", (node: Paragraph) => {
      let changed = false;
      const newChildren: PhrasingContent[] = [];

      for (const child of node.children) {
        if (child.type !== "text" || !MARKDOC_TAG.test(child.value)) {
          MARKDOC_TAG.lastIndex = 0;
          newChildren.push(child);
          continue;
        }

        MARKDOC_TAG.lastIndex = 0;
        changed = true;
        const parts = splitMarkdocTags(child.value);
        for (const part of parts) {
          newChildren.push(part as any);
        }
      }

      if (changed) {
        node.children = newChildren;
      }
    });

    // Expose collected references via remarkPluginFrontmatter
    if (!file.data.astro) file.data.astro = {};
    if (!file.data.astro.frontmatter) file.data.astro.frontmatter = {};
    file.data.astro.frontmatter.references = refs;
  };
}

Web Proxy Viewer  |  New URL  |  Original Page