Skip to content

Conversation

@aaryan610
Copy link
Member

@aaryan610 aaryan610 commented Nov 28, 2025

Description

This PR implements the new markdown rules in the Copy markdown option.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Summary by CodeRabbit

  • Refactor
    • Updated Markdown generation logic to use a new conversion approach with metadata integration.
    • Modified editor helper functions to propagate metadata through the conversion pipeline.
    • Enhanced editor hook to track metadata changes in dependency tracking.

✏️ Tip: You can customize this high-level summary in your review settings.

@makeplane
Copy link

makeplane bot commented Nov 28, 2025

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 28, 2025

Walkthrough

The changes refactor how Markdown is generated in the editor. Instead of retrieving Markdown directly from storage, the implementation now converts HTML to Markdown using a utility function and editor metadata. The ref helpers and use-editor hook are updated to propagate metadata extraction logic throughout the flow.

Changes

Cohort / File(s) Summary
Editor Ref Helper Enhancement
packages/editor/src/core/helpers/editor-ref.ts
Added imports for convertHTMLToMarkdown and IEditorProps. Extended TArgs type to include getEditorMetaData. Refactored getMarkDown() to: obtain HTML via editor.getHTML(), extract metadata via getEditorMetaData(), convert HTML to Markdown using convertHTMLToMarkdown(), and return the result.
Use Editor Hook Update
packages/editor/src/core/hooks/use-editor.ts
Updated imperative handle initialization to pass getEditorMetaData to getEditorRefHelpers and added getEditorMetaData to the dependency array.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Verify that convertHTMLToMarkdown output matches previous getMarkdown() behavior
  • Confirm metadata extraction via getEditorMetaData is applied correctly
  • Check dependency array inclusion of getEditorMetaData doesn't cause unnecessary re-renders or ref updates

Poem

🐰 From storage deep, we hop to new ways,
HTML to Markdown, through metadata's maze,
A conversion dance, with metadata's grace,
The editor's heart finds its rightful place! 📝✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately identifies the main change: fixing a regression in the copy markdown option via new markdown rules implementation.
Description check ✅ Passed The description includes the required Description section and Type of Change section, though Test Scenarios and Screenshots sections are missing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/copy-markdown

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression in the "Copy markdown" option by implementing new markdown conversion rules. The change migrates from the old TipTap markdown storage approach to a new unified conversion method that uses metadata extraction.

Key Changes:

  • Pass getEditorMetaData function through the editor ref helpers chain
  • Replace the legacy markdown storage retrieval with the new convertHTMLToMarkdown utility
  • Ensure consistency with the clipboard markdown conversion pattern

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
packages/editor/src/core/hooks/use-editor.ts Passes getEditorMetaData to getEditorRefHelpers and adds it to the dependency array of useImperativeHandle
packages/editor/src/core/helpers/editor-ref.ts Updates getMarkDown() to use convertHTMLToMarkdown with metadata extraction, replacing the old markdown storage approach

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/editor/src/core/helpers/editor-ref.ts (1)

13-13: Consider using import type for type-only imports.

Per coding guidelines, type-only imports should use import type for proper tree-shaking and to respect verbatimModuleSyntax:

Apply this diff:

-import type { EditorRefApi, IEditorProps, TEditorCommands } from "@/types";
+import type { EditorRefApi, TEditorCommands } from "@/types";
+import type { IEditorProps } from "@/types";

Or consolidate all as type imports (if not already):

-import type { EditorRefApi, IEditorProps, TEditorCommands } from "@/types";
+import type { EditorRefApi, IEditorProps, TEditorCommands } from "@/types";

Note: The current import is already using import type, so this is already correct. The comment above is only applicable if any of these were regular imports.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 123f59e and be10bf8.

📒 Files selected for processing (2)
  • packages/editor/src/core/helpers/editor-ref.ts (2 hunks)
  • packages/editor/src/core/hooks/use-editor.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • packages/editor/src/core/hooks/use-editor.ts
  • packages/editor/src/core/helpers/editor-ref.ts
🧠 Learnings (1)
📚 Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{js,mjs,cjs} : Use `import` tags in JSDoc for cleaner type imports in JavaScript files when working in a mixed codebase (TypeScript 5.5+)

Applied to files:

  • packages/editor/src/core/helpers/editor-ref.ts
🧬 Code graph analysis (2)
packages/editor/src/core/hooks/use-editor.ts (1)
packages/editor/src/core/helpers/editor-ref.ts (1)
  • getEditorRefHelpers (24-261)
packages/editor/src/core/helpers/editor-ref.ts (2)
packages/editor/src/core/types/editor.ts (2)
  • IEditorProps (142-171)
  • EditorRefApi (100-139)
