diff --git a/js/desktop/src/features/compose/markdown-editor.css b/js/desktop/src/features/compose/markdown-editor.css index 9fd6791..501b7b0 100644 --- a/js/desktop/src/features/compose/markdown-editor.css +++ b/js/desktop/src/features/compose/markdown-editor.css @@ -1,7 +1,12 @@ -/* Blend MDXEditor into the compose glass card. - We lean on MDXEditor's bundled `dark-theme` for typography (heading sizes, - list markers, code styling) and only override the chrome: transparent - background, no border, and padding/colors tuned to the surrounding card. */ +/* Blend MDXEditor into the compose glass card, and restore prose typography. + * + * MDXEditor renders real
elements and leans on the + * browser's default styles for their look — it ships no heading/list + * typography of its own. Tailwind's Preflight resets those defaults + * (headings -> `font-size: inherit`, lists -> `list-style: none`), which would + * otherwise make a heading or bullet look identical to body text. So we style + * the content elements explicitly here, mirroring the rendered display in + * text-particle-view.tsx so "write" and "read" match. */ .llink-mdxeditor { --baseBg: transparent; @@ -24,10 +29,106 @@ line-height: 1.7; } -.llink-mdx-content :where(h1, h2, h3, h4, h5, h6) { +/* Headings */ +.llink-mdx-content h1, +.llink-mdx-content h2, +.llink-mdx-content h3, +.llink-mdx-content h4, +.llink-mdx-content h5, +.llink-mdx-content h6 { color: #fff; + line-height: 1.25; +} +.llink-mdx-content h1 { + font-size: 1.875rem; + font-weight: 700; + margin-bottom: 0.75rem; +} +.llink-mdx-content h2 { + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 0.5rem; +} +.llink-mdx-content h3 { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 0.5rem; +} +.llink-mdx-content h4 { + font-size: 1.125rem; + font-weight: 500; + margin-bottom: 0.25rem; +} +.llink-mdx-content h5 { + font-size: 1rem; + font-weight: 500; + margin-bottom: 0.25rem; +} +.llink-mdx-content h6 { + font-size: 0.875rem; + font-weight: 500; + margin-bottom: 0.25rem; } +/* Block spacing */ +.llink-mdx-content p { + margin-bottom: 0.75rem; + line-height: 1.625; +} +.llink-mdx-content > :last-child { + margin-bottom: 0; +} + +/* Inline emphasis */ +.llink-mdx-content strong { + font-weight: 600; + color: #fff; +} +.llink-mdx-content em { + font-style: italic; +} .llink-mdx-content a { color: #60a5fa; + text-decoration: underline; +} + +/* Lists — Preflight strips the marker and indentation, so restore both */ +.llink-mdx-content ul, +.llink-mdx-content ol { + margin-bottom: 0.75rem; + padding-left: 1.25rem; +} +.llink-mdx-content ul { + list-style: disc; +} +.llink-mdx-content ol { + list-style: decimal; +} +.llink-mdx-content li { + margin-bottom: 0.25rem; + line-height: 1.625; +} + +/* Blockquote */ +.llink-mdx-content blockquote { + margin-bottom: 0.75rem; + padding-left: 1rem; + border-left: 2px solid rgb(255 255 255 / 0.3); + font-style: italic; + color: rgb(255 255 255 / 0.7); +} + +/* Inline code */ +.llink-mdx-content code { + border-radius: 0.25rem; + background: rgb(255 255 255 / 0.1); + padding: 0.1rem 0.375rem; + font-size: 0.85em; +} + +/* Horizontal rule */ +.llink-mdx-content hr { + margin: 1rem 0; + border: none; + border-top: 1px solid rgb(255 255 255 / 0.1); } diff --git a/js/desktop/src/features/compose/markdown-editor.tsx b/js/desktop/src/features/compose/markdown-editor.tsx index 317a907..0510e49 100644 --- a/js/desktop/src/features/compose/markdown-editor.tsx +++ b/js/desktop/src/features/compose/markdown-editor.tsx @@ -83,7 +83,11 @@ export function MarkdownEditor({ listsPlugin(), quotePlugin(), thematicBreakPlugin(), - linkPlugin(), + // disableAutoLink: keep pasted/typed URLs as plain text rather than + // turning them into `[url](url)`. The compose flow already turns bare + // URLs into link-preview cards, so auto-linking would both duplicate + // the URL in the markdown and double up the preview cards. + linkPlugin({ disableAutoLink: true }), codeBlockPlugin({ defaultCodeBlockLanguage: "" }), codeMirrorPlugin({ codeBlockLanguages: CODE_BLOCK_LANGUAGES }), markdownShortcutPlugin(), diff --git a/js/desktop/src/lib/link-metadata.ts b/js/desktop/src/lib/link-metadata.ts index 78b9388..0bdbc9d 100644 --- a/js/desktop/src/lib/link-metadata.ts +++ b/js/desktop/src/lib/link-metadata.ts @@ -10,5 +10,7 @@ export interface LinkMetadata { const URL_REGEX = /https?:\/\/[^\s<>"')\]]+/g; export function extractUrls(text: string): string[] { - return Array.from(text.matchAll(URL_REGEX), (m) => m[0]); + // Dedupe: a URL repeated in the text (e.g. a `[url](url)` markdown link) + // should only yield a single preview card. + return Array.from(new Set(Array.from(text.matchAll(URL_REGEX), (m) => m[0]))); }