Commit Graph

51 Commits

Author SHA1 Message Date
agent_coder 6190de14cc fix(editor): let short wrong-layout prefixes match by title (#283)
The #285 gate dropped every remapped (wrong-layout) candidate shorter than 3
chars, which broke the legitimate short prefix '/сщ' -> 'co' -> Code while '/co'
still worked. Replace the blanket length filter with a match-TYPE gate: the
original query and remaps >= 3 chars match fully (title/description/searchTerms);
a short (1-2 char) remap is restricted to a TITLE fuzzy-match. So '/сщ' -> 'co'
matches the 'Code' title again, while '/cy' -> 'сн' and '/b' -> 'и' still do not
surface Footnote (they only ever leaked in via the 'сноска'/'примечание'
searchTerm substrings, not the title).

Adds positive tests for /сщ and /co; keeps the /cy and /b negatives.

closes #283

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 14:09:36 +03:00
agent_coder d34b5f532f fix(#283 review r3): drop dead remap guard + use relative test import
F4: menu-items.layout.test.ts imports from './menu-items' (relative, no extension),
matching the sibling test files (was still the aliased '@/.../menu-items.ts').
F5: remove the dead 'candidate !== originalCandidate' clause from the remapped-candidate
filter — buildLayoutCandidates dedupes remaps against the original via Set, so the tail
after destructuring can never equal the original; the length gate is the only real
condition. Comment updated to state the dedup invariant instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 08:16:08 +03:00
agent_coder 0f4b03d89f fix(#283 review r2): gate remapped layout candidates against short-query over-match
This actually lands F1+F2 (round 1 pushed only the test rename by mistake).

F1: only the ORIGINAL query matches without length limits; remapped (wrong-layout)
candidates must be >= 3 chars before they can match, via a shared candidateMatchesItem
helper applied to both the item filter and the tie-break sort. Stops a 1-2 char ASCII
query from spuriously substring-matching Cyrillic searchTerms (/cy->сн no longer hits
'сноска', /b->и no longer hits 'примечание'), while keeping real wrong-layout commands
(/сщву->Code, /cyjcrf->Footnote), genuine short queries (/p, /h1) and Cyrillic terms
(/сноска->Footnote) working.
F2: reword the buildLayoutCandidates JSDoc (an ASCII query yields multiple candidates;
dedup only collapses when nothing is remappable).

Adds negative tests for /cy and /b.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 07:42:08 +03:00
agent_coder d70b80c449 fix(#283 review): gate remapped layout candidates to avoid short-query over-match
F1: only the ORIGINAL query does full matching; remapped (wrong-layout) candidates
must be >= 3 chars and differ from the original before they can match (via a shared
candidateMatchesItem helper, applied to both the filter and the tie-break sort). This
stops a short remapped candidate from substring-matching the only cyrillic searchTerms
(/cy->сн, /b->и no longer surface Footnote) while keeping real wrong-layout commands
(/сщву->Code, /cyjcrf->Footnote) and genuine cyrillic terms (/сноска->Footnote) working.
F2: fix the buildLayoutCandidates JSDoc (an ascii query yields multiple candidates,
not a single-element set).
F3: rename the test to menu-items.layout.test.ts + relative import, per sibling convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 07:00:35 +03:00
agent_coder 5f02b7c80e fix(editor): match slash-menu commands typed in the wrong keyboard layout (closes #283)
Typing a command with the wrong layout (e.g. Russian ЙЦУКЕН -> /сщву for 'code')
matched nothing and collapsed the popup. Add ЙЦУКЕН<->QWERTY layout maps and a
buildLayoutCandidates(query) = [original, RU->EN, EN->RU]; getSuggestionItems now
matches an item if ANY candidate hits (fuzzy title / description / searchTerms),
and the tie-break sort is candidate-aware. Keeping the original among candidates
preserves genuine Cyrillic search terms (сноска -> Footnote). One-function change;
slash-command.ts allow() reuses it, so the popup-collapse is fixed transitively.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 05:44:58 +03:00
claude code agent 227 f7b99f9fb3 feat(editor): recursive tree mode for the subpages node (#150)
The `subpages` node showed only one level of direct children. Add a `recursive`
attribute that renders the FULL descendant tree of the current page — fully
expanded, unlimited depth. Default `false`, so every previously-inserted node
stays flat (backward compatible). No backend changes: `POST /pages/tree` (via the
`getSpaceTree` wrapper) already returns the whole subtree as a flat `IPage[]`
(recursive CTE, permission-filtered); the nested tree is built on the client by
`parentPageId`.

- editor-ext `subpages.ts`: `recursive` attribute (parse/render `data-recursive`),
  shared by client + server so the collab ProseMirror schema keeps the attribute.
- `getSpaceTree`: arg loosened to `{ spaceId?; pageId? }` (the endpoint accepts
  either); new `useGetPageTreeQuery(pageId)` react-query hook.
- `subpages-view.tsx`: split into `FlatSubpages` (unchanged) and
  `RecursiveSubpages`; `buildSubtree` assembles the nested tree (cycle/self-parent
  guard, `sortPositionKeys` per level, root excluded) and a recursive `TreeNode`
  renders it (16px indent per depth, soft "showing N" note past 300 — data never
  capped). Shared/public context reads the already-nested shared tree, no
  `/pages/tree` request.
- toggles: bubble-menu flat⇄tree button + a second slash-menu item "Page tree".

Review follow-ups folded in: invalidate `["page-tree"]` from the create / update /
move / delete cache helpers so an open recursive tree refreshes (no stale data);
mode icon made reactive on editor transactions; `t` threaded into `TreeNode`
(no per-node useTranslation); shared-subtree hook deduped to a thin alias.

editor-ext build + client `tsc --noEmit` both clean. Backend untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 14:33:07 +03:00
claude code agent 227 9e1d057878 fix(qa): resolve QA-pass issues #122–#134
Batch of fixes from the automated QA pass on develop. Each was reproduced and
then verified fixed live (browser/curl); logic-bearing fixes have unit tests.

Functional bugs:
- #122 collab-token was capped by the anonymous public-share-AI throttler (5/min);
  skip all non-AUTH named throttlers on this auth-guarded, client-cached route.
- #123 editor onAuthenticationFailed threw `jwtDecode(undefined)` and never
  reconnected; read the token via a ref, guard the decode (incl. missing exp),
  and refetch+reconnect on any auth failure.
- #124 a slash command containing a space ("/Heading 1") inserted literal text;
  enable allowSpaces and close the menu when the query matches no items.
- #125 space slug auto-gen produced uppercase initials for multi-word names;
  computeSpaceSlug now yields a lowercase alphanumeric slug.
- #126 AI chat window position/size now persisted (atomWithStorage) across reload;
  also fixes a latent ResizeObserver-attach bug on first open.
- #127 workspace name update accepted URLs; add @NoUrls (parity with setup).
- #132 icon-columns 4/5 passed calc() into SVG width/height attrs (console spam);
  size via style. share-for-page query returns null instead of undefined.
- #134 "Reindex now" counter looked stuck: reindex runs async; the client now
  polls coverage (bounded) so the counter climbs live; misleading server comment
  reworded.

UX / consistency:
- #128 add success toasts to favorite/label/avatar/member-(de)activate.
- #129 "1 result found" pluralization; hide the single-option Type filter.
- #130 replace raw Zod strings with friendly messages (name/password/group).
- #131 unify "Untitled" casing in tree/breadcrumb/tab; stop force-uppercasing
  space-name chips; fix confirm-dialog labels (Cancel / Remove), invite
  placeholder typo, Export/Move-to-space labels.
- #133 disable profile Save when clean; toast on unsupported avatar image;
  style the invalid-invitation page with a CTA; hide Share for read-only users;
  align the dictation "not configured" message; "Go to login page" typo.

Tests: computeSpaceSlug, workspace-name NoUrls DTO, share-query null
normalization, slash getSuggestionItems empty-close.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 20:47:40 +03:00
claude_code 3d4ad664b3 test(refactor-tail): extract pure cores + cover collab/share/ai-chat/client gate
Batches 6-9: behaviour-preserving extractions of testable pure cores plus the
tests they unblock, and a fix for the broken client test environment.
Full suites green: server 113 suites / 1117 + 1 todo, client 30 files / 338.

client (R0 infra):
- vitest.setup.ts: in-memory localStorage/sessionStorage Storage stub wired via
  setupFiles. Unblocks menu-items.gating.test.ts (was 9 failing) -> client suite
  fully green. + menu-items.suggestions.test.ts (getSuggestionItems filter/sort).

share:
- extract buildShareMetaHtml (share-seo.util.ts) from the SEO controller; tests
  for reflected-XSS escaping in <title>/og/twitter meta, noindex, truncation;
  extractPageSlugId; updateAttachmentAttr; prepareContentForShare comment-strip
  (anonymous-viewer metadata-leak guard).

ai-chat (security extractions):
- selectAccessibleHits: CASL post-filter for semantic search (restricted page in
  an accessible space must NOT leak to the agent).
- validateResolvedAddresses: SSRF connect-time guard (block if ANY resolved
  address is private).
- resolveAudioFormat: mime whitelist (dead `?? 'webm'` fallback dropped, set
  unchanged). + mcp-servers toView header-leak guard, MCP tool namespacing.

collaboration (data-loss area):
- extract computeHistoryJob (pins the "agent delay MUST stay 0" invariant) and
  resolveSource. Integration: onAuthenticate read-only matrix (collab auth
  bypass), HistoryProcessor (contributor restore on save failure), onStoreDocument
  Approach-A boundary snapshot (human revision pinned before agent overwrite).

Reviewed (APPROVE WITH SUGGESTIONS): extractions behaviour-preserving, security
tests mutation-resistant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:10:27 +03:00
claude code agent 227 9797751b0a test(html-embed): cover slash-menu gating of the HTML embed item (#98)
Export + test isHtmlEmbedFeatureEnabled: the 'HTML embed' slash item is hidden by
default / when the toggle is off / on broken localStorage (no throw), shown only
when the workspace toggle is exactly true.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 05:52:15 +03:00
claude_code 81823fce1e feat(html-embed): sandbox the embed block; split trusted trackers into an admin field
Convert the htmlEmbed node from same-origin raw-HTML execution to a sandboxed
iframe (sandbox="allow-scripts allow-popups allow-forms", no allow-same-origin,
srcdoc) with postMessage auto-resize (validated by event.source) and an optional
manual height attr. The block now runs in an opaque origin and cannot reach the
viewer's cookies/session/API, so it is safe for any member.

Because the block is now harmless, remove the entire admin/role gating apparatus:
drop htmlEmbedAllowed/canAuthorHtmlEmbed/stripDisallowedHtmlEmbedNodes/
collectHtmlEmbedSources and every role-based strip on the write paths (collab
REST/MCP + socket, page create/duplicate, import x2, transclusion unsync), along
with the now-unused WorkspaceRepo/UserRepo injections and the PageService.create
callerRole param. Keep one strip: prepareContentForShare still removes htmlEmbed
on the anonymous public-share read path when the workspace master toggle is OFF.

The workspace settings.htmlEmbed toggle is now a plain feature switch (gates the
slash-menu and share rendering); when ON the block is available to all members.

Add settings.trackerHead: an admin-only raw HTML/JS analytics snippet injected
verbatim into the <head> of public share pages only (ShareSeoController), for
trackers that genuinely need same-origin. Admin-gated via the existing CASL
Manage/Settings ability; never injected into the authenticated app shell.

Closes security-review findings #1, #2, #4, #5, #10 (and #3 as a security issue).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 02:48:41 +03:00
claude_code c5f44a6eee Merge branch 'develop' into feat/footnotes
Resolve conflicts at shared registration points by unioning both features
(footnotes + the already-merged html-embed / page-embed work):
- slash-menu/menu-items.ts, editor extensions.ts: keep both imports + configures
- collaboration.util.ts: register footnote nodes and pageEmbed
- editor-ext marked.utils.ts: register footnote + html-embed markdown extensions
- editor-ext package.json/tsconfig.json/vitest.config.ts: union of test config
  (jsdom env for footnote DOM tests + combined test/spec include glob)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:21:07 +03:00
claude_code 19ae6a0efa Merge pull request 'feat(editor): page templates — live whole-page embed (MVP)' (#17) from feat/page-templates into develop
Develop / build (push) Has been cancelled
2026-06-20 20:34:44 +03:00
claude code agent 227 8fcce6a674 feat(html-embed): per-workspace feature toggle, default OFF
The admin-only raw HTML/JS embed is a deliberate stored-XSS surface, so gate the
whole feature behind a workspace toggle that is OFF by default; it only works
when a workspace admin explicitly enables it.

- settings.htmlEmbed (boolean, default false) + workspace-update field htmlEmbed,
  persisted via WorkspaceRepo.updateSetting with an audit diff. Flipping it is
  admin-only (same Manage Settings CASL as other workspace toggles).
- New gate htmlEmbedAllowed(featureEnabled, role) = featureEnabled && admin/owner.
  All 7 server write paths (create, duplicate, collab onStoreDocument, REST/MCP/AI
  updatePageContent, single + zip import, transclusion unsync) now read the
  workspace's settings.htmlEmbed and strip unless (toggle ON AND admin). OFF
  (default, or a failed/empty workspace lookup) strips htmlEmbed for EVERYONE
  including admins -> existing embeds are cleaned up on next save, none persist.
- Client (defense-in-depth): the /html slash item is hidden unless toggle ON +
  admin; the NodeView executes nothing and shows a 'disabled in this workspace'
  placeholder when OFF; an admin Switch in Workspace Settings -> General with a
  description of the behavior.
- docs/html-embed-admin.md documents the toggle + admin-only + fail-closed
  coedit (a non-admin save strips an admin's embed) + execution semantics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 19:28:39 +03:00
claude code agent 227 4d17befb0d feat(editor): footnotes (reference + definitions model)
Adds footnotes: a superscript marker in the text linked to an editable
definition in a Footnotes section at the end of the page, with auto-numbering
and a read-only hover popover. Chose the reference+definitions model (3 plain
nodes) over an inline atom with a sub-editor specifically for collaboration
safety.

editor-ext (packages/editor-ext/src/lib/footnote/):
- footnoteReference (inline atom, id), footnotesList (block, last child),
  footnoteDefinition (paragraph+, id). renderHTML emits sup[data-footnote-ref]
  / section[data-footnotes] / div[data-footnote-def]; parse-rule priority makes
  the empty reference win over the Superscript mark (else it is dropped on the
  server save).
- numbering: a decoration-only plugin (pure function of doc order) -> every
  client computes identical numbers, no document mutation, Yjs-safe.
- sync plugin: single-pass, always SYNC_META-tagged and skipping remote txns
  (terminates, no loop), idempotent; canonicalizes to one trailing footnotesList
  (merging duplicates), creates missing definitions, drops orphans, and
  coexists with TrailingNode. Disabled in read-only.
- commands setFootnote (one tx: reference + definition at the matching index +
  focus) / removeFootnote (cascade, one undo) / scrollTo*. slash /footnote.

client: superscript NodeView + floating-ui read-only popover; bottom-list and
definition NodeViews; registered in mainExtensions.

server: the three nodes registered in tiptapExtensions so collab/save/export
keep them. Round-trip regression spec guards the Superscript parse-priority.

markdown: turndown/marked round-trip to pandoc/GFM [^id] (+ a code-fence guard
so footnote-like lines inside code blocks are not extracted).

MCP mirror: schema + markdown-converter + commentsToFootnotes rewritten to real
footnote nodes + diff marker counting; NUL sentinels written as \u0000 escapes.

v2 follow-ups (per plan): definition reordering on reference move, id-collision
regeneration on paste, multiple references to one footnote.

Implements docs/footnotes-plan.md (variant B).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:39:00 +03:00
claude code agent 227 39ae89264d feat(editor): page templates - live whole-page embed (MVP)
Embed another page's LIVE content into a host page (it updates when the source
changes, not a static copy). A page can be flagged a template for discovery in
the picker; any accessible page can be embedded.

Server:
- migrations: pages.is_template (+ partial index) and page_template_references
  (whole-page back-refs); db.d.ts/entity types hand-merged (db.d.ts is curated).
- POST /pages/toggle-template (CASL Edit) flips is_template; is_template is
  returned by findById + the sidebar tree select so the tree menu label
  reflects state. Search suggestions gain an onlyTemplates filter for the picker.
- POST /pages/template/lookup ({sourcePageIds[]}, <=50): returns each accessible
  source's {title, icon, slugId, content, sourceUpdatedAt} with comment marks
  stripped (same access path as transclusion: filterViewerAccessiblePageIds;
  inaccessible -> no_access, missing -> not_found; error path -> not_found, never
  raw content).
- reference sync (collectPageEmbedsFromPmJson + syncPageTemplateReferences) on
  the Yjs save hook; duplicatePage remaps pageEmbed.sourcePageId + inserts refs.
  Known MVP gap: REST content updates don't resync refs (lookup uses in-doc ids).

Client:
- pageEmbed node (editor-ext, registered in BOTH client + server schemas);
  read-only NodeView with a batching lookup; '/Embed page' slash + template
  picker (self-embed prevented); 'Make/Unset template' in the tree node menu.
- Cycle guard: an ancestry-chain context + depth cap (5) render a 'circular
  embed' placeholder instead of recursing.
- Public shares show a placeholder (no public lookup in MVP).

MVP excludes (follow-ups): public-share lookup, unsync->static copy, server-side
expansion for export/RAG, MCP schema mirror, point-in-time snapshots.

Implements docs/page-templates-plan.md (MVP, variant A).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 10:05:00 +03:00
claude code agent 227 bd28dbfe2b feat(editor): admin-only raw HTML/CSS/JS embed node
Adds an htmlEmbed block node that renders and executes raw HTML/CSS/JS in the
wiki origin (e.g. an analytics tracker) — the owner-chosen variant C. Because
this is stored-XSS by design, only workspace admins/owners may get such a node
persisted; everyone executes it when reading.

- Node (editor-ext): htmlEmbed atom/isolating block; source stored base64 in
  data-source for lossless HTML<->JSON round-trip. renderHTML emits only the
  encoded marker (never inlines raw markup), so generateHTML/export/search are
  not themselves injection vectors. Registered in BOTH client extensions and
  server tiptapExtensions. Markdown round-trip via an <!--html-embed:b64-->
  comment (turndown) + a marked rule.
- Client NodeView: injects source and re-creates <script> elements so they
  actually run; edit modal; renders in read-only/share too. Slash item is
  admin-gated (adminOnly filtered by the user's workspace role).
- SERVER ENFORCEMENT (the real control — UI gating alone is insufficient):
  stripHtmlEmbedNodes() removes htmlEmbed from any document persisted by a
  non-admin, applied at every write path that introduces content from an
  untrusted author: collab onStoreDocument, REST/MCP/AI updatePageContent,
  single-file import, zip/multi-file import, page duplication, and transclusion
  unsync. Page restore introduces no new content. Public share/readonly viewers
  render fetched (already-stripped) content and do NOT open a collab socket, so
  the only residual is a transient broadcast window to concurrent authenticated
  editors (documented).

Implements docs/arbitrary-html-embed-plan.md (variant C).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 08:54:54 +03:00
Philip Okugbe 33895b0607 bug fixes (#2250)
* util

* fix page position collation

* support fixed toolbar in templates editor

* date localization

* fix clipped emoji in templates editor

* fix page updated time object

* fix flickers

* fix: remove redundant breadcrumb from destination modal
2026-05-28 16:20:37 +01:00
Philip Okugbe 92c0e36e46 fix(a11y): WCAG 2.1 AA fixes (#2219) 2026-05-20 16:47:25 +01:00
Philip Okugbe f4af4c3fc0 feat(editor): add page break node (#2202) 2026-05-14 03:48:13 +01:00
David Gallardo 6046d04375 feat(editor): replace emoji picker with browse + search (#2171)
* feat(editor): show emoji name in suggestion list

Replace the fixed-column emoji grid with a vertical list that displays
each emoji alongside its :shortcode: name. This makes the picker more
discoverable—users can see and learn shortcodes without prior knowledge.

Changes:
- EmojiList: switch from SimpleGrid/ActionIcon to UnstyledButton list
  rows showing emoji glyph + monospace 🆔 label
- Navigation simplified to ArrowUp/ArrowDown (list has no columns)
- Results capped at 8 items for a focused, scannable dropdown
- CSS module: rename menuBtn -> menuItem, tighten padding

* feat(editor): replace SearchIndex with name/id includes search

Port the exact search algorithm from the original extension:
- Build a flat index from @emoji-mart/data: { id, name (lowercase), native }
- Filter with name.includes(q) || id.includes(q) — predictable, no
  keyword indirection
- Results capped at 5 (same as extension)
- Frequently-used emojis (sorted by usage) shown when query is empty
- Remove emoji-mart init() / SearchIndex / getEmojiDataFromNative
  dependencies; index is built lazily and cached in memory
- Remove unused GRID_COLUMNS constant

* feat(editor): emoji picker with browse and search modes

When the query is empty the picker shows a category bar with 8 tabs
(people, nature, food…) and a scrollable emoji grid. Typing after ':'
switches to a compact list that shows the glyph and :shortcode: side by
side, making it easy to discover emoji names while you type.

- Category data is loaded lazily from @emoji-mart/data and cached, so
  opening the picker more than once has no overhead
- Grid keyboard nav: arrow keys move by cell/row, Enter picks
- List keyboard nav: up/down through results, Enter picks
- Mouse hover syncs the keyboard selection index in both modes
- incrementEmojiUsage tracks picks so frequently used ones bubble up
  in future sessions

* fix(editor): polish emoji picker copy and loading

* feat: add emoji to slash command

* Add keyboard support to emoji group navigation

---------

Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
2026-05-08 21:33:43 +01:00
Philip Okugbe de60aa7e61 feat: synced blocks (transclusion) (#2163)
* feat: synced blocks (transclusion)

* fix:remove name

* make placeholders smaller

* feat: enforce strict transclusion schema

* fix: scope synced blocks to workspace, gate unsync on edit permission

* fix collab module error
2026-05-08 13:23:16 +01:00
Peter Tripp c9fa6e20b3 Add alias: /toc and /ol (#2161) 2026-05-08 01:20:27 +01:00
Philip Okugbe dbe6c2d6ba feat: A11y fixes (#2148) 2026-05-04 21:21:37 +01:00
Philip Okugbe d42091ccb1 feat: favorites (#2103)
* feat: favorites and templates(ee)

* rename migrations

* fix sidebar

* cleanup tabs

* fix

* turn off templates

* cleanup

* uuid validation
2026-04-12 22:06:25 +01:00
Philip Okugbe 879aa2c3d8 feat: page update notifications (#2074)
* feat: watchers notification and email preferences

* fix: email copy

* digests

* clean up

* fix

* clean up

* move backlinks queue-up to history processor

* fix

* fix keys

* feat: group notifications

* filter

* adjust email digest window
2026-03-31 16:03:59 +01:00
Philip Okugbe 7981ef462e feat(editor): audio and PDF nodes (#2064)
* use local resizable

* feat: aduio

* support audio imports

* feat: use confluence real file names

* cleanup

* error handling

* hide notice

* add audio

* fix pulse

* Fix import and export

* unify pulse

* hide in readonly mode

* keywords

* keyword

* translations

* better sort

* feat: PDF embed

* cleanup

* remove audio menu

* open active

* hide focus on readonly mode

* increase iframe default dimension
2026-03-28 17:33:29 +00:00
Philip Okugbe ea44468fad feat: editor inline status node (#1973)
* inline status node

* fix alignment

* fix

* typed storage

* fix math block popup on select all
2026-02-27 01:34:03 +00:00
Philip Okugbe ef87210b3d feat: editor UI refresh and enhancements (#1968)
* feat: new image menu
* switch to resizable side handles
* use pixels

* refactor excalidraw and drawio menu

* support image resize undo

* video resize

* callout menu refresh

* refresh table menus

* fix color scheme

* fix: patch @tiptap/core ResizableNodeView to prevent resize sticking after mouseup

* feat: columns

* notes callout

* focus on first column

* capture tab key in column

* fix print

* hide columns menu when some nodes are focused

* fix print

* fix columns

* selective placeholder

* fix blockquote

* quote

* fix callout in columns
2026-02-24 15:22:37 +00:00
Philip Okugbe 4878850b25 fix: attachment bugs in safari(#1908)
* use widely available arrayBuffer
* fix stream fails in safari
* fix hasFocus bug
* fix safari upload bug
* feat: add HTTP range request support for file serving
2026-02-05 07:47:03 -08:00
Philip Okugbe 657fdf8cb7 feat: Tiptap V3 migration (#1854)
* Tiptap3 migration - WIP

* fix collaboration

* remove unused code

* fix flicker

* disable duplicate extensions

* update tiptap version

* Switch to useEditorState
- Set shouldRerenderOnTransaction to false

* fix editable state

* add tippyoptions for reference

* merge main

* tiptap 3.6.1

* fix bubble menu

* fix converter

* fix menus

* fix collaboration caret css

* fix: Set `isInitialized` to force immediate react node view rendering

* feat: Migrate tippy.js menus to Floating UI

* feat: Update collaboration connection for HocusPocus v3

* fix: Connect/disconnect websocketProvider

* cleanup

* cleanup

* feat: Improved placeholder and upload handling for images

* feat: Improved placeholder and upload handling for videos

* refactor: Image node and view clean-up

* feat: Improved placeholder and upload handling for attachments

* fix: Video view styles

* fix: Transaction handling on asset upload

* fix: Use imageDimensionsFromStream

* feat: Multiple file upload, improved placeholders, local previews

* fix: Drag & drop, paste upload

* fix: Allow media as attachment

* * add skeleton pulse animation
* add translation strings
* fix attachment view responsiveness

* fix collab connection status display

* Tiptap v3.17.0

* fix suggestion menu exit bug

* fix search shortcut

* fix history editor css

* tiptap 3.17.1

---------

Co-authored-by: Arek Nawo <areknawo@areknawo.com>
2026-01-24 20:41:08 +00:00
Philip Okugbe 73ee6ee8c3 feat: subpages (child pages) list node (#1462)
* feat: subpages list node

* disable user-select

* support subpages node list in public pages
2025-08-31 18:54:52 +01:00
Philip Okugbe 50b3f9ddd9 generic iframe embed (#1234) 2025-06-09 22:32:23 +01:00
fuscodev 8aa604637e feat: nested toggle block (#671)
* feat: nested toggle block

* fix: md export

* fix detailsButton icon alignment

---------

Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
2025-04-04 13:01:39 +01:00
Philip Okugbe 21c3ad0ecc feat: enhance editor uploads (#895)
* * multi-file paste support
* allow media files (image/videos) to be attachments
* insert trailing node if file placeholder is at the end of the editor

* fix video align
2025-03-15 18:27:26 +00:00
Hoie Kim 5fece5fc68 feat: google sheets embed (#615) 2025-01-11 22:22:06 +00:00
lleohao 670ee64179 Support I18n (#243)
* feat: support i18n

* feat: wip support i18n

* feat: complete space translation

* feat: complete page translation

* feat: update space translation

* feat: update workspace translation

* feat: update group translation

* feat: update workspace translation

* feat: update page translation

* feat: update user translation

* chore: update pnpm-lock

* feat: add query translation

* refactor: merge to single file

* chore: remove necessary code

* feat: save language to BE

* fix: only load current language

* feat: save language to locale column

* fix: cleanups

* add language menu to preferences page

* new translations

* translate editor

* Translate editor placeholders

* translate space selection component

---------

Co-authored-by: Philip Okugbe <phil@docmost.com>
Co-authored-by: Philip Okugbe <16838612+Philipinho@users.noreply.github.com>
2025-01-04 13:17:17 +00:00
Philip Okugbe 532001fd82 chore: fix linting (#544)
* fix: eslint (server)

* fix: eslint (client)

* commit package lock file

* fix linting
2024-12-09 14:51:31 +00:00
Philip Okugbe ab70cee278 feat: third-party embeds (#423)
* wip

* Add more providers

* icons

* unify embed providers (Youtube)

* fix case

* YT music

* remove redundant code
2024-10-29 18:13:20 +00:00
Philip Okugbe 6a3a7721be features and bug fixes (#322)
* fix page import title bug

* fix youtube embed in markdown export

* add link to rendered file html

* fix: markdown callout import

* update local generateJSON

* feat: switch spaces from sidebar

* remove unused package

* feat: editor date menu command

* fix date description

* update default locale code

* feat: add more code highlight languages
2024-09-17 15:40:49 +01:00
Philipinho 7e6a71fa2d add HR divider to slash menu 2024-09-02 01:28:15 +01:00
Philipinho 1141796f24 Show version
* Add default mermaid content
2024-09-01 17:30:34 +01:00
Philip Okugbe 87b99f8646 feat: draw.io (diagrams.net) integration (#215)
* draw.io init

* updates
2024-09-01 12:26:20 +01:00
Philip Okugbe 38e9eef2dc feat: excalidraw integration (#214)
* update tiptap version

* excalidraw init

* cleanup

* better file handling and other fixes

* use different modal to fix excalidraw cursor position issue
* see https://github.com/excalidraw/excalidraw/issues/7312
* fix websocket in vite dev mode

* WIP

* add align attribute

* fix table

* menu icons

* Render image in excalidraw html
* add size to custom SVG components

* rewrite undefined font urls
2024-08-31 19:11:07 +01:00
Philip Okugbe 7dc37b933f feat: editor file attachments (#194)
* fix current slider value

* WIP

* changes to extension attributes

* update command title
2024-08-26 12:38:47 +01:00
Philip Okugbe 7e80797e3f feat: mermaid diagram integration (#202) 2024-08-24 18:30:07 +01:00
Philipinho 3c70e40d16 add table header by default 2024-07-12 16:53:33 +01:00
SurajJadhav7 99cf6dab62 added fuzzy matching logic for menu search 2024-07-01 16:49:36 +05:30
Philipinho 1f4bd129a8 editor improvements
* add callout, youtube embed, image, video, table, detail, math
* fix attachments module
* other fixes
2024-06-20 14:57:00 +01:00
Philipinho f0fd1cfe1b css fixes 2024-04-25 01:19:50 +01:00
Philipinho 5ee74d49d7 fix tiptap editor types 2024-04-05 01:16:07 +01:00