Skip to content
Open
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
23 changes: 22 additions & 1 deletion packages/core/src/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,27 @@ export function createEditor(config: EditorConfig): EditorAPI {
viewRef.current = view;
lastMarkdownTransformRevision = getMarkdownTransformRevision(view.state);

requestAnimationFrame(() => {
const containerEl = config.container;
const computedHeight = getComputedStyle(containerEl).height;
const hasExplicitHeight = computedHeight !== "0px" && computedHeight !== "auto" && computedHeight !== "";
if (!hasExplicitHeight) {
const style = getComputedStyle(containerEl);
let hint = "";
if (style.display === "none") {
hint =
"The container has `display: none`. Consider setting `display: block` or another visible display value.";
} else {
hint =
"The container has a computed height of 0. Give it an explicit CSS height (e.g. `height: 100%`, `min-height: 400px`, or a fixed pixel value).";
}
console.warn(
`[Nexus-Editor] Container element has zero height. The editor may appear blank.\n${hint}`,
containerEl
);
}
});

api = {
getDocument() {
return view.state.doc.toString();
Expand Down Expand Up @@ -1080,4 +1101,4 @@ export function createEditor(config: EditorConfig): EditorAPI {
};

return api;
}
}
42 changes: 41 additions & 1 deletion packages/core/test/editor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,46 @@ describe("createEditor", () => {
expect(html).toContain("console.log(1)");
editor.destroy();
});

it("warns when container has zero height", async () => {
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
const rAFSpy = vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) => {
cb(0);
return 0;
});

const container = document.createElement("div");
container.style.height = "0px";
createEditor({ container, initialValue: "hello" });

// requestAnimationFrame callback runs synchronously via the mock
expect(warnSpy).toHaveBeenCalledTimes(1);
const message: string = warnSpy.mock.calls[0]?.[0] ?? "";
expect(message).toContain("[Nexus-Editor]");
expect(message).toContain("zero height");
expect(message).toContain("explicit CSS height");

rAFSpy.mockRestore();
warnSpy.mockRestore();
});

it("does not warn when container has explicit height set", async () => {
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
const rAFSpy = vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) => {
cb(0);
return 0;
});

const container = document.createElement("div");
container.style.height = "400px";
const editor = createEditor({ container, initialValue: "hello" });

expect(warnSpy).not.toHaveBeenCalled();

rAFSpy.mockRestore();
warnSpy.mockRestore();
editor.destroy();
});
});

function captureViewPlugin(onView: (view: EditorView) => void) {
Expand Down Expand Up @@ -917,4 +957,4 @@ describe("createEditor — DOM event hook layer", () => {
expect(passthrough.defaultPrevented).toBe(false);
editor.destroy();
});
});
});