Skip to content

feat: add inline KaTeX math support#167

Open
PerretWilliam wants to merge 1 commit into
erictli:mainfrom
PerretWilliam:feat/inline-katex
Open

feat: add inline KaTeX math support#167
PerretWilliam wants to merge 1 commit into
erictli:mainfrom
PerretWilliam:feat/inline-katex

Conversation

@PerretWilliam

@PerretWilliam PerretWilliam commented Jun 5, 2026

Copy link
Copy Markdown

Summary

This PR adds inline KaTeX support to the editor so expressions written as $...$ are converted into inline math, alongside the existing block math syntax.

What changed

  • Added inline math node handling in the editor
  • Added inline math input conversion on typing the closing $
  • Added an inline math slash command
  • Updated markdown paste and plain-text stripping to handle inline math
  • Adjusted KaTeX styling so inline math aligns better with surrounding text
  • Kept existing block math behavior intact

Demo

Enregistrement.de.l.ecran.2026-06-05.a.13.01.07.mov

How to test

  • Type $a+b$ and verify it converts into inline math when the closing $ is typed
  • Test $a+b$ followed by space and enter
  • Verify block math $$a+b$$ still works
  • Verify $19.99 is not converted
  • Verify undo/redo works after conversion
  • Verify inline math can be edited again after insertion
  • Verify copy/paste and markdown/plain-text export still behave correctly

Summary by CodeRabbit

Release Notes

  • New Features

    • Added inline mathematical expression support with keyboard shortcut and dedicated editing interface
    • Enhanced math rendering with improved styling and display behavior
  • Improvements

    • Improved markdown-to-text conversion to properly handle LaTeX math expressions
    • Refined mathematical expression selection and interaction in the editor

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds inline LaTeX math support ($...$) to a TipTap editor, complementing existing block math. It introduces a new editor extension, unifies math editing popups, wires inline math through slash commands, and updates text normalization across the application.

Changes

Inline math feature

Layer / File(s) Summary
Math extensions: shared plugin and inline math
src/components/editor/MathExtensions.ts
createMathSelectionPlugin unifies DOM selection and Enter/Space handling for both block and inline math nodes. normalizeInlineMath extracts and trims content from $...$ delimiters. New ScratchInlineMath extension detects $...$ input patterns, extracts LaTeX, and creates inline math nodes; ScratchBlockMath is refactored to use the shared plugin.
Visual styling for math nodes
src/App.css
Inline-math TipTap nodes render as inline-block with vertical alignment; selected-node outline now includes both block-math and inline-math elements.
Math popup infrastructure and geometry
src/components/editor/Editor.tsx
getMathNodeRect computes DOMRect bounds for math nodes. mathPopupRef tracks the unified popup lifecycle. openMathPopup and closeMathPopup manage popup state and render math editors via ReactRenderer and Tippy.
Math editing handlers for block and inline
src/components/editor/Editor.tsx
handleEditBlockMath and handleEditInlineMath both use the unified popup flow, validate node type, apply LaTeX on submit, and adjust cursor position on cancel.
Math insertion and extension registration
src/components/editor/Editor.tsx, src/components/editor/SlashCommand.tsx
ScratchInlineMath is added to the editor extensions list with inline KaTeX display and onClick routing. Block and inline math insertion use openMathPopup with node insertion and selection adjustments. Inline math slash-command entry dispatches slash-command-inline-math events.
Command routing, event listeners, and lifecycle
src/components/editor/Editor.tsx
Markdown paste-detection regex updated for $$...$$. useEffect listener routes slash-command-inline-math events to handleAddInlineMath. Unmount cleanup destroys the math popup. Link popup opening closes the math popup. handleAddLink dependency array updated for closeMathPopup.
Text normalization and shortcut documentation
src/lib/plainText.ts, src-tauri/src/lib.rs, src/lib/shortcuts.ts
plainTextFromMarkdown and Rust strip_markdown remove LaTeX math delimiters. Inline math shortcut ($...$) added to keyboard shortcuts reference.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • erictli/scratch#80: Builds on the block-math keyboard selection and plugin infrastructure extended in this PR.
  • erictli/scratch#66: Extends KaTeX block-math integration with a refactored shared popup flow and inline-math support.
  • erictli/scratch#24: Uses the same slash-command infrastructure as the new inline math command.

Suggested reviewers

  • erictli

Poem

A rabbit hops through dollar signs with glee,
Where $...$ now renders gracefully,
Block and inline math dance as one,
The unified popup flow has begun. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add inline KaTeX math support' accurately summarizes the main change: adding inline math support to the application alongside existing block math functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/plainText.ts (1)

550-567: 💤 Low value

Consider clarifying comment specificity.

The comment on line 550 mentions "but only if not starting with a digit (to avoid stripping prices like $19.99)", but this guard only applies to inline math ($...$), not block math ($$...$$). While the implementation is correct, the comment could be more precise to avoid confusion.

Optional comment improvement
-    // Remove block math ($$...$$) and inline math ($...$), but only if not starting with a digit (to avoid stripping prices like $19.99)
+    // Remove block math ($$...$$) unconditionally and inline math ($...$) only if not starting with a digit (to avoid stripping prices like $19.99)

Implementation note: The Rust implementation achieves the same result as the TypeScript version using a slightly different approach (callback-based digit check vs. negative lookahead), which is appropriate for the Rust regex crate's API.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/plainText.ts` around lines 550 - 567, Update the imprecise comment
that reads "but only if not starting with a digit (to avoid stripping prices
like $19.99)" to explicitly state that this digit-check guard applies only to
inline math delimiters ($...$) and not to block math ($$...$$); locate the
comment in src/lib/plainText.ts near the inline-math regex/handling logic and
reword it to clarify the scope (inline vs block math) so readers understand the
guard's applicability without changing the implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/lib/plainText.ts`:
- Around line 550-567: Update the imprecise comment that reads "but only if not
starting with a digit (to avoid stripping prices like $19.99)" to explicitly
state that this digit-check guard applies only to inline math delimiters ($...$)
and not to block math ($$...$$); locate the comment in src/lib/plainText.ts near
the inline-math regex/handling logic and reword it to clarify the scope (inline
vs block math) so readers understand the guard's applicability without changing
the implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b2fad5ca-9aba-404a-99a8-f9051c23a2e9

📥 Commits

Reviewing files that changed from the base of the PR and between a638f02 and f113720.

📒 Files selected for processing (7)
  • src-tauri/src/lib.rs
  • src/App.css
  • src/components/editor/Editor.tsx
  • src/components/editor/MathExtensions.ts
  • src/components/editor/SlashCommand.tsx
  • src/lib/plainText.ts
  • src/lib/shortcuts.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant