md viewer fix
Build and Push Docker Image / build (push) Successful in 13s

This commit is contained in:
2026-04-22 22:39:19 -05:00
parent c86b950a0d
commit 82596a9ac4
2 changed files with 141 additions and 14 deletions
+139
View File
@@ -0,0 +1,139 @@
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import type { Components } from 'react-markdown';
const components: Components = {
// ── Headings ────────────────────────────────────────────────────────────────
h1: ({ children }) => (
<h1 className="text-2xl font-bold text-white mt-8 mb-4 pb-3 border-b border-border first:mt-0">
{children}
</h1>
),
h2: ({ children }) => (
<h2 className="text-lg font-semibold text-white mt-7 mb-3 pb-2 border-b border-border/50 flex items-center gap-2">
<span className="inline-block w-1 h-4 rounded-sm shrink-0" style={{ background: 'var(--accent)' }} />
{children}
</h2>
),
h3: ({ children }) => (
<h3 className="text-base font-semibold text-white mt-5 mb-2">{children}</h3>
),
h4: ({ children }) => (
<h4 className="text-sm font-semibold text-zinc-200 mt-4 mb-1 uppercase tracking-wide">{children}</h4>
),
// ── Paragraph ───────────────────────────────────────────────────────────────
p: ({ children }) => (
<p className="text-zinc-300 leading-7 mb-4 last:mb-0">{children}</p>
),
// ── Links ───────────────────────────────────────────────────────────────────
a: ({ href, children }) => (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2 decoration-[var(--accent)]/50 hover:decoration-[var(--accent)] transition-colors"
style={{ color: 'var(--accent)' }}
>
{children}
</a>
),
// ── Strong / Em ─────────────────────────────────────────────────────────────
strong: ({ children }) => (
<strong className="font-semibold text-white">{children}</strong>
),
em: ({ children }) => (
<em className="italic text-zinc-400">{children}</em>
),
// ── Horizontal rule ─────────────────────────────────────────────────────────
hr: () => <hr className="my-6 border-border" />,
// ── Blockquote ──────────────────────────────────────────────────────────────
blockquote: ({ children }) => (
<blockquote className="my-4 pl-4 border-l-2 text-zinc-400 italic bg-white/[0.02] rounded-r-lg py-3 pr-3" style={{ borderLeftColor: 'var(--accent)' }}>
{children}
</blockquote>
),
// ── Lists ───────────────────────────────────────────────────────────────────
ul: ({ children }) => (
<ul className="my-3 space-y-1.5 list-none pl-4">{children}</ul>
),
ol: ({ children }) => (
<ol className="my-3 space-y-1.5 list-decimal list-inside pl-2 text-zinc-300">{children}</ol>
),
li: ({ children }) => (
<li className="text-zinc-300 leading-relaxed flex gap-2 items-start">
<span className="mt-2.5 w-1.5 h-1.5 rounded-full shrink-0" style={{ background: 'var(--accent)', opacity: 0.7 }} />
<span className="flex-1">{children}</span>
</li>
),
// ── Inline code ─────────────────────────────────────────────────────────────
code: ({ className, children, ...props }) => {
const isBlock = Boolean(className);
if (isBlock) return <code className={className} {...props}>{children}</code>;
return (
<code className="font-mono text-[0.8em] bg-white/10 text-[#e2a4ff] px-1.5 py-0.5 rounded-md border border-white/10">
{children}
</code>
);
},
// ── Code block ──────────────────────────────────────────────────────────────
pre: ({ children }) => (
<pre className="my-4 bg-[#0d0d14] border border-border rounded-xl overflow-x-auto">
<div className="flex items-center justify-between px-4 py-2 border-b border-border/50">
<div className="flex gap-1.5">
<span className="w-3 h-3 rounded-full bg-red-500/40" />
<span className="w-3 h-3 rounded-full bg-yellow-500/40" />
<span className="w-3 h-3 rounded-full bg-green-500/40" />
</div>
</div>
<div className="p-4 text-sm font-mono text-zinc-300 leading-relaxed">
{children}
</div>
</pre>
),
// ── Tables ──────────────────────────────────────────────────────────────────
table: ({ children }) => (
<div className="my-5 overflow-x-auto rounded-xl border border-border">
<table className="w-full text-sm border-collapse">{children}</table>
</div>
),
thead: ({ children }) => (
<thead className="bg-white/[0.04] border-b border-border">{children}</thead>
),
tbody: ({ children }) => (
<tbody className="divide-y divide-border">{children}</tbody>
),
tr: ({ children }) => (
<tr className="transition-colors hover:bg-white/[0.03]">{children}</tr>
),
th: ({ children }) => (
<th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-muted whitespace-nowrap">
{children}
</th>
),
td: ({ children }) => (
<td className="px-4 py-3 text-zinc-300 align-top">{children}</td>
),
};
interface Props {
content: string;
}
export default function MarkdownViewer({ content }: Props) {
return (
<div className="min-w-0">
<ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>
{content}
</ReactMarkdown>
</div>
);
}
+2 -14
View File
@@ -1,7 +1,6 @@
import { useState, useEffect, useRef } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import MarkdownViewer from '../components/ui/MarkdownViewer';
import {
ArrowLeft, ExternalLink, Pencil, Trash2, Upload, FileText,
X, Save, FolderOpen, Eye, Code2
@@ -244,18 +243,7 @@ export default function ProjectDetail() {
</div>
<div className="p-6 overflow-auto max-h-[70vh]">
{docViewMode === 'preview' ? (
<div className="prose prose-invert prose-sm max-w-none
prose-headings:text-white prose-headings:font-semibold
prose-p:text-zinc-300 prose-p:leading-relaxed
prose-a:text-[var(--accent)] prose-a:no-underline hover:prose-a:underline
prose-code:bg-white/10 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono
prose-pre:bg-surface prose-pre:border prose-pre:border-border
prose-blockquote:border-l-[var(--accent)] prose-blockquote:text-muted
prose-li:text-zinc-300 prose-strong:text-white
prose-table:text-sm prose-th:text-muted prose-td:text-zinc-300
prose-hr:border-border">
<ReactMarkdown remarkPlugins={[remarkGfm]}>{docContent}</ReactMarkdown>
</div>
<MarkdownViewer content={docContent} />
) : (
<pre className="text-xs text-zinc-300 font-mono whitespace-pre-wrap">{docContent}</pre>
)}