2243 Commits
Author SHA1 Message Date
b2b41dd3ca fix: Remap internal links when duplicating a document tree (#13270)
* fix: Remap internal links when duplicating a document tree

Duplicating a document tree now assigns the identifiers of every duplicate
before any content is written, so links and mentions between the documents
being duplicated point at the copies rather than the originals.

* fix: Remap fully qualified links when duplicating a document tree

Links written as a full url to this installation are now remapped alongside
relative ones, and stay fully qualified. Where a link is displayed as its own
url the text is updated to match.

Also trims surrounding whitespace in sanitizeUrl, which otherwise failed
validation and prepended a second scheme to an already qualified url.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: Remap links across trees when duplicating a collection

The collection duplication task duplicated each root document separately, so
only links within a single tree were remapped. It now duplicates the whole
collection as one unit, with identifiers assigned across every tree before any
content is written.

* fix: Match document links by identifier rather than host when duplicating

An installation can be reached through more than one host, so comparing a
link's host against the configured url left fully qualified links to a
document in the duplicated set unmapped. The document a link identifies now
decides whether it is replaced, and the host it was written with is kept.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 22:44:06 -04:00
000f2f98fb feat: Add TextPack (.textpack) support (#13235)
* feat: Add TextPack (.textpack) import support

Adds a single-document importer for TextPack, the zipped variant of
TextBundle used by Bear, Ulysses, iA Writer and others. Bare .textbundle
directories are not supported, as a directory cannot be delivered through
a browser file input.

The bundle's text entry may use any extension, per the spec, with
info.json's type deciding whether it can be read as markdown. Assets are
inlined as data URIs for the existing attachment pipeline to pick up,
bounded by the attachment size limit and a memory ceiling, and only for
media types markdown-it accepts as a link destination.

Also fixes an existing bug where a file embedded in an HTML or email
import as a data URI was stored in the document as base64 rather than
being uploaded as an attachment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Refactor to individual converters

* refactor

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 20:42:05 -04:00
Tom MoorandGitHub d6d11171c3 Rename Members -> Users (#13262) 2026-08-02 14:46:20 -04:00
e5170b75b0 fix: Show roles as a selection list in the user role menu (#13260)
The user role submenu labelled each item "Promote to…" or "Demote to…"
depending on the target user's current role, and hid the role they
already had. Show the plain role names with a checkmark against the
current one, matching the group member role menu.


Claude-Session: https://claude.ai/code/session_01LfzcABi86HH7n6j9QrY4po

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-02 14:07:16 -04:00
73f960a544 fix: Invalid sort comparator for frequently used items (#13258)
* fix: Invalid sort comparator for frequently used items (#13241)

Extracts frequency tracking for icons, emojis, and code languages into a
shared FrequencyTracker with a spec-compliant, stable sort.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Snapshot frequently used icons while picker is open

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Sync frequent custom emojis to tracked ids, preserving order

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 08:43:28 -04:00
4bb422425c fix: Bound plain text cache in command bar search index (#13252)
* fix: Bound plain text cache in command bar search index

Adds a shared LRUCache utility with optional sessionStorage persistence
and uses it for the command bar plain text cache, which previously grew
without limit, and for the Mermaid diagram cache, which had its own
bespoke LRU implementation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: Avoid double lookup in LRUCache.get

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: Read persisted LRUCache values lazily

Hydration now loads only the key index, reading each value from storage
on first access. This avoids a synchronous read and parse of the entire
cache on first use, and keeps in memory only the entries the session
actually touches.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: Assert lazy LRUCache reads without a storage spy

Spying on Storage.prototype missed the calls under Node 26, where a
native Storage global shadows the jsdom one. Replacing the stored value
after hydration asserts the same behavior independently of environment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 07:56:28 -04:00
Tom MoorandGitHub efc68de4a0 fix: error id guards break for non-Error throwables (#13250)
Widen the narrowed instanceof Error checks introduced in the TypeScript 6
upgrade with a shared errToId helper that accepts any object carrying a
string id, restoring the login email-matching recovery path.
2026-08-02 07:19:24 -04:00
Tom MoorandGitHub 890f0451a8 feat: Multi-select documents (#13041)
* first pass

* refactor

* refactor

* wip

* Fix BatchableApiMethods docs; remove ApiClient batch test

* Refactor actions

* refactor batch send to share error code handling

* Remove multi-select from read-only
Refactor performBatch to common

* refactor
2026-08-01 20:45:20 -04:00
Tom MoorandGitHub 8bcf4a43a7 Add control to collapse pinned docs (#13233)
* Add control to collapse pinned docs

* feedback
2026-08-01 20:36:12 -04:00
13b9b2c62d feat: Add support for web page and eml import (#13229)
* feat: Add support for web page and email import

* fix: Type mailparser result explicitly

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Combine HTML and Web Page

* fix: Validate mime type before inlining MIME archive parts

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 18:30:06 -04:00
Tom MoorandGitHub 93638564cf feat: Adds user profile cards on hover (#13230)
* wip

* Add option to suppress hover card
2026-08-01 18:12:09 -04:00
8b35f7bd17 feat: Import file dialog (#13228)
* feat: Replace import document file picker with a modal

Choosing "Import document" now opens a dialog that lists the supported
file formats with an icon for each, and accepts files either dropped onto
it or chosen with the system file picker.

Also closes the gaps between the formats the dialog advertises and those
the importer actually accepts:

- `.tsv` was offered by the file picker but rejected by the server, it is
  now converted to a table like CSV
- `.csv` and `.htm` are now recognised by extension, so they still import
  when the browser reports an unhelpful mime type
- `.markdown` is now offered by the file picker, it was already supported

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dj1UnjnRX336CQcdzw3ott

* Add intermediate dialog for file import

* tweaks, polish

* Update failure message

* test

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-01 17:46:47 -04:00
Tom MoorandGitHub f5b39aba8f fix: CMD-Enter in table within toggle block does not add row (#13226)
* fix: CMD-Enter in table within toggle block does not add newline

* simplify
2026-08-01 16:15:40 +00:00
Translate-O-TronandGitHub d949199aee New Crowdin updates (#13218)
* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Romanian translations

* fix: New French translations

* fix: New Spanish translations

* fix: New Catalan translations

* fix: New Czech translations

* fix: New Danish translations

* fix: New German translations

* fix: New Hebrew translations

* fix: New Hungarian translations

* fix: New Italian translations

* fix: New Japanese translations

* fix: New Korean translations

* fix: New Dutch translations

* fix: New Polish translations

* fix: New Portuguese translations

* fix: New Swedish translations

* fix: New Turkish translations

* fix: New Ukrainian translations

* fix: New Chinese Simplified translations

* fix: New Chinese Traditional translations

* fix: New Vietnamese translations

* fix: New Portuguese, Brazilian translations

* fix: New Indonesian translations

* fix: New Persian translations

* fix: New Thai translations

* fix: New English, United Kingdom translations

* fix: New Norwegian Bokmal translations

* fix: New French translations

* fix: New Romanian translations

* fix: New Spanish translations

* fix: New Catalan translations

* fix: New Czech translations

* fix: New Danish translations

* fix: New German translations

* fix: New Hebrew translations

* fix: New Hungarian translations

* fix: New Italian translations

* fix: New Japanese translations

* fix: New Korean translations

* fix: New Dutch translations

* fix: New Polish translations

* fix: New Portuguese translations

* fix: New Swedish translations

* fix: New Turkish translations

* fix: New Ukrainian translations

* fix: New Chinese Simplified translations

* fix: New Chinese Traditional translations

* fix: New Vietnamese translations

* fix: New Portuguese, Brazilian translations

* fix: New Indonesian translations

* fix: New Persian translations

* fix: New Thai translations

* fix: New Norwegian Bokmal translations
2026-08-01 11:48:20 -04:00
Tom MoorandGitHub bb520666ba Add time support to date mentions (#13222) 2026-08-01 11:47:46 -04:00
Tom MoorandGitHub eb88df4825 Add Danish and Indonesian to the language options (#13221) 2026-08-01 10:26:54 -04:00
Tom MoorandGitHub 3b6a3f45e3 Add contextual menu to group table (#13220)
* Add contextual menu to group table

* feedback
2026-08-01 12:15:23 +00:00
Tom MoorandGitHub e6908c1511 feat: Inline read-only comments (#13209)
* feat: Inline read-only comments

* Improve anchor disambiguation

* fix: Spurious edits from inline comments
2026-08-01 08:08:52 -04:00
Translate-O-TronandGitHub bc4073a797 New Crowdin updates (#13216)
* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Romanian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New English, United Kingdom translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Catalan translations from Crowdin [ci skip]

* fix: New Czech translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Hungarian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
2026-08-01 07:25:13 -04:00
Tom MoorandGitHub 9264db2ce1 fix: Restore v3 i18n (#13215) 2026-07-31 21:43:59 -04:00
Tom MoorandGitHub 17accab55a fix: Strip comments for diffing (#13212)
* fix: Strip comments for diffing

* feedback
2026-07-31 08:03:16 -04:00
Tom MoorandGitHub 9a50a980f8 Update CSRF handling to set secure host-bound where possible (#13203) 2026-07-30 17:27:11 -04:00
Tom MoorandGitHub ade792f709 feat: Add ability to duplicate collection (#13197)
* feat: Add ability to duplicate collection

* Add confirmation dialog
2026-07-29 21:28:59 -04:00
Tom MoorandGitHub f228714c7a fix: googletagmanager not included in CSP unless enabled through env (#13195)
* fix: googletagmanager not incuded in CSP unless enabled through ENV

* Remove other points of CSP surgery, hey it proves the value of the refactor
2026-07-29 20:48:37 -04:00
Tom MoorandGitHub f78f285ec0 feat: Improve keyboard shortcuts guide ally (#13193)
* fix: Ally for keyboard shortcut guide

* Remove translations

* feedback
2026-07-29 19:17:11 -04:00
Tom MoorandGitHub f84ca3b9c3 Display model title in dialog header (#13196)
* Display model title in dialogs

* feedback
2026-07-29 19:12:24 -04:00
Tom MoorandGitHub a9d31d3882 feat: Add color swatch hover card (#13192)
* feat: Add color swatch hover card

* refactor
2026-07-29 18:09:17 -04:00
Tom MoorandGitHub 7bc6a3ca79 Add rubber-banding to sidebar resize (#13188)
* Add rubber-banding to sidebar resize

* refactor
2026-07-28 21:08:09 -04:00
82419bbb0f fix: Don't report failed dimension loading to Sentry (#13185)
Image and video dimension loading failures now warn and resolve undefined
rather than rejecting, which surfaced as unhandled errors in Sentry.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-28 17:59:18 -04:00
5ff3020318 fix: Crash when two mermaid diagrams are adjacent (#13173)
* fix: Crash when two mermaid diagrams are adjacent

A diagram's widget decoration sits at the end of its code block, which is
also the start position of the following block. When the next block is also
a mermaid diagram and has no decoration of its own yet, it adopted the
preceding diagram's renderer — and so its single DOM element — leaving two
widget decorations sharing one node and crashing prosemirror-view.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Enter with mermaid selection deletes node

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-28 08:58:01 -04:00
Tom MoorandGitHub c5f9646337 Icon picker glow-up (#13177)
* Icon panel glow-up

* Move colorPalette to shared/constants
2026-07-28 08:47:09 -04:00
Tom MoorandGitHub b377c2cf96 Allow pasting on images to replace in editor (#13178)
* Allow pasting on images to replace in editor

* feedback
2026-07-28 08:20:33 -04:00
Tom MoorandGitHub f97523f0b0 Add days until expiry to export email (#13175) 2026-07-27 21:43:35 -04:00
Tom MoorandGitHub 5befd94fb8 perf: Fix streaming file outputs passthrough (#13153)
* perf: Fix streaming file outputs passthrough correctly

* test
2026-07-27 18:23:51 -04:00
Tom MoorandGitHub 86335325e8 fix: attachments.redirect should be considered in read scope. (#13155)
closes #13152
2026-07-27 17:43:06 -04:00
Tom MoorandGitHub 6268bc149a fix: Add missing zod schema check for incoming document.text (#13143)
* fix: Add missing zod schema check for incoming document.text

* feedback

* test
2026-07-26 08:25:25 -04:00
e1c906a1c2 feat: Fuse powered local content search (#13115)
* wip

* generalize

* refactor

* Extract SearchResultIcon for command bar results

Both search action builders rendered the same document icon inline. Move it
into a shared component alongside the other command bar pieces, forwarding
size so the command bar can continue to size icons via cloneElement.

Also drop the redundant charAt(0).toUpperCase() on the initial, as the Icon
component already normalizes it.

Co-Authored-By: Claude <noreply@anthropic.com>

* PR feedback
Prevent same doc showing twice in cmd k
Improve result ordering in main app command bar
Refactor to flattenTree

* Upgrade Fuse to 7.5.0, use workers

* fix: Re-register search actions when index is enriched

Include result contexts in the command bar registration key so that
snippets refresh when the same documents are enriched, and only mark a
server search as cached once its results are actually fed to the index.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-25 13:16:53 -04:00
62a2220a48 fix: preserve diagrams.net source through API markdown round-trip (#13082)
* fix: preserve diagrams.net source through API markdown round-trip

Images with source: "diagrams.net" (draw.io embeds) lost their editability
when updated through the API (documents.create/update with text). The
markdown serializer/deserializer had no slot for the source attribute, so
every round-trip through markdown stripped it, downgrading editable diagrams
to static images.

Encode source as a "source=<value>" token in the markdown title attribute,
which already carries layoutClass and size. The token is extracted on parse
and emitted on serialize, surviving the full API round-trip.

* fix: address image source review feedback

Authored-by: Terminus (AI Assistant) <raisalpwardana+terminus@gmail.com>

* fix: narrow image test node attributes

Authored-by: Terminus (AI Assistant) <raisalpwardana+terminus@gmail.com>

* fix: narrow image test attributes

Authored-by: Terminus (AI Assistant) <raisalpwardana+terminus@gmail.com>

---------

Co-authored-by: Raisal P Wardana <IEatCodeDaily@users.noreply.github.com>
2026-07-25 12:36:07 -04:00
8192bc0514 chore: Audit and move inline actions to definitions (#13133)
* chore: Audit and move inline actions to definitions

* fix: Reuse existing smart-quote translation key in emoji delete dialog

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove two usages of 'Link copied' translation

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-25 16:13:12 +00:00
Tom MoorandGitHub 08a3b64295 chore: Exhaustive deps warning -> error (#13124)
* chore: Exhaustive deps turned to error

* Refactor useDragResize

* Refactor Lightbox to explicit state machine

* feedback

* ci
2026-07-25 10:43:49 -04:00
Tom MoorandGitHub d63372694b chore: More lint warnings -> errors (#13122) 2026-07-25 07:56:13 -04:00
Tom MoorandGitHub 87a4a40939 Remove ReactDOM from toDOM server rendering (#13109) 2026-07-23 20:06:27 -04:00
Tom MoorandGitHub 9884e0379f perf: Memory usage fixes (#13101)
* fix: Module level cache in headingToSlug

* fix: Remove retained full User and Team model on every ws connection

* feedback
2026-07-23 08:14:35 -04:00
Tom MoorandGitHub 55fa306838 fix: Spuriously removed edit string (#13097)
closes #13096
2026-07-22 20:23:21 -04:00
Tom MoorandGitHub b1d2fb986f chore: Address 11 lint warnings (#13092) 2026-07-21 23:07:10 -04:00
Tom Moor bc898c40c8 fix: Format number for locale on imports listing 2026-07-21 21:13:04 -04:00
Tom MoorandGitHub 19f77b8fa8 fix: OOM on large markdown imports (#13086)
fix: Markdown import does no truncate titles
2026-07-21 20:39:31 -04:00
okxintandGitHub 1c556cfe3b fix: allow read-scoped API tokens to call collection membership endpoints (#13057)
collections.memberships and collections.group_memberships both authorize
with read permission, but methodToScope was missing entries for
"memberships" and "group_memberships", causing them to default to
Scope.Write. Read-scoped tokens could not list collection members.
2026-07-20 19:25:29 -04:00
Tom MoorandGitHub d57db81c6b feat: Split view (#13044)
Adds the ability to open a second route alongside the current one:

- The secondary route is stored in a `split` query string parameter so
  that reloading the page hydrates both panes.
- The secondary pane runs in its own in-memory router kept in sync with
  the query parameter, so links followed inside the pane navigate the
  pane rather than the primary route.
- Navigation while a split is open preserves the split, is directed to
  the focused pane, and routes that cannot render in a pane (such as
  settings) close the split.
- The focused pane is shown with an accent outline, updated as panes are
  clicked or focused, and keyboard shortcuts only apply to the focused
  pane.
- "Open in split view" added to document and collection menus and the
  command bar.
2026-07-19 11:57:33 -04:00
7d3e6591c2 feat: Add onNotice callback to decouple shared editor from toast library (#13046)
* feat: Add onNotice callback to decouple shared editor from toast library

Shared editor code called sonner's toast directly. Introduce an onNotice
callback (defaulting to a toast) so the shared editor stays agnostic of the
host app's notification library.

* Add lint rule to prevent regression

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 08:56:35 -04:00