Releases: Razee4315/Paperling
Releases · Razee4315/Paperling
Paperling v1.0.35
What's new in v1.0.35
Added
- The Export and Settings dropdown menus are now fully keyboard-operable: focus
moves into the menu on open, Arrow/Home/End move between items, and Escape
closes and returns focus to the button. - The file explorer refreshes when the window regains focus and gained a manual
refresh button, so its list no longer goes stale after files change on disk.
Changed
- PDF export now saves directly. On Windows, "Export → PDF" asks where to
save and writes the file straight away, instead of opening the system print
dialog. The PDF keeps selectable text and working links. - The theme now matches your operating system's light/dark setting on first
launch, and follows it until you pick a theme yourself. - Notifications stack instead of replacing one another, and error messages stay
on screen longer than confirmations. - The Light theme has a softer, warmer tone for a bit more character.
Removed
- The GitHub theme. (Light covers the same clean, bright look.)
Fixed
- Find & Replace now shows "Invalid pattern" for an unparseable regex instead of
a misleading "No results". - Cancelling the export save dialog no longer shows a false "Exported" message.
- A persistent autosave failure keeps reminding you (throttled) instead of
going quiet after the first warning.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for the full history.
Paperling v1.0.34
What's new in v1.0.34
Changed
- PDF export now saves directly. On Windows, "Export → PDF" asks where to
save and writes the file straight away, instead of opening the system print
dialog. The PDF keeps selectable text and working links.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for the full history.
Paperling v1.0.33
What's new in v1.0.33
A new version of Paperling is available.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for the full history.
Paperling v1.0.32
What's new in v1.0.32
A new version of Paperling is available.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for the full history.
Paperling v1.0.31
What's new in v1.0.31
A new version of Paperling is available.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for the full history.
Paperling v1.0.30
What's new in v1.0.30
Changed
- The "What's new" update popup now shows a concise summary of just the latest
release's changes, instead of the full changelog history.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for the full history.
Paperling v1.0.29
What's new in v1.0.29
Added
- Fullscreen mode (F11). Press F11 to toggle distraction-free fullscreen on
Windows, Linux, and macOS. The title bar stays visible so there's always an
obvious way back, and a one-time hint reminds you to press F11 to exit. Also
available from the command palette. - Auto-updater. Paperling now checks GitHub Releases on launch and shows a
popup when a newer version is available, with "Update now" (download with
progress, install, restart), "Skip this version" (remembered per version),
and "Later". Update packages are signed; the updater verifies the signature
before installing. - AI on/off switch. A new "Enable AI" toggle in Settings → AI (on by
default). Turning it off hides every AI surface: the title-bar AI button,
the AI side panel, the formatting-toolbar sparkle, Alt+J, and the command
palette entry. - Shimmery AI button. The title-bar AI button now carries the familiar
sparkle icon with a subtle shimmer animation. - Visual table editor. A floating toolbar appears when the caret is inside a
Markdown table, with buttons to insert or delete rows and columns, set
per-column alignment, and tidy (re-align) the layout. Built on a pure,
fully tested table model, so editing a table no longer means hand-aligning pipes.
Changed
- Cleaner "What's new" in the update popup. The updater now shows the
release's actual changes as a tidy, scrollable list instead of a block of raw
text. Release notes are sourced automatically from this changelog at build
time, and links open in your browser rather than inside the app. - Relicensed to Apache 2.0. MarkLite moved from the previous custom
non-commercial terms to the Apache License 2.0: free for both personal and
commercial use, with an explicit patent grant. SeeLICENSEandNOTICE. - Sharper positioning. The hero, README, and site now lead with what is
genuinely different (no-setup single-file editing, a free bring-your-own-model
AI that proposes edits as accept-or-reject diffs, live math and chemistry)
instead of generic "minimal / lightweight" claims.
Fixed
- List bullets and numbers now render in the preview. Tailwind v4's base
reset had stripped the list markers, leaving lists indented but marker-less. - Ctrl+S (and Ctrl+O / N / E) work with CapsLock on. An unshifted Ctrl+S
reportse.key === "S", which previously fell through and did nothing. - Heading anchor links give feedback. Clicking the link icon next to a
heading now copies a section link and shows a checkmark, instead of appearing
to do nothing when the heading is already at the top of the view. - Alt+J opens the AI side panel. With no text selected it now opens the
docked AI panel (previously it only opened the inline selection bubble); with
a selection it still opens selection-assist in place.
Fixed — Click after scroll lands on the right line
- Scrolling and immediately clicking (or double-clicking) used to land
the caret on a line one row off from where it visibly looked like
the click was — typing then added text to the "wrong" line, which
was confusing. The cause: the highlight overlay'sscrollTopwas
synced to the textarea via a rAF loop, which catches up on the NEXT
frame after the scroll. If you clicked inside that 16-ms window, the
textarea had already placed the caret at the new position but the
overlay was still painting the old one, so the visible glyph at the
click coordinate didn't match the textarea's text-position mapping. - Replaced the rAF loop with a synchronous
onScrollhandler on the
textarea. The overlay's scrollTop is now updated in the same turn
as the scroll event, so the two layers stay in lockstep and clicks
always land where the user expects. Also frees the main thread from
a 60 Hz rAF callback that was firing whether the editor was idle or
not.
Improved — Smaller per-keystroke recompute
updateCursorPositionran twice per keystroke (selectionchange AND
keyup both fire). The downstream setStates already bailed via
Object.is, but the substring + split work itself ran twice. Now
caches the last reported (start, end) range and short-circuits at
the top when nothing's moved.
Improved — Cold start and runtime performance
- Bundle main chunk: 1.08 MB → 282 kB (~74% smaller). Welcome screen no
longer ships the markdown rendering pipeline, jspdf/html2canvas, the
command palette, settings, stats dialog, file explorer, outline panel,
shortcuts cheatsheet, or the unsaved-changes dialog. Each is its own
chunk, fetched the moment its surface mounts.vite manualChunks
groups React and the markdown stack into stable vendor chunks the
WebView2 disk cache can hold across upgrades. - First file open: instant. A
requestIdleCallbackafter the welcome
screen settles starts the markdown chunk download in the background, so
by the time the user opens a file the bundle is already in cache. - Typing path: less work per keystroke. Command-palette heading scan
no longer runs on every typing pause — only while the palette is
actually open. App's per-keystrokecontent.split("\n")for
lineCountmoved into MarkdownPreview where it's actually used (one
fewer full-document scan per keystroke). StatusBar, TitleBar,
MarkdownPreview, and CodeEditor wrapped inReact.memowith stable
callbacks so caret-only re-renders bail out of reconciliation. - Highlight cache: drop LRU thrash. The CodeEditor's per-line
highlight cache used to dodelete + seton every cached line per
render to maintain LRU order — ~20 k Map mutations per keystroke on a
10 k-line file. The pruning that actually mattered ("is this line
still in the doc?") doesn't depend on order, so we just lookup-only on
hit and let the rare hard-cap fallback evict FIFO.
Added — Chemistry notation in math
- KaTeX now loads the mhchem contrib alongside the rest of the math
bundle, so\ce{...}and\pu{...}render in the preview.
This unlocks textbook-grade chemistry: balanced equations, ions,
isotopes, oxidation states, arrows, and Kröger-Vink defect notation
(e.g.$\ce{2 Fe^x_{Fe} + O^x_{O} -> 2 Fe'_{Fe} + V_{O}^{**} + 1/2 O2 ^}$).
The math-detection regex now also picks up bare\ce{/\pu{,
so chemistry-only documents trigger the lazy load even without
$delimiters. New/chemslash command inserts a starter snippet.
Improved — Book-style math typography
- Display equations are centered with proper vertical breathing room and
scroll horizontally on narrow viewports instead of overflowing the
reading column. KaTeX glyphs no longer inherit the globalcodeborder
/background, and equation tags pick up the muted-text colour for a
printed-textbook feel.
Fixed — Caret drifts off the rendered glyph after scrolling
- The CodeEditor stacks a transparent
<textarea>on top of a styled
highlight overlay; alignment relies on both layers wrapping at the
same column. Once the document grew past the viewport the textarea
sprouted a vertical scrollbar that quietly ate ~10 px of its content
area, while the overlay kept its full width. With word-wrap on, the
two layers wrapped at different columns and the caret started landing
a character or two off the rendered text after every scroll. Both
layers now reserve a fixed scrollbar gutter (scrollbar-gutter: stable),
and the overlay's own scrollbar is hidden visually so only the
textarea's remains user-facing.
Improved — Editor performance on large documents
- Typing into a 5 k+ line markdown file used to feel "sticky" because
the highlight overlay mounted every line as a<div>and React's
reconciler walked the lot on every keystroke. The overlay now
virtualizes: only the lines visible in the viewport (plus a 40-line
buffer) render, with fixed-height spacers above and below preserving
scroll-height parity with the textarea so caret alignment is intact.
Re-renders only fire when the visible window shifts by more than half
the buffer, so smooth scrolling no longer thrashes setState.
Word-wrap mode and small docs (under 400 lines) keep the previous
full-render path. Per-line wrapper styles are also hoisted to module
scope and the non-virtualized list is wrapped inReact.memoso
unchanged lines short-circuit prop diffing.
Fixed — Webview accelerator collision
- AI assist shortcut now also responds to Alt+J. On Windows, WebView2
treatsCtrl+Jas a "browser accelerator" for the built-in Downloads
UI — the page never sees the keydown, soe.preventDefault()can't
rescue it. Alt+J skips that path entirely. macOS (WKWebView) and Linux
(WebKitGTK) keepCtrl+Jworking; the cheatsheet detects the platform
and shows the right one. A capture-phasekeydownlistener also
preventDefaults Ctrl+J app-wide, so on platforms where the page does
see the event the host webview's default action is suppressed
regardless of which element is focused.
Fixed — Security
read_file/save_filerefuse documents above 50 MB. Stat happens before
the read so an oversized file fails fast with a clear "File too large"
toast instead of pulling hundreds of MB of UTF-8 into the webview while
the UI freezes.save_imagerefuses payloads above 25 MB and now enforces an extension
whitelist (png,jpg,jpeg,gif,webp,bmp,svg,
case-insensitive). A caller can no longer drop a.exe/.dll/.lnk
into the user's documents folder under cover of the markdown image-paste
flow. Tests cover the new rejections plus all whitelisted extensions.- AI requests get a 60 s wall-clock timeout (composed with the user's
existingAbortController) and the response is capped at 200 KB. A
stuck local llama.cpp or a runaway model can no longer hang the AI
bubble forever or paste megabytes of text into the editor. - Tauri CSP fur...
Paperling v1.0.28
What's new in v1.0.28
Added
- Fullscreen mode (F11). Press F11 to toggle distraction-free fullscreen on
Windows, Linux, and macOS. The title bar stays visible so there's always an
obvious way back, and a one-time hint reminds you to press F11 to exit. Also
available from the command palette. - Auto-updater. Paperling now checks GitHub Releases on launch and shows a
popup when a newer version is available, with "Update now" (download with
progress, install, restart), "Skip this version" (remembered per version),
and "Later". Update packages are signed; the updater verifies the signature
before installing. - AI on/off switch. A new "Enable AI" toggle in Settings → AI (on by
default). Turning it off hides every AI surface: the title-bar AI button,
the AI side panel, the formatting-toolbar sparkle, Alt+J, and the command
palette entry. - Shimmery AI button. The title-bar AI button now carries the familiar
sparkle icon with a subtle shimmer animation. - Visual table editor. A floating toolbar appears when the caret is inside a
Markdown table, with buttons to insert or delete rows and columns, set
per-column alignment, and tidy (re-align) the layout. Built on a pure,
fully tested table model, so editing a table no longer means hand-aligning pipes.
Changed
- Cleaner "What's new" in the update popup. The updater now shows the
release's actual changes as a tidy, scrollable list instead of a block of raw
text. Release notes are sourced automatically from this changelog at build
time, and links open in your browser rather than inside the app. - Relicensed to Apache 2.0. MarkLite moved from the previous custom
non-commercial terms to the Apache License 2.0: free for both personal and
commercial use, with an explicit patent grant. SeeLICENSEandNOTICE. - Sharper positioning. The hero, README, and site now lead with what is
genuinely different (no-setup single-file editing, a free bring-your-own-model
AI that proposes edits as accept-or-reject diffs, live math and chemistry)
instead of generic "minimal / lightweight" claims.
Fixed
- List bullets and numbers now render in the preview. Tailwind v4's base
reset had stripped the list markers, leaving lists indented but marker-less. - Ctrl+S (and Ctrl+O / N / E) work with CapsLock on. An unshifted Ctrl+S
reportse.key === "S", which previously fell through and did nothing. - Heading anchor links give feedback. Clicking the link icon next to a
heading now copies a section link and shows a checkmark, instead of appearing
to do nothing when the heading is already at the top of the view. - Alt+J opens the AI side panel. With no text selected it now opens the
docked AI panel (previously it only opened the inline selection bubble); with
a selection it still opens selection-assist in place.
Fixed — Click after scroll lands on the right line
- Scrolling and immediately clicking (or double-clicking) used to land
the caret on a line one row off from where it visibly looked like
the click was — typing then added text to the "wrong" line, which
was confusing. The cause: the highlight overlay'sscrollTopwas
synced to the textarea via a rAF loop, which catches up on the NEXT
frame after the scroll. If you clicked inside that 16-ms window, the
textarea had already placed the caret at the new position but the
overlay was still painting the old one, so the visible glyph at the
click coordinate didn't match the textarea's text-position mapping. - Replaced the rAF loop with a synchronous
onScrollhandler on the
textarea. The overlay's scrollTop is now updated in the same turn
as the scroll event, so the two layers stay in lockstep and clicks
always land where the user expects. Also frees the main thread from
a 60 Hz rAF callback that was firing whether the editor was idle or
not.
Improved — Smaller per-keystroke recompute
updateCursorPositionran twice per keystroke (selectionchange AND
keyup both fire). The downstream setStates already bailed via
Object.is, but the substring + split work itself ran twice. Now
caches the last reported (start, end) range and short-circuits at
the top when nothing's moved.
Improved — Cold start and runtime performance
- Bundle main chunk: 1.08 MB → 282 kB (~74% smaller). Welcome screen no
longer ships the markdown rendering pipeline, jspdf/html2canvas, the
command palette, settings, stats dialog, file explorer, outline panel,
shortcuts cheatsheet, or the unsaved-changes dialog. Each is its own
chunk, fetched the moment its surface mounts.vite manualChunks
groups React and the markdown stack into stable vendor chunks the
WebView2 disk cache can hold across upgrades. - First file open: instant. A
requestIdleCallbackafter the welcome
screen settles starts the markdown chunk download in the background, so
by the time the user opens a file the bundle is already in cache. - Typing path: less work per keystroke. Command-palette heading scan
no longer runs on every typing pause — only while the palette is
actually open. App's per-keystrokecontent.split("\n")for
lineCountmoved into MarkdownPreview where it's actually used (one
fewer full-document scan per keystroke). StatusBar, TitleBar,
MarkdownPreview, and CodeEditor wrapped inReact.memowith stable
callbacks so caret-only re-renders bail out of reconciliation. - Highlight cache: drop LRU thrash. The CodeEditor's per-line
highlight cache used to dodelete + seton every cached line per
render to maintain LRU order — ~20 k Map mutations per keystroke on a
10 k-line file. The pruning that actually mattered ("is this line
still in the doc?") doesn't depend on order, so we just lookup-only on
hit and let the rare hard-cap fallback evict FIFO.
Added — Chemistry notation in math
- KaTeX now loads the mhchem contrib alongside the rest of the math
bundle, so\ce{...}and\pu{...}render in the preview.
This unlocks textbook-grade chemistry: balanced equations, ions,
isotopes, oxidation states, arrows, and Kröger-Vink defect notation
(e.g.$\ce{2 Fe^x_{Fe} + O^x_{O} -> 2 Fe'_{Fe} + V_{O}^{**} + 1/2 O2 ^}$).
The math-detection regex now also picks up bare\ce{/\pu{,
so chemistry-only documents trigger the lazy load even without
$delimiters. New/chemslash command inserts a starter snippet.
Improved — Book-style math typography
- Display equations are centered with proper vertical breathing room and
scroll horizontally on narrow viewports instead of overflowing the
reading column. KaTeX glyphs no longer inherit the globalcodeborder
/background, and equation tags pick up the muted-text colour for a
printed-textbook feel.
Fixed — Caret drifts off the rendered glyph after scrolling
- The CodeEditor stacks a transparent
<textarea>on top of a styled
highlight overlay; alignment relies on both layers wrapping at the
same column. Once the document grew past the viewport the textarea
sprouted a vertical scrollbar that quietly ate ~10 px of its content
area, while the overlay kept its full width. With word-wrap on, the
two layers wrapped at different columns and the caret started landing
a character or two off the rendered text after every scroll. Both
layers now reserve a fixed scrollbar gutter (scrollbar-gutter: stable),
and the overlay's own scrollbar is hidden visually so only the
textarea's remains user-facing.
Improved — Editor performance on large documents
- Typing into a 5 k+ line markdown file used to feel "sticky" because
the highlight overlay mounted every line as a<div>and React's
reconciler walked the lot on every keystroke. The overlay now
virtualizes: only the lines visible in the viewport (plus a 40-line
buffer) render, with fixed-height spacers above and below preserving
scroll-height parity with the textarea so caret alignment is intact.
Re-renders only fire when the visible window shifts by more than half
the buffer, so smooth scrolling no longer thrashes setState.
Word-wrap mode and small docs (under 400 lines) keep the previous
full-render path. Per-line wrapper styles are also hoisted to module
scope and the non-virtualized list is wrapped inReact.memoso
unchanged lines short-circuit prop diffing.
Fixed — Webview accelerator collision
- AI assist shortcut now also responds to Alt+J. On Windows, WebView2
treatsCtrl+Jas a "browser accelerator" for the built-in Downloads
UI — the page never sees the keydown, soe.preventDefault()can't
rescue it. Alt+J skips that path entirely. macOS (WKWebView) and Linux
(WebKitGTK) keepCtrl+Jworking; the cheatsheet detects the platform
and shows the right one. A capture-phasekeydownlistener also
preventDefaults Ctrl+J app-wide, so on platforms where the page does
see the event the host webview's default action is suppressed
regardless of which element is focused.
Fixed — Security
read_file/save_filerefuse documents above 50 MB. Stat happens before
the read so an oversized file fails fast with a clear "File too large"
toast instead of pulling hundreds of MB of UTF-8 into the webview while
the UI freezes.save_imagerefuses payloads above 25 MB and now enforces an extension
whitelist (png,jpg,jpeg,gif,webp,bmp,svg,
case-insensitive). A caller can no longer drop a.exe/.dll/.lnk
into the user's documents folder under cover of the markdown image-paste
flow. Tests cover the new rejections plus all whitelisted extensions.- AI requests get a 60 s wall-clock timeout (composed with the user's
existingAbortController) and the response is capped at 200 KB. A
stuck local llama.cpp or a runaway model can no longer hang the AI
bubble forever or paste megabytes of text into the editor. - Tauri CSP fur...
Paperling v1.0.27
What's new in v1.0.27
Added
- Fullscreen mode (F11). Press F11 to toggle distraction-free fullscreen on
Windows, Linux, and macOS. The title bar stays visible so there's always an
obvious way back, and a one-time hint reminds you to press F11 to exit. Also
available from the command palette. - Auto-updater. Paperling now checks GitHub Releases on launch and shows a
popup when a newer version is available, with "Update now" (download with
progress, install, restart), "Skip this version" (remembered per version),
and "Later". Update packages are signed; the updater verifies the signature
before installing. - AI on/off switch. A new "Enable AI" toggle in Settings → AI (on by
default). Turning it off hides every AI surface: the title-bar AI button,
the AI side panel, the formatting-toolbar sparkle, Alt+J, and the command
palette entry. - Shimmery AI button. The title-bar AI button now carries the familiar
sparkle icon with a subtle shimmer animation. - Visual table editor. A floating toolbar appears when the caret is inside a
Markdown table, with buttons to insert or delete rows and columns, set
per-column alignment, and tidy (re-align) the layout. Built on a pure,
fully tested table model, so editing a table no longer means hand-aligning pipes.
Changed
- Cleaner "What's new" in the update popup. The updater now shows the
release's actual changes as a tidy, scrollable list instead of a block of raw
text. Release notes are sourced automatically from this changelog at build
time, and links open in your browser rather than inside the app. - Relicensed to Apache 2.0. MarkLite moved from the previous custom
non-commercial terms to the Apache License 2.0: free for both personal and
commercial use, with an explicit patent grant. SeeLICENSEandNOTICE. - Sharper positioning. The hero, README, and site now lead with what is
genuinely different (no-setup single-file editing, a free bring-your-own-model
AI that proposes edits as accept-or-reject diffs, live math and chemistry)
instead of generic "minimal / lightweight" claims.
Fixed
- List bullets and numbers now render in the preview. Tailwind v4's base
reset had stripped the list markers, leaving lists indented but marker-less. - Ctrl+S (and Ctrl+O / N / E) work with CapsLock on. An unshifted Ctrl+S
reportse.key === "S", which previously fell through and did nothing. - Heading anchor links give feedback. Clicking the link icon next to a
heading now copies a section link and shows a checkmark, instead of appearing
to do nothing when the heading is already at the top of the view. - Alt+J opens the AI side panel. With no text selected it now opens the
docked AI panel (previously it only opened the inline selection bubble); with
a selection it still opens selection-assist in place.
Fixed — Click after scroll lands on the right line
- Scrolling and immediately clicking (or double-clicking) used to land
the caret on a line one row off from where it visibly looked like
the click was — typing then added text to the "wrong" line, which
was confusing. The cause: the highlight overlay'sscrollTopwas
synced to the textarea via a rAF loop, which catches up on the NEXT
frame after the scroll. If you clicked inside that 16-ms window, the
textarea had already placed the caret at the new position but the
overlay was still painting the old one, so the visible glyph at the
click coordinate didn't match the textarea's text-position mapping. - Replaced the rAF loop with a synchronous
onScrollhandler on the
textarea. The overlay's scrollTop is now updated in the same turn
as the scroll event, so the two layers stay in lockstep and clicks
always land where the user expects. Also frees the main thread from
a 60 Hz rAF callback that was firing whether the editor was idle or
not.
Improved — Smaller per-keystroke recompute
updateCursorPositionran twice per keystroke (selectionchange AND
keyup both fire). The downstream setStates already bailed via
Object.is, but the substring + split work itself ran twice. Now
caches the last reported (start, end) range and short-circuits at
the top when nothing's moved.
Improved — Cold start and runtime performance
- Bundle main chunk: 1.08 MB → 282 kB (~74% smaller). Welcome screen no
longer ships the markdown rendering pipeline, jspdf/html2canvas, the
command palette, settings, stats dialog, file explorer, outline panel,
shortcuts cheatsheet, or the unsaved-changes dialog. Each is its own
chunk, fetched the moment its surface mounts.vite manualChunks
groups React and the markdown stack into stable vendor chunks the
WebView2 disk cache can hold across upgrades. - First file open: instant. A
requestIdleCallbackafter the welcome
screen settles starts the markdown chunk download in the background, so
by the time the user opens a file the bundle is already in cache. - Typing path: less work per keystroke. Command-palette heading scan
no longer runs on every typing pause — only while the palette is
actually open. App's per-keystrokecontent.split("\n")for
lineCountmoved into MarkdownPreview where it's actually used (one
fewer full-document scan per keystroke). StatusBar, TitleBar,
MarkdownPreview, and CodeEditor wrapped inReact.memowith stable
callbacks so caret-only re-renders bail out of reconciliation. - Highlight cache: drop LRU thrash. The CodeEditor's per-line
highlight cache used to dodelete + seton every cached line per
render to maintain LRU order — ~20 k Map mutations per keystroke on a
10 k-line file. The pruning that actually mattered ("is this line
still in the doc?") doesn't depend on order, so we just lookup-only on
hit and let the rare hard-cap fallback evict FIFO.
Added — Chemistry notation in math
- KaTeX now loads the mhchem contrib alongside the rest of the math
bundle, so\ce{...}and\pu{...}render in the preview.
This unlocks textbook-grade chemistry: balanced equations, ions,
isotopes, oxidation states, arrows, and Kröger-Vink defect notation
(e.g.$\ce{2 Fe^x_{Fe} + O^x_{O} -> 2 Fe'_{Fe} + V_{O}^{**} + 1/2 O2 ^}$).
The math-detection regex now also picks up bare\ce{/\pu{,
so chemistry-only documents trigger the lazy load even without
$delimiters. New/chemslash command inserts a starter snippet.
Improved — Book-style math typography
- Display equations are centered with proper vertical breathing room and
scroll horizontally on narrow viewports instead of overflowing the
reading column. KaTeX glyphs no longer inherit the globalcodeborder
/background, and equation tags pick up the muted-text colour for a
printed-textbook feel.
Fixed — Caret drifts off the rendered glyph after scrolling
- The CodeEditor stacks a transparent
<textarea>on top of a styled
highlight overlay; alignment relies on both layers wrapping at the
same column. Once the document grew past the viewport the textarea
sprouted a vertical scrollbar that quietly ate ~10 px of its content
area, while the overlay kept its full width. With word-wrap on, the
two layers wrapped at different columns and the caret started landing
a character or two off the rendered text after every scroll. Both
layers now reserve a fixed scrollbar gutter (scrollbar-gutter: stable),
and the overlay's own scrollbar is hidden visually so only the
textarea's remains user-facing.
Improved — Editor performance on large documents
- Typing into a 5 k+ line markdown file used to feel "sticky" because
the highlight overlay mounted every line as a<div>and React's
reconciler walked the lot on every keystroke. The overlay now
virtualizes: only the lines visible in the viewport (plus a 40-line
buffer) render, with fixed-height spacers above and below preserving
scroll-height parity with the textarea so caret alignment is intact.
Re-renders only fire when the visible window shifts by more than half
the buffer, so smooth scrolling no longer thrashes setState.
Word-wrap mode and small docs (under 400 lines) keep the previous
full-render path. Per-line wrapper styles are also hoisted to module
scope and the non-virtualized list is wrapped inReact.memoso
unchanged lines short-circuit prop diffing.
Fixed — Webview accelerator collision
- AI assist shortcut now also responds to Alt+J. On Windows, WebView2
treatsCtrl+Jas a "browser accelerator" for the built-in Downloads
UI — the page never sees the keydown, soe.preventDefault()can't
rescue it. Alt+J skips that path entirely. macOS (WKWebView) and Linux
(WebKitGTK) keepCtrl+Jworking; the cheatsheet detects the platform
and shows the right one. A capture-phasekeydownlistener also
preventDefaults Ctrl+J app-wide, so on platforms where the page does
see the event the host webview's default action is suppressed
regardless of which element is focused.
Fixed — Security
read_file/save_filerefuse documents above 50 MB. Stat happens before
the read so an oversized file fails fast with a clear "File too large"
toast instead of pulling hundreds of MB of UTF-8 into the webview while
the UI freezes.save_imagerefuses payloads above 25 MB and now enforces an extension
whitelist (png,jpg,jpeg,gif,webp,bmp,svg,
case-insensitive). A caller can no longer drop a.exe/.dll/.lnk
into the user's documents folder under cover of the markdown image-paste
flow. Tests cover the new rejections plus all whitelisted extensions.- AI requests get a 60 s wall-clock timeout (composed with the user's
existingAbortController) and the response is capped at 200 KB. A
stuck local llama.cpp or a runaway model can no longer hang the AI
bubble forever or paste megabytes of text into the editor. - Tauri CSP fur...
Paperling v1.0.26
Paperling v1.0.26
A minimal, distraction-free markdown editor.
Installation
- Windows:
.msi(recommended) or.exe(NSIS installer) - Linux:
.debor.AppImage - macOS:
.dmg
See the CHANGELOG for details.