packages/utils/src/editor/markdown-parser/root.ts (1)
  • convertHTMLToMarkdown (112-143)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Agent
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build and lint web apps
🔇 Additional comments (5)
packages/editor/src/core/helpers/editor-ref.ts (4)

5-6: LGTM!

The import of convertHTMLToMarkdown is correctly added to support the new markdown conversion flow.


13-13: LGTM!

The addition of IEditorProps to the type imports is correct and follows TypeScript best practices by using import type.


19-22: LGTM!

The type extension using Pick<IEditorProps, "getEditorMetaData"> is a clean and type-safe approach to ensure the function signature matches the interface definition.


25-25: LGTM!

The destructuring correctly extracts getEditorMetaData alongside the existing properties.

packages/editor/src/core/hooks/use-editor.ts (1)

135-144: getEditorMetaData is already memoized in parent components via useCallback; the dependency array addition is correct and poses no performance concerns.

The verification confirms that getEditorMetaData is properly wrapped in useCallback in the parent components (both apps/web/core/hooks/use-parse-editor-content.ts and apps/space/core/hooks/use-parse-editor-content.ts), ensuring it remains stable across renders. The addition of getEditorMetaData to the useImperativeHandle dependency array on line 143 is therefore correct per React's rules of hooks, and the ref helpers will only be recreated when necessary. No performance issues arise from this change.

Comment on lines 81 to 91
getMarkDown: () => {
const markdownOutput = editor?.storage?.markdown?.getMarkdown?.() ?? "";
return markdownOutput;
if (!editor) return "";
const editorHTML = editor.getHTML();
const metaData = getEditorMetaData(editorHTML);
// convert to markdown
const markdown = convertHTMLToMarkdown({
description_html: editorHTML,
metaData,
});
return markdown;
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for the markdown conversion flow.

The refactored getMarkDown implementation doesn't handle potential errors from getEditorMetaData or convertHTMLToMarkdown. If either function throws, it could break the copy markdown functionality and impact user experience.

Apply this diff to add defensive error handling:

 getMarkDown: () => {
   if (!editor) return "";
-  const editorHTML = editor.getHTML();
-  const metaData = getEditorMetaData(editorHTML);
-  // convert to markdown
-  const markdown = convertHTMLToMarkdown({
-    description_html: editorHTML,
-    metaData,
-  });
-  return markdown;
+  try {
+    const editorHTML = editor.getHTML();
+    const metaData = getEditorMetaData(editorHTML);
+    // convert to markdown
+    const markdown = convertHTMLToMarkdown({
+      description_html: editorHTML,
+      metaData,
+    });
+    return markdown;
+  } catch (error) {
+    console.error("Error converting HTML to markdown:", error);
+    return "";
+  }
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
getMarkDown: () => {
const markdownOutput = editor?.storage?.markdown?.getMarkdown?.() ?? "";
return markdownOutput;
if (!editor) return "";
const editorHTML = editor.getHTML();
const metaData = getEditorMetaData(editorHTML);
// convert to markdown
const markdown = convertHTMLToMarkdown({
description_html: editorHTML,
metaData,
});
return markdown;
},
getMarkDown: () => {
if (!editor) return "";
try {
const editorHTML = editor.getHTML();
const metaData = getEditorMetaData(editorHTML);
// convert to markdown
const markdown = convertHTMLToMarkdown({
description_html: editorHTML,
metaData,
});
return markdown;
} catch (error) {
console.error("Error converting HTML to markdown:", error);
return "";
}
},
🤖 Prompt for AI Agents
In packages/editor/src/core/helpers/editor-ref.ts around lines 81 to 91, the
getMarkDown function currently calls getEditorMetaData and convertHTMLToMarkdown
without protection; wrap the conversion flow in a try/catch, catch any errors
from metadata extraction or markdown conversion, log the error with the project
logger (or console.error if no logger is available), and return an empty string
(or a safe fallback) so the UI doesn't break; ensure the catch block avoids
rethrowing and keeps the function deterministic.

@pushya22 pushya22 merged commit 6b85d67 into preview Dec 1, 2025
13 checks passed
@pushya22 pushya22 deleted the fix/copy-markdown branch December 1, 2025 07:18
ClarenceChen0627 pushed a commit to ClarenceChen0627/plane that referenced this pull request Dec 5, 2025
ClarenceChen0627 pushed a commit to ClarenceChen0627/plane that referenced this pull request Dec 5, 2025
ClarenceChen0627 pushed a commit to ClarenceChen0627/plane that referenced this pull request Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants