Complete GFM support: tables, task lists, strikethrough

Editor: add tablePlugin so markdown tables round-trip and render. Task
lists (`- [ ]`), strikethrough, code (inline + fenced), headings, lists,
quotes, and links already work via listsPlugin/core/markdownShortcut. CSS:
suppress the disc bullet on task-list items (they draw their own checkbox)
and style tables.

Display: render task-list checkboxes (no stray bullet), GFM tables, and
strikethrough so the read view matches what the editor produces.

https://claude.ai/code/session_019DU6V5z6Nr4Vu7b1fBDnq4
This commit is contained in:
Claude
2026-05-29 19:35:34 +00:00
parent 273916d7a7
commit 0e0ca86073
3 changed files with 69 additions and 2 deletions
@@ -108,6 +108,10 @@
margin-bottom: 0.25rem;
line-height: 1.625;
}
/* Task-list items draw their own checkbox — no disc bullet. */
.llink-mdx-content li[class*="_listItem"] {
list-style: none;
}
/* Blockquote */
.llink-mdx-content blockquote {
@@ -132,3 +136,20 @@
border: none;
border-top: 1px solid rgb(255 255 255 / 0.1);
}
/* Tables */
.llink-mdx-content table {
margin-bottom: 0.75rem;
border-collapse: collapse;
width: auto;
}
.llink-mdx-content th,
.llink-mdx-content td {
border: 1px solid rgb(255 255 255 / 0.2);
padding: 0.375rem 0.625rem;
text-align: left;
}
.llink-mdx-content th {
background: rgb(255 255 255 / 0.08);
font-weight: 600;
}
@@ -9,6 +9,7 @@ import {
linkPlugin,
codeBlockPlugin,
codeMirrorPlugin,
tablePlugin,
markdownShortcutPlugin,
} from "@mdxeditor/editor";
import "@mdxeditor/editor/style.css";
@@ -90,6 +91,10 @@ export function MarkdownEditor({
linkPlugin({ disableAutoLink: true }),
codeBlockPlugin({ defaultCodeBlockLanguage: "" }),
codeMirrorPlugin({ codeBlockLanguages: CODE_BLOCK_LANGUAGES }),
tablePlugin(),
// Headings, lists (incl. `- [ ]` task lists), emphasis, strikethrough,
// inline code, quotes, and links all transform as you type via these
// shortcuts; fenced code blocks and tables are inserted via paste/import.
markdownShortcutPlugin(),
]}
/>
@@ -95,14 +95,55 @@ const markdownComponents: React.ComponentProps<typeof ReactMarkdown>["components
{children}
</pre>
),
ul: ({ children }) => <ul className="mb-3 list-disc pl-5 text-white last:mb-0">{children}</ul>,
del: ({ children }) => <del className="text-white/70 line-through">{children}</del>,
ul: ({ className, children }) => (
<ul
className={cn(
"mb-3 text-white last:mb-0",
className?.includes("contains-task-list") ? "list-none pl-0" : "list-disc pl-5",
)}
>
{children}
</ul>
),
ol: ({ children }) => <ol className="mb-3 list-decimal pl-5 text-white last:mb-0">{children}</ol>,
li: ({ children }) => <li className="mb-1 leading-relaxed">{children}</li>,
li: ({ className, children }) => (
<li
className={cn(
"mb-1 leading-relaxed",
className?.includes("task-list-item") && "flex list-none items-start gap-2",
)}
>
{children}
</li>
),
input: ({ type, checked }) =>
type === "checkbox" ? (
<input
type="checkbox"
checked={!!checked}
readOnly
className="mt-1.5 size-3.5 shrink-0 accent-blue-500"
/>
) : null,
blockquote: ({ children }) => (
<blockquote className="mb-3 border-l-2 border-white/30 pl-4 italic text-white/70 last:mb-0">
{children}
</blockquote>
),
table: ({ children }) => (
<div className="mb-3 overflow-x-auto last:mb-0">
<table className="w-auto border-collapse text-sm text-white">{children}</table>
</div>
),
th: ({ children }) => (
<th className="border border-white/20 bg-white/10 px-2.5 py-1.5 text-left font-semibold">
{children}
</th>
),
td: ({ children }) => (
<td className="border border-white/20 px-2.5 py-1.5">{children}</td>
),
hr: () => <hr className="my-4 border-white/10" />,
};