@calternal/editor
Public Markdown and Note editor surface, including the split Card layer (DESIGN §9, #632).
Interfaces
Section titled “Interfaces”ChromeInteraction
Section titled “ChromeInteraction”Properties
Section titled “Properties”Methods
Section titled “Methods”hold()
Section titled “hold()”hold(): () =>
void
Arm (or extend) the window. Returns an idempotent release — safe to call twice (mirrors holdSelectionAssassin’s own contract; Svelte effect teardowns and pointer cleanup paths can both fire in edge cases).
Returns
Section titled “Returns”() => void
ComposerNoteDraft
Section titled “ComposerNoteDraft”Title + body a Composer text becomes.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
body |
string |
Markdown body after the H1; may be empty. |
title |
string |
Plain title (becomes the note H1, frontmatter title: and filename slug). |
ComposerNoteTarget
Section titled “ComposerNoteTarget”The event an “Add note” session is bound to.
Properties
Section titled “Properties”EditorProps
Section titled “EditorProps”Props for the standalone Svelte editor surface. Hosts own storage and choose
when to call publishMarkdown() through the component instance.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
ariaLabel |
string |
Accessible name for the Markdown surface. |
autofocus? |
boolean |
- |
bareUrlPaste? |
boolean |
Keep standalone URL paste as bare Markdown and allow immediate Undo to make a link (#1151). |
editable? |
boolean |
Mount the shared Markdown surface as a read-only document. |
editorAttributes? |
Record<string, string> |
Host-owned DOM attributes, merged with the editor’s accessible defaults. |
linkHTMLAttributes? |
Readonly<Record<string, string>> |
Optional link DOM attributes; no Markdown or schema attributes are added. |
noteCards? |
boolean |
Render shared Card surfaces for --- section breaks in a Note. |
onCardLayout? |
(segmented) => void |
Reports whether --- currently splits the Note into multiple Cards. |
onEditorReady? |
EditorReady |
- |
onImageResolve? |
ImageSourceResolver |
Display-only URL mapping; stored Markdown remains unchanged. |
onLinkClick? |
EditorLinkClick |
- |
onLoadError? |
(error) => void |
- |
onMarkdownChange? |
MarkdownChange |
Called only when the host explicitly publishes at its save boundary. |
onTransaction? |
EditorTransaction |
- |
slashItems? |
SlashItem[] |
Append host-owned commands to the shared slash commands. |
source |
EditorSource |
Initial source. Changing it requires remounting the surface. |
FormatCommand
Section titled “FormatCommand”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
group |
FormatGroup |
- |
id |
string |
Stable id — also the FormatIcon switch key AND the automation/test hook (buttons expose data-cmd={id}). Prefer this over a CSS class for selectors, per CLAUDE.md’s a11y/addressability rule. |
label |
string |
Accessible name (the button’s aria-label). |
shortcut? |
string |
Stable id shared with a host’s shortcut registry. |
text? |
string |
Optional short text glyph for consumers that render a command label. |
Methods
Section titled “Methods”isActive()
Section titled “isActive()”isActive(
editor):boolean
True when this mark/block is active at the current selection — drives
aria-pressed + the pressed visual.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
editor |
Editor |
Returns
Section titled “Returns”boolean
run(
editor):void
Apply/toggle the format. Always begins .chain().focus() so applying
from a toolbar (whose button took the pointer) restores the caret and
toggles in place rather than against a blurred, selection-less editor.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
editor |
Editor |
Returns
Section titled “Returns”void
ImagePasteContent
Section titled “ImagePasteContent”Sanitized text and HTML from an image paste. The host receives source strings here and image bytes in a separate File list. Temporary image URLs are removed from inserted HTML. Issue #1036; DESIGN §9.
Properties
Section titled “Properties”MoveInfo
Section titled “MoveInfo”The shared “a block moved” shape for a live-region announcement — produced
by whichever caller commits a move (touchDrag.ts today; the keyboard path,
Task 11, will produce the SAME shape from its own commit site) so
NoteEditor.svelte’s announcement wording is governed by ONE contract
regardless of which input modality drove the move. index/count are
1-based/total for a natural “position N of M” reading; dir is which way
the block moved (not currently rendered into the wording, but kept for a
future richer announcement — e.g. distinguishing “up” vs “down” — without
a shape change).
Properties
Section titled “Properties”| Property | Type |
|---|---|
count |
number |
dir |
-1 | 1 |
index |
number |
summary |
string |
Properties
Section titled “Properties”| Property | Type |
|---|---|
content |
PMNode[] |
type |
"doc" |
PMNode
Section titled “PMNode”Properties
Section titled “Properties”| Property | Type |
|---|---|
attrs? |
Record<string, unknown> |
content? |
PMNode[] |
marks? |
PMMark[] |
text? |
string |
type |
string |
SlashItem
Section titled “SlashItem”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
hint |
string |
- |
icon |
string |
Inline SVG path markup for the leading icon (drawn at 18x18, currentColor). |
keywords |
string[] |
- |
run |
(editor, range) => void |
- |
title |
string |
- |
Type Aliases
Section titled “Type Aliases”BlockMoveScope
Section titled “BlockMoveScope”BlockMoveScope =
"note"|"document"
‘note’: the leading H1 is the note title — never selectable and never
crossed. ‘document’: every top-level block is ordinary (day entry and the
editor harness). Same meaning as blockMoveBounds’ scope.
EditorLinkClick
Section titled “EditorLinkClick”EditorLinkClick = (
href,event) =>void
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
href |
string |
event |
MouseEvent |
Returns
Section titled “Returns”void
EditorReady
Section titled “EditorReady”EditorReady = (
editor) =>void
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
editor |
FileIcon |
Returns
Section titled “Returns”void
EditorSource
Section titled “EditorSource”EditorSource = {
kind:"markdown";value:string; } | {awareness?:unknown;doc:unknown;fragment?:unknown;kind:"yjs"; }
A document source is exclusive: Markdown is supported in Phase 1, while the Yjs branch reserves the stable shape for the collaboration phase.
EditorTransaction
Section titled “EditorTransaction”EditorTransaction = (
transaction,editor) =>void
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
transaction |
FileIcon |
editor |
FileIcon |
Returns
Section titled “Returns”void
FormatGroup
Section titled “FormatGroup”FormatGroup =
"inline"|"block"
ImageSourceResolver
Section titled “ImageSourceResolver”ImageSourceResolver = (
storedSource) =>string|null|undefined
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
storedSource |
string |
Returns
Section titled “Returns”string | null | undefined
MarkdownChange
Section titled “MarkdownChange”MarkdownChange = (
markdown,editor) =>void
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
markdown |
string |
editor |
FileIcon |
Returns
Section titled “Returns”void
NoteCardsLayer
Section titled “NoteCardsLayer”NoteCardsLayer =
ReturnType<typeofNoteCardsLayer>
Paint shared Card surfaces behind --- sections in a Note.
The layer does not wrap ProseMirror blocks or receive pointer input. Use it
with the Note cards decoration so selection and block positions stay fixed.
Issue #632; DESIGN §9.
PMMark
Section titled “PMMark”PMMark = {
type:"bold"; } | {type:"italic"; } | {type:"code"; } | {type:"strike"; } | {type:"underline"; } | {type:"highlight"; } | {attrs: {href:string; };type:"link"; } | {attrs: {raw:string; };type:"escapedWikilink"; }
ShortcutBinder
Section titled “ShortcutBinder”ShortcutBinder = <
T>(id,command) =>Record<string,T>
The editor owns its keyboard actions, while each host may own shortcut preferences. This small seam lets the calternal.js app keep using its shared registry without making the editor package depend on app settings or stores.
Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
T |
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
id |
string |
command |
T |
Returns
Section titled “Returns”Record<string, T>
WikilinkLinkFormatter
Section titled “WikilinkLinkFormatter”WikilinkLinkFormatter = (
path,text,anchor) =>string
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
path |
string |
text |
string |
anchor |
string | null |
Returns
Section titled “Returns”string
WikilinkResolution
Section titled “WikilinkResolution”WikilinkResolution = {
kind:"ok";path:string;title?:string; } | {kind:"missing"|"ambiguous"; }
Host-owned result for resolving one wiki reference. Resolution and URL construction stay outside the editor package because they depend on the host’s note index and navigation contract.
WikilinkResolver
Section titled “WikilinkResolver”WikilinkResolver = (
reference) =>WikilinkResolution
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
reference |
string |
Returns
Section titled “Returns”Variables
Section titled “Variables”ALL_COMMANDS
Section titled “ALL_COMMANDS”
constALL_COMMANDS:FormatCommand[]
Complete command inventory retained for callers that need every transform.
AttachmentImage
Section titled “AttachmentImage”
constAttachmentImage:FileIcon<AttachmentImageOptions,any>
BLOCK_COMMANDS
Section titled “BLOCK_COMMANDS”
constBLOCK_COMMANDS:FormatCommand[]
Callout
Section titled “Callout”
constCallout:FileIcon<any,any>
CollaborationHistoryKeys
Section titled “CollaborationHistoryKeys”
constCollaborationHistoryKeys:FileIcon<any,any>
INLINE_COMMANDS
Section titled “INLINE_COMMANDS”
constINLINE_COMMANDS:FormatCommand[]
NoteCardsLayer
Section titled “NoteCardsLayer”
constNoteCardsLayer:Component
Paint shared Card surfaces behind --- sections in a Note.
The layer does not wrap ProseMirror blocks or receive pointer input. Use it
with the Note cards decoration so selection and block positions stay fixed.
Issue #632; DESIGN §9.
prefersReducedMotion
Section titled “prefersReducedMotion”
constprefersReducedMotion:ReducedMotion
SINGLE_LINE_TITLE_WORDS
Section titled “SINGLE_LINE_TITLE_WORDS”
constSINGLE_LINE_TITLE_WORDS:7=7
How many words a single-line text contributes to its title.
SLASH_ITEMS
Section titled “SLASH_ITEMS”
constSLASH_ITEMS:SlashItem[]
Functions
Section titled “Functions”bindEditorShortcut()
Section titled “bindEditorShortcut()”bindEditorShortcut<
T>(id,command):Record<string,T>
Default keymap for a standalone editor consumer without a host registry.
Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
T |
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
id |
string |
command |
T |
Returns
Section titled “Returns”Record<string, T>
calloutLabel()
Section titled “calloutLabel()”calloutLabel(
kind):string
Sentence-case label shared by the editable callout node and read view.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
kind |
string |
Returns
Section titled “Returns”string
calternalExtensions()
Section titled “calternalExtensions()”calternalExtensions(
opts?):AnyExtension[]
Build the shared Markdown schema and interactions (DESIGN §9). Mount and decoration updates keep the loaded tree exact; new blocks require an explicit editing action (#661). Both the live and fallback hosts use this preset.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
opts? |
ExtensionOpts |
Returns
Section titled “Returns”AnyExtension[]
composerNoteTargetKey()
Section titled “composerNoteTargetKey()”composerNoteTargetKey(
target):string
Stable identity for an event-bound Composer Note session.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
target |
ComposerNoteTarget | null |
Returns
Section titled “Returns”string
composerNoteTargetLabel()
Section titled “composerNoteTargetLabel()”composerNoteTargetLabel(
target):string
Chip text: 16:00 · Call with the design team. CSS truncates, never this.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
target |
ComposerNoteTarget |
Returns
Section titled “Returns”string
composerTextToNote()
Section titled “composerTextToNote()”composerTextToNote(
raw):ComposerNoteDraft|null
Map Composer text to a note (the user’s rule for “Add note”):
- Multi-line: the FIRST non-blank line is the title; every later line is the body, verbatim (only blank edge lines are trimmed, so indentation and internal blank lines survive).
- Single line: the title is the first 7 words; the body keeps the ENTIRE line so nothing the user typed is lost. When the line has 7 words or fewer the title already holds all of it, so the body stays empty instead of repeating the title.
- A leading ATX heading marker (
#,##…) is dropped from the TITLE only: the H1 is written by the note builder, and# # Titlewould be noise. Other markdown characters stay; the core escapes them where they would break the attachment link text. - Whitespace-only text returns null: an empty composer never creates a note.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
raw |
string |
Returns
Section titled “Returns”ComposerNoteDraft | null
convertWikilinks()
Section titled “convertWikilinks()”convertWikilinks(
md,resolve,formatLink):string
Convert every [[ref]] / [[ref|alias]] / [[ref#anchor]] in md that
the host resolver identifies uniquely into an angle-wrapped standard
display link. A ref that is unresolved OR
ambiguous is left completely VERBATIM — this function never guesses which
note a ref means, mirroring resolveNoteRef’s own “never guess” contract
(note-resolver.ts). Fenced code blocks (``` or ~~~) are scanned line-by-line
and left untouched, so a [[…]] inside an example snippet is never treated
as a real reference. Inline code SPANS (single- or double-backtick, e.g.
`[[x]]`) are guarded the same way, per-line, via findCodeSpanRanges
(I1, T8 review) — see that function’s own comment for the exact CommonMark
backtick-run semantics it mirrors.
Line-based (not a single global regex over the whole body) so the fence
toggle is trivial to reason about: a fence line flips inFence and is
passed through verbatim; every other line gets the wikilink substitution
only while inFence is false, and only for matches falling OUTSIDE any
inline code span on that line.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
md |
string |
resolve |
WikilinkResolver |
formatLink |
WikilinkLinkFormatter |
Returns
Section titled “Returns”string
createChromeInteraction()
Section titled “createChromeInteraction()”createChromeInteraction():
ChromeInteraction
Mint a fresh, independent instance — see the class’s own header for why this replaced a module-level singleton. Called once per EditorSurface mount (the real app path) or ad hoc by a bare unit test that doesn’t need cross-pipeline sharing at all.
Returns
Section titled “Returns”docToMarkdown()
Section titled “docToMarkdown()”docToMarkdown(
doc):string
Serialize a TipTap doc JSON to a markdown body string.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
doc |
PMDoc |
Returns
Section titled “Returns”string
hasWikilinkSyntax()
Section titled “hasWikilinkSyntax()”hasWikilinkSyntax(
md):boolean
True if md contains anything that could be a [[wikilink]] (either the
clean on-disk form or the backslash-escaped form a legacy/live-typed doc
may contain — see wikilinkSyntax.ts). A false positive just costs
an extra (harmless) convertWikilinks pass; a false negative would mean a
typed/pulled wikilink silently never converts, so this intentionally errs
toward “maybe” rather than trying to be exact.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
md |
string |
Returns
Section titled “Returns”boolean
markdownFromSource()
Section titled “markdownFromSource()”markdownFromSource(
source):string
Return Markdown or reject a reserved source before mounting an editor.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
source |
EditorSource |
Returns
Section titled “Returns”string
markdownToDoc()
Section titled “markdownToDoc()”markdownToDoc(
md,work?):PMDoc
Parse Markdown. The schema stores line breaks, not source newline spelling. Source offsets stay off this ordinary editor parse path.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
md |
string |
work? |
MarkdownSourceWork |
Returns
Section titled “Returns”markdownToDocWithSourcePositions()
Section titled “markdownToDocWithSourcePositions()”markdownToDocWithSourcePositions(
md,work?):MarkdownSourceDocument
The editor parser plus exact raw spans for reminder commit-time targeting.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
md |
string |
work? |
MarkdownSourceWork |
Returns
Section titled “Returns”MarkdownSourceDocument
noteSlashItems()
Section titled “noteSlashItems()”noteSlashItems(
actions):SlashItem[]
Notes-editor-only slash items: /source and /draw need host actions, so
they are injected instead of added to the shared SLASH_ITEMS defaults.
Any other EditorSurface mount (the dev editor harness) keeps the plain
default. (The day-entry BlockEditor that motivated the split is removed.)
The old /properties item is RETIRED. The block editor has no properties
surface now; a future inspector sheet owns that interaction.
Actions are INJECTED (not imported store singletons) so this file stays
store-free — slash.ts has zero svelte/store imports today, and reaching
into $lib/stores/noteView.svelte directly here would be the first (this
keeps the day-entry consumer’s import graph from ever seeing notes-editor
view state it has no use for). toggleSource remains the NoteEditor’s async
wrapper, while draw receives the editor after the slash range is
removed so the host can insert a Drawing block at the current selection.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
actions |
{ draw?: (editor) => void; toggleSource?: () => void; } |
actions.draw? |
(editor) => void |
actions.toggleSource? |
() => void |
Returns
Section titled “Returns”References
Section titled “References”createEditor
Section titled “createEditor”Renames and re-exports FileIcon
Editor
Section titled “Editor”Renames and re-exports FileIcon
EditorContent
Section titled “EditorContent”Renames and re-exports FileIcon
NodeViewWrapper
Section titled “NodeViewWrapper”Renames and re-exports FileIcon
SvelteTipTapEditor
Section titled “SvelteTipTapEditor”Renames and re-exports FileIcon