diff --git a/packages/core/src/editor.ts b/packages/core/src/editor.ts index 4d356ea2..9a266be5 100644 --- a/packages/core/src/editor.ts +++ b/packages/core/src/editor.ts @@ -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(); @@ -1080,4 +1101,4 @@ export function createEditor(config: EditorConfig): EditorAPI { }; return api; -} +} \ No newline at end of file diff --git a/packages/core/test/editor.test.ts b/packages/core/test/editor.test.ts index 85505eba..31afbd99 100644 --- a/packages/core/test/editor.test.ts +++ b/packages/core/test/editor.test.ts @@ -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) { @@ -917,4 +957,4 @@ describe("createEditor — DOM event hook layer", () => { expect(passthrough.defaultPrevented).toBe(false); editor.destroy(); }); -}); +}); \ No newline at end of file