mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
feat(editor): wrap long Markdown lines (#2459)
This commit is contained in:
@@ -18,6 +18,14 @@ function editor(page: Page) {
|
|||||||
return page.getByTestId("file-source-editor").filter({ visible: true }).locator(".cm-content");
|
return page.getByTestId("file-source-editor").filter({ visible: true }).locator(".cm-content");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasHorizontalOverflow(element: HTMLElement): boolean {
|
||||||
|
return element.scrollWidth > element.clientWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fitsViewportWidth(element: HTMLElement): boolean {
|
||||||
|
return element.scrollWidth === element.clientWidth;
|
||||||
|
}
|
||||||
|
|
||||||
async function replaceEditorText(page: Page, content: string): Promise<void> {
|
async function replaceEditorText(page: Page, content: string): Promise<void> {
|
||||||
const contentElement = editor(page);
|
const contentElement = editor(page);
|
||||||
await contentElement.click();
|
await contentElement.click();
|
||||||
@@ -202,6 +210,36 @@ test.describe("CodeMirror workspace file editing", () => {
|
|||||||
).toHaveCSS("font-family", "monospace");
|
).toHaveCSS("font-family", "monospace");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("wraps Markdown while source code remains horizontally scrollable", async ({
|
||||||
|
page,
|
||||||
|
withWorkspace,
|
||||||
|
}) => {
|
||||||
|
const workspace = await withWorkspace({ prefix: "file-editing-wrap-" });
|
||||||
|
const longLine = "word ".repeat(300);
|
||||||
|
await writeFile(path.join(workspace.repoPath, "notes.md"), `${longLine}\n`, "utf8");
|
||||||
|
await writeFile(
|
||||||
|
path.join(workspace.repoPath, "source.ts"),
|
||||||
|
`const value = "${longLine}";\n`,
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
await workspace.navigateTo();
|
||||||
|
await openWorkspaceFile(page, "notes.md");
|
||||||
|
await page.getByTestId("file-mode-source").click();
|
||||||
|
|
||||||
|
const markdownScroller = page
|
||||||
|
.getByTestId("file-source-editor")
|
||||||
|
.filter({ visible: true })
|
||||||
|
.locator(".cm-scroller");
|
||||||
|
await expect.poll(() => markdownScroller.evaluate(fitsViewportWidth)).toBe(true);
|
||||||
|
|
||||||
|
await openWorkspaceFile(page, "source.ts");
|
||||||
|
const sourceScroller = page
|
||||||
|
.getByTestId("file-source-editor")
|
||||||
|
.filter({ visible: true })
|
||||||
|
.locator(".cm-scroller");
|
||||||
|
await expect.poll(() => sourceScroller.evaluate(hasHorizontalOverflow)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
test("autosaves, saves immediately, resolves conflicts, and restores live updates after reconnect", async ({
|
test("autosaves, saves immediately, resolves conflicts, and restores live updates after reconnect", async ({
|
||||||
page,
|
page,
|
||||||
withWorkspace,
|
withWorkspace,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Annotation, Compartment, EditorState, Transaction } from "@codemirror/s
|
|||||||
import { EditorView } from "@codemirror/view";
|
import { EditorView } from "@codemirror/view";
|
||||||
import { getLanguageForFile } from "@getpaseo/highlight";
|
import { getLanguageForFile } from "@getpaseo/highlight";
|
||||||
import { getCM, vim } from "@replit/codemirror-vim";
|
import { getCM, vim } from "@replit/codemirror-vim";
|
||||||
|
import { isRenderedMarkdownFile } from "@/components/file-pane-render-mode";
|
||||||
import type { WorkspaceFileLocation } from "@/workspace/file-open";
|
import type { WorkspaceFileLocation } from "@/workspace/file-open";
|
||||||
import type { FileEditorModel } from "./model";
|
import type { FileEditorModel } from "./model";
|
||||||
import { editorBaseExtensions, editorTheme, type EditorVisualTheme } from "./extensions.web";
|
import { editorBaseExtensions, editorTheme, type EditorVisualTheme } from "./extensions.web";
|
||||||
@@ -19,9 +20,14 @@ interface FileEditorViewProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const languageCompartment = new Compartment();
|
const languageCompartment = new Compartment();
|
||||||
|
const wrappingCompartment = new Compartment();
|
||||||
const themeCompartment = new Compartment();
|
const themeCompartment = new Compartment();
|
||||||
const vimCompartment = new Compartment();
|
const vimCompartment = new Compartment();
|
||||||
|
|
||||||
|
function wrappingForFile(filename: string) {
|
||||||
|
return isRenderedMarkdownFile(filename) ? EditorView.lineWrapping : [];
|
||||||
|
}
|
||||||
|
|
||||||
export function FileEditorView({
|
export function FileEditorView({
|
||||||
model,
|
model,
|
||||||
filename,
|
filename,
|
||||||
@@ -50,6 +56,7 @@ export function FileEditorView({
|
|||||||
vimCompartment.of(values.vimEnabled ? vim() : []),
|
vimCompartment.of(values.vimEnabled ? vim() : []),
|
||||||
...editorBaseExtensions(() => void values.model.save()),
|
...editorBaseExtensions(() => void values.model.save()),
|
||||||
languageCompartment.of(getLanguageForFile(values.filename)?.extension ?? []),
|
languageCompartment.of(getLanguageForFile(values.filename)?.extension ?? []),
|
||||||
|
wrappingCompartment.of(wrappingForFile(values.filename)),
|
||||||
themeCompartment.of(editorTheme(values.theme)),
|
themeCompartment.of(editorTheme(values.theme)),
|
||||||
EditorView.updateListener.of((update) => {
|
EditorView.updateListener.of((update) => {
|
||||||
if (
|
if (
|
||||||
@@ -104,7 +111,10 @@ export function FileEditorView({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
viewRef.current?.dispatch({
|
viewRef.current?.dispatch({
|
||||||
effects: languageCompartment.reconfigure(getLanguageForFile(filename)?.extension ?? []),
|
effects: [
|
||||||
|
languageCompartment.reconfigure(getLanguageForFile(filename)?.extension ?? []),
|
||||||
|
wrappingCompartment.reconfigure(wrappingForFile(filename)),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
}, [filename]);
|
}, [filename]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user