|
1 | | -import { useState, useRef, useEffect, useMemo } from "react"; |
2 | | -import Asciidoctor from "@asciidoctor/core"; |
| 1 | +import { useState } from "react"; |
3 | 2 | import T from "./i18n.js"; |
4 | 3 | import { useTheme } from "./theme.js"; |
5 | 4 | import { VERSION, TIER_BG, TYPE_COLORS } from "./constants.js"; |
6 | 5 | import { getTierIndex, detectBrowserLanguage } from "./utils.js"; |
7 | 6 | import RadarChart from "./components/RadarChart.jsx"; |
8 | 7 | import MitigationCard from "./components/MitigationCard.jsx"; |
9 | | - |
10 | | -const adoc = Asciidoctor(); |
11 | | - |
12 | | -const ADOC_SIDEBAR_STYLES = ` |
13 | | - .adoc-content p { margin: 0.5em 0; } |
14 | | - .adoc-content a { color: var(--link); text-decoration: underline; text-decoration-color: var(--link-underline); } |
15 | | - .adoc-content a:hover { text-decoration-color: var(--link); } |
16 | | - .adoc-content strong { color: var(--text-primary); } |
17 | | - .adoc-content code { background: var(--bg-card); padding: 1px 4px; border-radius: 3px; font-size: 0.92em; } |
18 | | -`; |
19 | | - |
20 | | -function DocSidebar({ docs, open, onClose }) { |
21 | | - const ref = useRef(null); |
22 | | - useEffect(() => { if (open && ref.current) ref.current.scrollTop = 0; }, [open]); |
23 | | - useEffect(() => { |
24 | | - if (open && ref.current) { |
25 | | - ref.current.querySelectorAll(".adoc-content a").forEach((a) => { |
26 | | - a.setAttribute("target", "_blank"); |
27 | | - a.setAttribute("rel", "noopener"); |
28 | | - }); |
29 | | - } |
30 | | - }); |
31 | | - |
32 | | - const rendered = useMemo(() => |
33 | | - docs.sections.map((sec) => ({ |
34 | | - ...sec, |
35 | | - html: adoc.convert(sec.content, { safe: "safe", attributes: { showtitle: false } }), |
36 | | - })), |
37 | | - [docs.sections] |
38 | | - ); |
39 | | - |
40 | | - return ( |
41 | | - <div |
42 | | - ref={ref} |
43 | | - style={{ |
44 | | - position: "fixed", top: 0, right: 0, bottom: 0, |
45 | | - width: open ? "min(480px, 85vw)" : "0", |
46 | | - background: "var(--bg-sidebar)", borderLeft: open ? "1px solid var(--border)" : "none", |
47 | | - overflowY: "auto", overflowX: "hidden", |
48 | | - transition: "width 0.3s ease", |
49 | | - zIndex: 1000, |
50 | | - boxShadow: open ? "-8px 0 30px var(--shadow)" : "none", |
51 | | - }} |
52 | | - > |
53 | | - {open && ( |
54 | | - <div style={{ padding: "24px 20px" }}> |
55 | | - <style>{ADOC_SIDEBAR_STYLES}</style> |
56 | | - <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24 }}> |
57 | | - <h2 style={{ margin: 0, fontSize: 24, fontWeight: 700, color: "var(--text-heading)" }}>{docs.title}</h2> |
58 | | - <button onClick={onClose} style={{ background: "var(--bg-card)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text-secondary)", padding: "6px 12px", cursor: "pointer", fontSize: 16 }}>✕</button> |
59 | | - </div> |
60 | | - {rendered.map((sec) => ( |
61 | | - <div key={sec.id} style={{ |
62 | | - marginBottom: 28, |
63 | | - ...(sec.id === "disclaimer" ? { background: "var(--bg-card)", borderRadius: 10, padding: "14px 16px", border: "1px solid var(--border)" } : {}), |
64 | | - }}> |
65 | | - <h3 style={{ fontSize: 20, fontWeight: 700, color: sec.id === "disclaimer" ? "#f59e0b" : "var(--text-primary)", margin: "0 0 10px", paddingBottom: 6, borderBottom: sec.id === "disclaimer" ? "none" : "1px solid var(--border-subtle)" }}> |
66 | | - {sec.id === "disclaimer" ? "\u26A0\uFE0F " : ""}{sec.title} |
67 | | - </h3> |
68 | | - <div |
69 | | - className="adoc-content" |
70 | | - style={{ fontSize: 18, color: "var(--text-secondary)", lineHeight: 1.7 }} |
71 | | - dangerouslySetInnerHTML={{ __html: sec.html }} |
72 | | - /> |
73 | | - </div> |
74 | | - ))} |
75 | | - <div style={{ borderTop: "1px solid var(--border-subtle)", paddingTop: 16, marginTop: 8, fontSize: 15, color: "var(--text-secondary)", textAlign: "center" }}> |
76 | | - Generated with data from Veracode, CodeRabbit, BaxBench, Unit 42, Aikido Security, CSA, and others. |
77 | | - </div> |
78 | | - </div> |
79 | | - )} |
80 | | - </div> |
81 | | - ); |
82 | | -} |
| 8 | +import DocSidebar from "./components/DocSidebar.jsx"; |
83 | 9 |
|
84 | 10 | export default function RiskRadar() { |
85 | 11 | const [lang, setLang] = useState(() => { |
|
0 commit comments