Skip to content

Commit 37778f1

Browse files
authored
Add components for cves, gh issues, and python downloadss (#26)
1 parent acb38be commit 37778f1

File tree

3 files changed

+121
-1
lines changed

3 files changed

+121
-1
lines changed

src/assets/styles/global.css

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,84 @@ body {
14371437
border-color: rgba(160, 160, 170, 0.32);
14381438
}
14391439

1440+
/* ── GitHub issue/PR — Green ────────────────────────── */
1441+
1442+
.prose .ref-gh-issue {
1443+
color: #1a6d2e;
1444+
background-color: rgba(34, 140, 60, 0.08);
1445+
border-color: rgba(34, 140, 60, 0.2);
1446+
}
1447+
1448+
.prose .ref-gh-issue:hover {
1449+
color: #145524;
1450+
background-color: rgba(34, 140, 60, 0.14);
1451+
border-color: rgba(34, 140, 60, 0.35);
1452+
}
1453+
1454+
.dark .prose .ref-gh-issue {
1455+
color: #6ddb8a;
1456+
background-color: rgba(50, 180, 80, 0.12);
1457+
border-color: rgba(50, 180, 80, 0.25);
1458+
}
1459+
1460+
.dark .prose .ref-gh-issue:hover {
1461+
color: #8de8a4;
1462+
background-color: rgba(50, 180, 80, 0.2);
1463+
border-color: rgba(50, 180, 80, 0.4);
1464+
}
1465+
1466+
/* ── CVE — Red/rose ────────────────────────────────── */
1467+
1468+
.prose .ref-cve {
1469+
color: #9f1239;
1470+
background-color: rgba(190, 30, 70, 0.07);
1471+
border-color: rgba(190, 30, 70, 0.18);
1472+
}
1473+
1474+
.prose .ref-cve:hover {
1475+
color: #7f0f2e;
1476+
background-color: rgba(190, 30, 70, 0.13);
1477+
border-color: rgba(190, 30, 70, 0.32);
1478+
}
1479+
1480+
.dark .prose .ref-cve {
1481+
color: #f0758e;
1482+
background-color: rgba(220, 60, 90, 0.12);
1483+
border-color: rgba(220, 60, 90, 0.25);
1484+
}
1485+
1486+
.dark .prose .ref-cve:hover {
1487+
color: #f5a0b2;
1488+
background-color: rgba(220, 60, 90, 0.2);
1489+
border-color: rgba(220, 60, 90, 0.4);
1490+
}
1491+
1492+
/* ── Python release — Python blue (distinct) ────────── */
1493+
1494+
.prose .ref-py-release {
1495+
color: #1a5276;
1496+
background-color: rgba(30, 100, 160, 0.08);
1497+
border-color: rgba(30, 100, 160, 0.2);
1498+
}
1499+
1500+
.prose .ref-py-release:hover {
1501+
color: #144060;
1502+
background-color: rgba(30, 100, 160, 0.14);
1503+
border-color: rgba(30, 100, 160, 0.35);
1504+
}
1505+
1506+
.dark .prose .ref-py-release {
1507+
color: #68b5e8;
1508+
background-color: rgba(50, 130, 200, 0.12);
1509+
border-color: rgba(50, 130, 200, 0.25);
1510+
}
1511+
1512+
.dark .prose .ref-py-release:hover {
1513+
color: #90caf0;
1514+
background-color: rgba(50, 130, 200, 0.2);
1515+
border-color: rgba(50, 130, 200, 0.4);
1516+
}
1517+
14401518
/* ── Post footer references panel ── */
14411519

14421520
.post-refs-header {

src/components/references/_icons.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,27 @@ export const docsIcon = lucide(
3333
'<path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/>',
3434
);
3535

36+
/** Lucide `circle-dot` — GitHub issue/PR */
37+
export const issueIcon = lucide(
38+
14,
39+
14,
40+
'<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="1"/>',
41+
);
42+
43+
/** Lucide `shield-alert` — CVE / security vulnerability */
44+
export const shieldIcon = lucide(
45+
14,
46+
14,
47+
'<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/>',
48+
);
49+
50+
/** Lucide `download` — Python release download */
51+
export const downloadIcon = lucide(
52+
14,
53+
14,
54+
'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/>',
55+
);
56+
3657
/** Lucide `arrow-up-right` — external link indicator */
3758
export const externalIcon = lucide(
3859
11,

src/plugins/remark-python-refs.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
* - PEP links (by URL pattern OR link text matching "PEP NNN")
99
* - CPython docs (docs.python.org/...)
1010
* - PyPI links (pypi.org/project/NAME/)
11+
* - GitHub issues/PRs (github.com/OWNER/REPO/issues|pull/NNN)
1112
* - GitHub repos (github.com/OWNER/REPO — exactly 2 path segments)
1213
* - GitHub users/orgs (github.com/NAME — exactly 1 segment, not reserved)
14+
* - CVE references (nvd.nist.gov/vuln/detail/CVE-YYYY-NNNNN)
15+
* - Python releases (python.org/downloads/release/python-XXXX/)
1316
*/
1417
import type { Root, Link, Paragraph, PhrasingContent } from "mdast";
1518
import { visit } from "unist-util-visit";
@@ -18,6 +21,9 @@ import {
1821
docsIcon,
1922
githubIcon,
2023
packageIcon,
24+
issueIcon,
25+
shieldIcon,
26+
downloadIcon,
2127
externalIcon,
2228
} from "../components/references/_icons.js";
2329

@@ -27,6 +33,9 @@ const PEP_OLD = /^https?:\/\/(?:www\.)?python\.org\/dev\/peps\/pep-(\d+)\/?/i;
2733
const PEP_NEW = /^https?:\/\/peps\.python\.org\/pep-(\d+)\/?/i;
2834
const DOCS = /^https?:\/\/docs\.python\.org\//i;
2935
const PYPI = /^https?:\/\/pypi\.org\/project\/([^/]+)\/?/i;
36+
const GH_ISSUE = /^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/(issues|pull)\/(\d+)\/?/i;
37+
const CVE = /^https?:\/\/nvd\.nist\.gov\/vuln\/detail\/(CVE-[\d-]+)\/?/i;
38+
const PY_RELEASE = /^https?:\/\/(?:www\.)?python\.org\/downloads\/release\/(python-[\w.]+)\/?/i;
3039
const GITHUB =
3140
/^https?:\/\/github\.com\/([\w.-]+)(?:\/([\w.-]+))?\/?$/i;
3241

@@ -64,7 +73,7 @@ const GH_RESERVED = new Set([
6473

6574
// ── Helpers ─────────────────────────────────────────────
6675

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

6978
interface Match {
7079
type: RefType;
@@ -108,6 +117,18 @@ function classify(url: string, linkText?: string): Omit<Match, "label" | "url">
108117
return { type: "pypi", icon: packageIcon };
109118
}
110119

120+
if ((m = url.match(GH_ISSUE))) {
121+
return { type: "gh-issue", icon: issueIcon };
122+
}
123+
124+
if ((m = url.match(CVE))) {
125+
return { type: "cve", icon: shieldIcon };
126+
}
127+
128+
if ((m = url.match(PY_RELEASE))) {
129+
return { type: "py-release", icon: downloadIcon };
130+
}
131+
111132
if ((m = url.match(GITHUB))) {
112133
const [, owner, repo] = m;
113134
if (repo) {

0 commit comments

Comments
 (0)