v2.3.5
Breaking Changes
- Theme foreground token split (#217). Active and selected states no longer consume
--notectl-primary-fg; they now use the new--notectl-accent-fgtoken. CSS integrations
that override--notectl-primary-fgfor active toolbar buttons, dropdown or picker items,
or selection outlines must set--notectl-accent-fginstead.--notectl-primary-fgnow
applies only to text on solid primary backgrounds. ExistingThemeobject literals remain
source-compatible becauseaccentForegroundis optional, but the changed CSS custom-property
fallback is a behavioral breaking change.
Fixed
-
Pressing below the content inserted a paragraph on mousedown (#219). The
click-below-content handler inEditorViewEventsran onmousedown, called
preventDefault(), and never checkedevent.button. That made it impossible to start a
drag-selection from the empty area below the last block (noticeable in full-height
editors), and a middle- or right-button press appended a paragraph instead of leaving
autoscroll or the context menu alone. The handler now only records an unmodified
primary-button press below the last block, without preventing the default, and completes
the append onmouseupwhen the pointer stayed within a 4px drag threshold. Drags,
shift-extensions, modified clicks, and non-primary buttons fall through to native
behavior; a trailing empty paragraph is still reused instead of stacking new ones. -
Accepting a native spellcheck suggestion did nothing (#218).
InputHandlercancels
every handledbeforeinputevent and re-applies the change as a transaction, but the
insertReplacementTextbranch only readevent.data. On a contenteditable host,
Chromium and WebKit deliver the replacement string on the event'sdataTransfer
(text/plain) withdata === null, so picking a suggestion from the browser's context
menu (or a macOS autocorrect) inserted nothing while the native replacement was already
prevented. The handler now readsdatawith adataTransferfallback and applies the
correction to the exact word range the browser reports viagetTargetRanges(). The
static range is mapped to a model selection by the new view-layerdomRangeToState
(wired throughEditorView.resolveDOMRangeinto the input layer), so the correction
lands on the right word even when the DOM selection stays collapsed (Safari autocorrect,
Firefox context menu) and remains undoable as a regular input transaction. Three guards
harden the new branch: a replacement arriving during an active IME composition is
swallowed instead of being applied against uncommitted composition text; a reported word
range that cannot be mapped degrades to a no-op at a collapsed caret instead of
duplicating the correction next to the typo; and pending caret mark toggles (e.g. Ctrl+B
pressed before accepting the suggestion) no longer bleed into the corrected word when the
browser-reported range replaces the selection. -
Dark preset rendered solid-primary button labels invisible (#217). The dark theme
shipped the same value (#89b4fa) forprimaryandprimaryForeground, so every control
that pairsbackground: var(--notectl-primary)withcolor: var(--notectl-primary-fg)
(the formula editor's primary button, the video popup's Embed and Submit buttons, the
table size editor's Apply button) drew its label in its own background color, a 1:1
contrast ratio. Root cause:--notectl-primary-fgwas overloaded with two conflicting
roles, text on a solid primary background versus primary-tinted text on neutral
backgrounds (active toolbar buttons, dropdown and picker active items, selection
outlines). The token is now split. A newaccentForegroundprimitive
(--notectl-accent-fg) carries the accent role with the exact values those surfaces used
before (light#1a5fa0, dark#89b4fa, so they do not change visually), while
primaryForegroundkeeps its documented "text on primary background" meaning with
WCAG-AA-readable values (light#1a1a1a, 5.2:1 on#4a90d9; dark#1e1e2e, 7.8:1 on
#89b4fa). The theme engine emits--notectl-accent-fg: var(--notectl-primary-fg)for
themes compiled before the split, preserving their rendering.ThemePrimitivesgains an
optionalaccentForegroundfield, so existing fullThemeobject literals remain
source-compatible; themes created viacreateTheme()inherit it from their base
automatically;createTheme()additionally derives the omittedaccentForegroundfrom
an overriddenprimaryForeground, so themes derived from a preset before the split keep
their accent surfaces on the chosen color. The shipped custom-elements manifest documents
the new--notectl-accent-fgcustom property. -
Pasting text from Word on macOS inserted a screenshot instead of the text (#216).
Word and Excel on macOS put a bitmap rendition of the copied content on the clipboard
alongside the HTML flavor, and Chromium exposes that bitmap as a file item. The paste
pipeline dispatched file items to the registered file handlers before considering the
HTML, so the image plugin claimed the paste and inserted a picture of the copied text.
Clipboard HTML that carries real content now takes precedence over accompanying image
file items. Markup that is nothing but an image representation keeps routing to the file
handlers, so copied web images still paste through the blob-URL and upload-service path;
non-image files also retain their registered handler precedence. Precedence is an
ordering, not a verdict: when the preferred HTML turns out to parse to nothing (design
tools ship metadata-only markup next to a bitmap), the skipped image files are
dispatched after all, so such pastes insert the image instead of silently discarding
the clipboard; if no deferred file handler claims them, the captured plain-text flavor
remains the final fallback. HTML counts as parsing to nothing when it materializes only
empty paragraphs (in any number) or text made of zero-width characters; a<br>is a
content signal, so blank-line-only markup still pastes as blank lines. Contentless HTML
no longer dispatches an empty paste transaction, so a range selection is not consumed
before the deferred files run. Embedded rich clipboard metadata is likewise validated
before replacing a selected range, so an invalid rich flavor falls through without a
delete-only transaction. Markdown that converts to contentless HTML falls back to a
plain-text paste of the captured text instead of being silently dropped.
Known trade-off: a Word copy containing text plus an embedded picture pastes as the
text without the picture (the picture'sfile:///source is unreachable from the
clipboard HTML); previously such copies pasted as a single bitmap of the whole
selection.