Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/app/src/components/CodeMirrorPaperSurface.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,39 @@ describe("CodeMirrorPaperSurface", () => {
expect(onEditorReady).toHaveBeenLastCalledWith(null, view);
});

it("keeps configurable paragraph rhythm in measured block spacers", async () => {
const onEditorReady = vi.fn();
const { container, rerender } = render(
<CodeMirrorPaperSurface
initialContent={"Synthetic first paragraph\n\nSynthetic second paragraph"}
onEditorReady={onEditorReady}
onMarkdownChange={() => {}}
paragraphSpacingPx={14}
/>,
);

expect(
container.querySelector<HTMLElement>(".cm-markra-paragraph-spacer")
?.style.height,
).toBe("14px");

rerender(
<CodeMirrorPaperSurface
initialContent={"Synthetic first paragraph\n\nSynthetic second paragraph"}
onEditorReady={onEditorReady}
onMarkdownChange={() => {}}
paragraphSpacingPx={6}
/>,
);

await waitFor(() => {
expect(
container.querySelector<HTMLElement>(".cm-markra-paragraph-spacer")
?.style.height,
).toBe("6px");
});
});

it("uses the configured shortcut to paste clipboard text without formatting", async () => {
const code = [
"const mockValue = items.at(0);",
Expand Down
8 changes: 8 additions & 0 deletions packages/app/src/components/CodeMirrorPaperSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export interface CodeMirrorPaperSurfaceProps {
onTextSelectionChange?: (selection: AiSelectionContext | null) => unknown;
openExternalUrl?: (url: string) => unknown;
openLocalAttachment?: (src: string) => unknown;
paragraphSpacingPx?: number;
plugins?: readonly MarkraPlugin[];
readClipboardText?: ClipboardTextReader;
readOnly?: boolean;
Expand Down Expand Up @@ -145,6 +146,7 @@ interface MarkdownExtensionOptions {
openExternalUrl: () => ((url: string) => unknown) | undefined;
openLocalAttachment: () => ((src: string) => unknown) | undefined;
openSpellcheckSuggestions: (view: EditorView) => boolean;
paragraphSpacingPx: number;
resolveImageSrc: (source: string) => string | undefined;
hideHeadingMarkersOnFocus: boolean;
showCodeBlockLineNumbers: boolean;
Expand All @@ -162,6 +164,7 @@ function markdownExtension({
openExternalUrl,
openLocalAttachment,
openSpellcheckSuggestions,
paragraphSpacingPx,
resolveImageSrc,
hideHeadingMarkersOnFocus,
showCodeBlockLineNumbers,
Expand Down Expand Up @@ -202,6 +205,7 @@ function markdownExtension({
highlight: extendedSyntax?.highlight ?? true,
resolveLinkTarget: linkOptions?.resolveTarget,
hideHeadingMarkersOnFocus,
paragraphSpacing: paragraphSpacingPx,
plugins: [
blocksPlugin({
callout: extendedSyntax?.githubAlerts ?? true,
Expand Down Expand Up @@ -361,6 +365,7 @@ export function CodeMirrorPaperSurface({
openExternalUrl,
openLocalAttachment,
plugins = emptyPlugins,
paragraphSpacingPx = 8,
readClipboardText = readAppClipboardText,
readOnly = false,
resolveImageSrc,
Expand Down Expand Up @@ -541,6 +546,7 @@ export function CodeMirrorPaperSurface({
openExternalUrl: () => openExternalUrlRef.current,
openLocalAttachment: () => openLocalAttachmentRef.current,
openSpellcheckSuggestions: openSpellcheckSuggestionMenu,
paragraphSpacingPx,
resolveImageSrc: (source) => resolveImageSrcRef.current?.(source),
hideHeadingMarkersOnFocus,
showCodeBlockLineNumbers,
Expand Down Expand Up @@ -689,6 +695,7 @@ export function CodeMirrorPaperSurface({
openExternalUrl: () => openExternalUrlRef.current,
openLocalAttachment: () => openLocalAttachmentRef.current,
openSpellcheckSuggestions: openSpellcheckSuggestionMenu,
paragraphSpacingPx,
resolveImageSrc: (source) => resolveImageSrcRef.current?.(source),
hideHeadingMarkersOnFocus,
showCodeBlockLineNumbers,
Expand All @@ -712,6 +719,7 @@ export function CodeMirrorPaperSurface({
Boolean(openExternalUrl),
Boolean(openLocalAttachment),
openSpellcheckSuggestionMenu,
paragraphSpacingPx,
plugins,
readClipboardText,
hideHeadingMarkersOnFocus,
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/components/MarkdownPaper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export function MarkdownPaper({
onActiveOutlineIndexChange={onActiveOutlineIndexChange}
onEditorReady={onEditorReady}
onMarkdownChange={onMarkdownChange}
paragraphSpacingPx={paragraphSpacingPx}
onSaveClipboardAttachment={onSaveClipboardAttachment}
onSaveClipboardImage={onSaveClipboardImage}
onSaveRemoteClipboardImage={onSaveRemoteClipboardImage}
Expand Down
25 changes: 5 additions & 20 deletions packages/app/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -987,45 +987,40 @@
/* Heading controls follow typography even when the final heading has no
foldable content and therefore no fold-toggle decoration. */
.markdown-paper .cm-line.cm-markra-h1 {
--markra-heading-control-center-offset: -5.5px;
--markra-heading-control-center-offset: 0px;
color: var(--editor-h1-color) !important;
padding-block: 0 16px !important;
font-size: var(--editor-h1-font-size) !important;
font-weight: var(--editor-h1-font-weight) !important;
line-height: var(--editor-h1-line-height) !important;
}

.markdown-paper .cm-line.cm-markra-h2 {
--markra-heading-control-center-offset: 8px;
--markra-heading-control-center-offset: 0px;
color: var(--editor-h2-color) !important;
padding-block: 28px 12px !important;
font-size: var(--editor-h2-font-size) !important;
font-weight: var(--editor-h2-font-weight) !important;
line-height: var(--editor-h2-line-height) !important;
}

.markdown-paper .cm-line.cm-markra-h3 {
--markra-heading-control-center-offset: 9px;
--markra-heading-control-center-offset: 0px;
color: var(--editor-h3-color) !important;
padding-block: 22px 4px !important;
font-size: var(--editor-h3-font-size) !important;
font-weight: var(--editor-h3-font-weight) !important;
line-height: var(--editor-h3-line-height) !important;
}

.markdown-paper .cm-line.cm-markra-h4 {
--markra-heading-control-center-offset: 8px;
--markra-heading-control-center-offset: 0px;
color: var(--editor-h4-color) !important;
padding-block: 18px 2px !important;
font-size: var(--editor-h4-font-size) !important;
font-weight: var(--editor-h4-font-weight) !important;
line-height: var(--editor-h4-line-height) !important;
}

.markdown-paper .cm-line.cm-markra-h5,
.markdown-paper .cm-line.cm-markra-h6 {
--markra-heading-control-center-offset: 7px;
padding-block-start: 14px !important;
--markra-heading-control-center-offset: 0px;
}

.markdown-paper .cm-line.cm-markra-h5 {
Expand Down Expand Up @@ -1065,12 +1060,6 @@
color: var(--editor-text-primary);
}

/* Paragraph spacing is extra rhythm after content, not a replacement for
an authored blank line, which must retain the editor's normal line height. */
.markdown-paper .cm-line.cm-markra-paragraph-end {
padding-block-end: var(--editor-paragraph-spacing) !important;
}

.markdown-paper .cm-line.cm-markra-list-item {
position: relative;
}
Expand Down Expand Up @@ -1130,10 +1119,6 @@
color: var(--editor-text-secondary) !important;
}

.markdown-paper .cm-line.cm-markra-empty-line + .cm-line.cm-markra-blockquote {
margin-block-start: 10px;
}

.markdown-paper .cm-line.cm-markra-list-item + .cm-line.cm-markra-list-item {
--markra-block-toolbar-block-offset: 4px;
padding-block-start: 4px !important;
Expand Down
40 changes: 26 additions & 14 deletions packages/app/src/styles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ describe("editor stylesheet", () => {
expect(styles).toContain("font-size: 31px");
expect(styles).toContain(".markdown-paper .cm-line.cm-markra-h3");
expect(styles).toContain("font-size: 24px");
expect(styles).toContain(".markdown-paper .cm-line.cm-markra-empty-line");
expect(styles).toContain(".markdown-paper .cm-line.cm-markra-list-item");
expect(styles).toContain('[data-markra-list-source="hidden"]::before');
expect(styles).toContain('content: "" !important');
Expand Down Expand Up @@ -96,6 +95,21 @@ describe("editor stylesheet", () => {
}
});

it("keeps vertical heading rhythm out of editable CodeMirror line boxes", () => {
const styles = readFileSync(`${process.cwd()}/src/styles.css`, "utf8");

for (let level = 1; level <= 6; level += 1) {
const ruleStart = styles.indexOf(
`.markdown-paper .cm-line.cm-markra-h${level} {`,
);
const ruleEnd = styles.indexOf("\n }", ruleStart);
const rule = styles.slice(ruleStart, ruleEnd);

expect(ruleStart).toBeGreaterThanOrEqual(0);
expect(rule).not.toContain("padding-block");
}
});

it("keeps CodeMirror's preview selection theme-aware and readable", () => {
const styles = readFileSync(`${process.cwd()}/src/styles.css`, "utf8");
const selectionStart = styles.indexOf(
Expand Down Expand Up @@ -465,24 +479,25 @@ describe("editor stylesheet", () => {
expect(styles).not.toContain(
".markdown-paper .cm-line.cm-markra-empty-line {",
);
expect(styles).toContain(
expect(styles).not.toContain(
".markdown-paper .cm-line.cm-markra-paragraph-end {",
);
expect(styles).toContain(
expect(styles).not.toContain(
"padding-block-end: var(--editor-paragraph-spacing) !important;",
);
expect(styles).not.toContain("cm-markra-paragraph-separator");
expect(styles).not.toContain(
'.cm-markra-empty-line[data-markra-empty-source="hidden"] {',
);
expect(styles).not.toContain(
".cm-line.cm-markra-empty-line + .cm-line.cm-markra-blockquote",
);
expect(styles).not.toContain("margin-block-start: 10px;");
});

it("keeps CodeMirror block rhythm aligned with the original visual editor", () => {
const styles = readFileSync(`${process.cwd()}/src/styles.css`, "utf8");

expect(styles).toContain(
".cm-line.cm-markra-empty-line + .cm-line.cm-markra-blockquote",
);
expect(styles).toContain(
'.cm-line.cm-markra-list-item[data-list-depth="0"] +',
);
Expand Down Expand Up @@ -661,24 +676,21 @@ describe("editor stylesheet", () => {
);
expect(styles).toContain(
".markdown-paper .cm-line.cm-markra-h1 {\n" +
" --markra-heading-control-center-offset: -5.5px;",
" --markra-heading-control-center-offset: 0px;",
);
expect(styles).toContain(
".markdown-paper .cm-line.cm-markra-h2 {\n" +
" --markra-heading-control-center-offset: 8px;",
" --markra-heading-control-center-offset: 0px;",
);
expect(styles).toContain(
".markdown-paper .cm-line.cm-markra-h3 {\n" +
" --markra-heading-control-center-offset: 9px;",
" --markra-heading-control-center-offset: 0px;",
);
expect(styles).toContain(
".markdown-paper .cm-line.cm-markra-h4 {\n" +
" --markra-heading-control-center-offset: 8px;",
);
expect(styles).toContain(
"--markra-heading-control-center-offset: 7px;\n" +
" padding-block-start: 14px !important;",
" --markra-heading-control-center-offset: 0px;",
);
expect(styles).toContain("--markra-heading-control-center-offset: 0px;");
expect(styles).not.toContain(
".cm-line.cm-markra-h3.markra-heading-toggle-heading {\n" +
" --markra-heading-control-center-offset:",
Expand Down
Loading
Loading