foldkit-richtext-dom 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { a as KeyBinding, n as Attachment, r as Decorate } from "./events-DLi6ecvD.mjs";
1
+ import { a as KeyBinding, n as Attachment, r as Decorate } from "./events-De4SvZil.mjs";
2
2
  import * as RichText from "foldkit-richtext";
3
3
  import { Schema } from "effect";
4
4
  import * as Mount from "foldkit/mount";
@@ -638,6 +638,8 @@ declare const attachEditor: (host: Element, content: RichText.Document, emit: (m
638
638
  * while the transition was in flight — so it reports whether it patched.
639
639
  */
640
640
  declare const patchEditor: (hostId: string, state: RichText.EditorState, changeSet: RichText.ChangeSet) => boolean;
641
+ /** Tells the editor at `hostId` that an edit it asked for is drawn or refused (`Attachment.answered`). */
642
+ declare const answerEditor: (hostId: string) => void;
641
643
  /** Draws the decorations of the editor at `hostId` again; false when none is attached there. */
642
644
  declare const redecorateEditor: (hostId: string) => boolean;
643
645
  /**
@@ -1119,5 +1121,5 @@ declare const events: Mount.MountDefinitionWithArgs<"RichTextDomEvents", {
1119
1121
  }[];
1120
1122
  }>;
1121
1123
  //#endregion
1122
- export { SlashMenu as a, focusEditor as c, patchEditor as d, redecorateEditor as f, toMessage as g, slashQuery as h, SlashEntry as i, heldDocument as l, slashMenu as m, EditorEvent as n, attachEditor as o, slashEntries as p, Message as r, events as s, EditorDrawing as t, matchingEntries as u };
1123
- //# sourceMappingURL=editor-gCZiXgG4.d.mts.map
1124
+ export { toMessage as _, SlashMenu as a, events as c, matchingEntries as d, patchEditor as f, slashQuery as g, slashMenu as h, SlashEntry as i, focusEditor as l, slashEntries as m, EditorEvent as n, answerEditor as o, redecorateEditor as p, Message as r, attachEditor as s, EditorDrawing as t, heldDocument as u };
1125
+ //# sourceMappingURL=editor-Cmo24yol.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor-gCZiXgG4.d.mts","names":["_$__events_js0.Attachment"],"sources":["../src/editor.ts"],"mappings":";;;;;cAyBa,mCAAO;;IACT,MAAI,OAAA;;;;;;IAIE,MAAI,OAAA;;;;IAEJ,MAAI,OAAA,gBAAA,OAAA,gBAAA,OAAA;;;;;;;;;;IAKJ,MAAI,OAAA,gBAAA,OAAA,gBAAA,OAAA;;;;;;IACH,OAAK,OAAA,gBAAA,OAAA;;;;;;;;;IAEL,YAAU,OAAA,OAAA,OAAA;;;;;;;IAER,IAAE,OAAA;;;;;;;;;IAIN,MAAI,OAAA,MAAA,OAAA;IAAmB,IAAE,OAAA,gBAAA,OAAA;;;;;;;;;;IAEtB,OAAK,OAAA,gBAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAkB,IAAE,OAAA,YAAA,OAAA,gBAAA,OAAA;;;;;;;;;;IAE1B,MAAI,OAAA,MAAA,OAAA;;;;IAEL,OAAK,OAAA;;;;IAEF,OAAK,OAAA;;;;;;;;;;;;;IAYrB,OAAK,OAAA;IACL,aAAW,OAAA;IACX,eAAa,OAAA,YAAA,OAAA;IACb,IAAE,OAAA,YAAA,OAAA;;;;IAGgB,MAAI,OAAA,YAAA,OAAA;;;;IAEL,MAAI,OAAA;IAAiB,IAAE,OAAA;;;;;;;;;IAOpB,MAAI,OAAA,MAAA,OAAA;IAAmB,QAAM,OAAA;;;;;;IAInC,MAAI,OAAA,MAAA,OAAA;IAAmB,OAAK,OAAA,QAAA,OAAA,QAAA,OAAA,MAAA,OAAA,MAAA,OAAA;;;IAChC,WAAS,OAAA,OAAA,OAAA,gBAAA,OAAA;;;;;;;;;;;;;;;;;;IACX,OAAK,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOL,iBAAiB,QAAQ;;;;;;KAOzB,cAAc,QAAQ;WAAoB;;;;;;;;cAQzC,YAAS,SAAa,SAAS,YAAU;;;;;;;;;;;;UAwCrC,WAAW;;WAEjB;;WAEA;;WAEA,UAAU;;WAEV,SAAS;;WAET;;WAEA;;WAEA;;;;;;;;cASE,aAAU;;;;;;;;cA8BV,cAAc,cAAc,WAAW;;;;;;cAoGvC,kBAAmB,SAAO,SAC5B,cAAc,WAAW,WAAS,kBAE1C,cAAc,WAAW;;UAaX,UAAU;WAChB;WACA,SAAS,cAAc,WAAW;;WAElC,aAAa,WAAW;;;;;;;;;;;;;cActB,YAAa,SAAO,SACtB,cAAc,WAAW,WAAS,oBACzB,kBAEjB,UAAU;;UAQI;WACN,YAAY,SAAS;WACrB,WAAW;;WAEX;;WAEA;;WAEA,QAAQ,SAAS;;WAEjB,SAAS,cAAc;;;;;;;cAQrB,eAAY,MACjB,SAAO,SACJ,SAAS,UAAQ,OACnB,SAAS,sBAAoB,UAC3B,kBAAAA;;;;;;cA2BE,cAAW,gBACR,OACP,SAAS,aAAW,WAChB,SAAS;;cAWT,mBAAgB;;;;;cAWhB,cAAW,gBAAkB,WAAa,SAAS;;;;;cAWnD,eAAY,mBAAqB,SAAS;;;;cAQ1C,QAAM,MAAA"}
1
+ {"version":3,"file":"editor-Cmo24yol.d.mts","names":["_$__events_js0.Attachment"],"sources":["../src/editor.ts"],"mappings":";;;;;cAyBa,mCAAO;;IACT,MAAI,OAAA;;;;;;IAIE,MAAI,OAAA;;;;IAEJ,MAAI,OAAA,gBAAA,OAAA,gBAAA,OAAA;;;;;;;;;;IAKJ,MAAI,OAAA,gBAAA,OAAA,gBAAA,OAAA;;;;;;IACH,OAAK,OAAA,gBAAA,OAAA;;;;;;;;;IAEL,YAAU,OAAA,OAAA,OAAA;;;;;;;IAER,IAAE,OAAA;;;;;;;;;IAIN,MAAI,OAAA,MAAA,OAAA;IAAmB,IAAE,OAAA,gBAAA,OAAA;;;;;;;;;;IAEtB,OAAK,OAAA,gBAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAkB,IAAE,OAAA,YAAA,OAAA,gBAAA,OAAA;;;;;;;;;;IAE1B,MAAI,OAAA,MAAA,OAAA;;;;IAEL,OAAK,OAAA;;;;IAEF,OAAK,OAAA;;;;;;;;;;;;;IAYrB,OAAK,OAAA;IACL,aAAW,OAAA;IACX,eAAa,OAAA,YAAA,OAAA;IACb,IAAE,OAAA,YAAA,OAAA;;;;IAGgB,MAAI,OAAA,YAAA,OAAA;;;;IAEL,MAAI,OAAA;IAAiB,IAAE,OAAA;;;;;;;;;IAOpB,MAAI,OAAA,MAAA,OAAA;IAAmB,QAAM,OAAA;;;;;;IAInC,MAAI,OAAA,MAAA,OAAA;IAAmB,OAAK,OAAA,QAAA,OAAA,QAAA,OAAA,MAAA,OAAA,MAAA,OAAA;;;IAChC,WAAS,OAAA,OAAA,OAAA,gBAAA,OAAA;;;;;;;;;;;;;;;;;;IACX,OAAK,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOL,iBAAiB,QAAQ;;;;;;KAOzB,cAAc,QAAQ;WAAoB;;;;;;;;cAQzC,YAAS,SAAa,SAAS,YAAU;;;;;;;;;;;;UAwCrC,WAAW;;WAEjB;;WAEA;;WAEA,UAAU;;WAEV,SAAS;;WAET;;WAEA;;WAEA;;;;;;;;cASE,aAAU;;;;;;;;cA8BV,cAAc,cAAc,WAAW;;;;;;cAoGvC,kBAAmB,SAAO,SAC5B,cAAc,WAAW,WAAS,kBAE1C,cAAc,WAAW;;UAaX,UAAU;WAChB;WACA,SAAS,cAAc,WAAW;;WAElC,aAAa,WAAW;;;;;;;;;;;;;cActB,YAAa,SAAO,SACtB,cAAc,WAAW,WAAS,oBACzB,kBAEjB,UAAU;;UAQI;WACN,YAAY,SAAS;WACrB,WAAW;;WAEX;;WAEA;;WAEA,QAAQ,SAAS;;WAEjB,SAAS,cAAc;;;;;;;cAQrB,eAAY,MACjB,SAAO,SACJ,SAAS,UAAQ,OACnB,SAAS,sBAAoB,UAC3B,kBAAAA;;;;;;cA2BE,cAAW,gBACR,OACP,SAAS,aAAW,WAChB,SAAS;;cAWT,eAAY;;cAMZ,mBAAgB;;;;;cAWhB,cAAW,gBAAkB,WAAa,SAAS;;;;;cAWnD,eAAY,mBAAqB,SAAS;;;;cAQ1C,QAAM,MAAA"}
@@ -1,6 +1,6 @@
1
- import { a as KeyBinding, r as Decorate } from "./events-DLi6ecvD.mjs";
2
- import { i as SlashEntry, n as EditorEvent, r as Message } from "./editor-gCZiXgG4.mjs";
3
- import { n as Vocabulary } from "./host-Cp2Zz-bO.mjs";
1
+ import { a as KeyBinding, r as Decorate } from "./events-De4SvZil.mjs";
2
+ import { i as SlashEntry, n as EditorEvent, r as Message } from "./editor-Cmo24yol.mjs";
3
+ import { n as Vocabulary } from "./host-BKvhyPj-.mjs";
4
4
  import * as RichText from "foldkit-richtext";
5
5
  import { Option, Schema } from "effect";
6
6
  import { Bundle, Wrapped } from "foldkit-bundle";
@@ -1 +1 @@
1
- {"version":3,"file":"editor-bundle.d.mts","names":[],"sources":["../src/editor-bundle.ts"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA8LV,QAAM,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCjB;qBAIW,yCAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YACd,uBAAuB,cAAc;;;;;iBAuChC;;WAEN,YAAY,SAAS;;WAErB,aAAa;;WAEb,aAAa,cAAc,SAAS;;;;;WAKpC,WAAW;;WAEX;;;;;WAKA;;;;;;WAMA,SAAS,cAAc;;;;;;WAMvB,eAAe,cAAc,WAAW;;;;;;WAMxC;;;;;;qBAOE,cAAW,gBAAkB,WAAa;;;;;;qBAqB1C,WAAQ,gBAAkB,YAAa,6CAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAkBtD,iCAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAEN,aAAW,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAGX,SAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAGN,SAAM,SAAa,YAAU;qBAC7B,QAAK,iBAAmB;qBACxB,UAAO,oDAAsD;qBAE7D,UAAO,iBAAmB;qBAC1B,UAAO,MAAU,SAAS,YAAU;qBAEpC,UAAO,iBAAmB;qBAC1B,UAAO,OAAW,SAAS,cAAY;qBAEvC,UAAO,YAAgB,cAAc,SAAS,eAAa;qBAE3D,YAAS,IAAQ,SAAS,cAAY;qBAEtC,cAAa;qBACb,QAAK,MAAU,SAAS,QAAM,IAAM,SAAS,WAAS;qBAEtD,WAAQ,OAAW,SAAS,OAAK,KAAO,SAAS,WAAS;qBAE1D,UAAO,MAAU,SAAS,WAAS;qBAEnC,eAAY,MAAU,SAAS,QAAM,OAAS,OAAO,eAAa;qBAElE,WAAQ,WAAe,SAAS,qBAAmB;qBAEnD,cAAa;qBACb,cAAa;qBACb,eAAc"}
1
+ {"version":3,"file":"editor-bundle.d.mts","names":[],"sources":["../src/editor-bundle.ts"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAuMV,QAAM,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCjB;qBAIW,yCAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YACd,uBAAuB,cAAc;;;;;iBAuChC;;WAEN,YAAY,SAAS;;WAErB,aAAa;;WAEb,aAAa,cAAc,SAAS;;;;;WAKpC,WAAW;;WAEX;;;;;WAKA;;;;;;WAMA,SAAS,cAAc;;;;;;WAMvB,eAAe,cAAc,WAAW;;;;;;WAMxC;;;;;;qBAOE,cAAW,gBAAkB,WAAa;;;;;;qBAqB1C,WAAQ,gBAAkB,YAAa,6CAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAkBtD,iCAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAEN,aAAW,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAGX,SAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAGN,SAAM,SAAa,YAAU;qBAC7B,QAAK,iBAAmB;qBACxB,UAAO,oDAAsD;qBAE7D,UAAO,iBAAmB;qBAC1B,UAAO,MAAU,SAAS,YAAU;qBAEpC,UAAO,iBAAmB;qBAC1B,UAAO,OAAW,SAAS,cAAY;qBAEvC,UAAO,YAAgB,cAAc,SAAS,eAAa;qBAE3D,YAAS,IAAQ,SAAS,cAAY;qBAEtC,cAAa;qBACb,QAAK,MAAU,SAAS,QAAM,IAAM,SAAS,WAAS;qBAEtD,WAAQ,OAAW,SAAS,OAAK,KAAO,SAAS,WAAS;qBAE1D,UAAO,MAAU,SAAS,WAAS;qBAEnC,eAAY,MAAU,SAAS,QAAM,OAAS,OAAO,eAAa;qBAElE,WAAQ,WAAe,SAAS,qBAAmB;qBAEnD,cAAa;qBACb,cAAa;qBACb,eAAc"}
@@ -1,5 +1,5 @@
1
1
  import { decorationsFor, inputRulesFor, placeDecorations, placeInputRules, placeKeymap, placeOverlay, placePlaceholders, placeRendering, placeServerRendered, placeSlashEntries, placeVocabulary, renderingFor, serverRenderedFor, slashEntriesFor, vocabularyFor } from "./host.mjs";
2
- import { Message, events, focusEditor, heldDocument, patchEditor, redecorateEditor, slashEntries, slashMenu, slashQuery } from "./editor.mjs";
2
+ import { Message, answerEditor, events, focusEditor, heldDocument, patchEditor, redecorateEditor, slashEntries, slashMenu, slashQuery } from "./editor.mjs";
3
3
  import { renderEditable } from "./view.mjs";
4
4
  import * as RichText from "foldkit-richtext";
5
5
  import { Effect, Equal, Match, Option, Schema } from "effect";
@@ -231,6 +231,16 @@ const patch = (hostId, state, changeSet) => ({
231
231
  }), Message.Patched())
232
232
  });
233
233
  /**
234
+ * Answers an edit the editor asked for (`Attachment.answered`), last among the Commands of
235
+ * its transition: the runtime runs them in order, so the answer follows the draw, or stands
236
+ * alone for an edit refused or changing nothing. An application that replaces the patch
237
+ * with its own keeps the answer after it.
238
+ */
239
+ const answer = (hostId) => ({
240
+ name: "RichText.answer",
241
+ effect: Effect.as(Effect.sync(() => answerEditor(hostId)), Message.Patched())
242
+ });
243
+ /**
234
244
  * The text between the start of the caret's block and the caret, or `''` when the
235
245
  * selection names no caret. A menu and the input rules read this; nothing about the query
236
246
  * is stored. A range is read from its start, which is where what is typed over it lands,
@@ -394,6 +404,7 @@ const transition = (model, incoming) => {
394
404
  Undone: (undone) => travel(model, state, undone),
395
405
  Redone: (redone) => travel(model, state, redone)
396
406
  }), Match.orElse((message) => {
407
+ const answering = message._tag === "Selected" ? [] : [answer(model.hostId)];
397
408
  let nextId = model.nextId;
398
409
  const collapsed = model.selection?.type === "Range" && model.selection.anchor.node === model.selection.focus.node && model.selection.anchor.offset === model.selection.focus.offset;
399
410
  if (message._tag === "ToggledMark" && collapsed && !(vocabulary.marks ?? RichText.shippedRegistry).accepts(message.mark)) return {
@@ -401,7 +412,8 @@ const transition = (model, incoming) => {
401
412
  outMessage: {
402
413
  _tag: "Rejected",
403
414
  error: "InvalidInput"
404
- }
415
+ },
416
+ commands: answering
405
417
  };
406
418
  const storedMarks = message._tag === "ToggledMark" && collapsed ? model.storedMarks?.includes(message.mark) ? model.storedMarks.filter((mark) => mark !== message.mark) : [...model.storedMarks ?? [], message.mark] : model.storedMarks;
407
419
  const command = message._tag === "Typed" && storedMarks !== null ? {
@@ -436,9 +448,13 @@ const transition = (model, incoming) => {
436
448
  outMessage: {
437
449
  _tag: "Rejected",
438
450
  error: result.error
439
- }
451
+ },
452
+ commands: answering
453
+ };
454
+ if (result.state === state && storedMarks === model.storedMarks) return {
455
+ model,
456
+ commands: answering
440
457
  };
441
- if (result.state === state && storedMarks === model.storedMarks) return { model };
442
458
  const contentChanged = result.state.document !== model.document;
443
459
  return {
444
460
  model: {
@@ -454,7 +470,7 @@ const transition = (model, incoming) => {
454
470
  changeSet: result.changeSet,
455
471
  transactions: result.transactions
456
472
  },
457
- commands: [patch(model.hostId, result.state, result.changeSet)]
473
+ commands: [patch(model.hostId, result.state, result.changeSet), ...answering]
458
474
  };
459
475
  }));
460
476
  };
@@ -1 +1 @@
1
- {"version":3,"file":"editor-bundle.mjs","names":[],"sources":["../src/editor-bundle.ts"],"sourcesContent":["/**\n * The controlled-editor feasibility harness (§27): the authoritative Document\n * lives in the parent Model, the editor Bundle reads it through its Link, and a\n * single parent transition commits both the document and the interaction state.\n *\n * No DOM, no persistence, no collaboration: this exists to answer whether Bundle\n * ownership can hold a rich-text editor without a second synchronized document\n * copy or a Command that commits half the transition.\n */\nimport { Effect, Equal, Match, Option, Schema } from 'effect'\nimport { define } from 'foldkit/customElement'\nimport { defineMessageUnion } from 'foldkit/message'\nimport { Bundle, Link, type Wrapped } from 'foldkit-bundle'\nimport * as RichText from 'foldkit-richtext'\nimport * as Submodel from 'foldkit/submodel'\nimport type * as Command from 'foldkit/command'\nimport type * as Update from 'foldkit/update'\nimport {\n heldDocument,\n events,\n focusEditor,\n Message,\n patchEditor,\n redecorateEditor,\n slashEntries,\n slashMenu,\n slashQuery,\n type EditorEvent,\n type SlashEntry,\n} from './editor.js'\nimport {\n decorationsFor,\n inputRulesFor,\n placeDecorations,\n placeInputRules,\n placeOverlay,\n placePlaceholders,\n placeRendering,\n placeServerRendered,\n placeKeymap,\n placeSlashEntries,\n placeVocabulary,\n renderingFor,\n serverRenderedFor,\n slashEntriesFor,\n type Vocabulary,\n vocabularyFor,\n} from './host.js'\nimport type { Decorate, KeyBinding } from './events.js'\nimport { renderEditable } from './view.js'\n\n/** Interaction state the parent owns beside the document. */\nexport const EditorState = Schema.Struct({\n selection: Schema.NullOr(RichText.Selection),\n /** Caller-owned identity source: a live edit mints, replay never does. */\n nextId: Schema.Number,\n /** Local undo history: snapshots of document plus selection. */\n history: RichText.History,\n /** Null inherits neighboring marks; an array explicitly sets them, even when empty. */\n storedMarks: Schema.NullOr(Schema.Array(Schema.String)),\n /**\n * The highlighted entry in a live slash menu (§123). The document says whether the\n * caret is in a query and what matches; this is the one thing the menu owns, and\n * `update` resolves Enter against it.\n */\n menuIndex: Schema.Number,\n /** The slash of the query whose menu Escape closed; it stays closed until that query ends. */\n slashDismissed: Schema.OptionFromNullOr(RichText.Position),\n /**\n * The host element the view renders and the patch Command finds (§118). It is\n * per-placement, so it arrives as the Bundle's args and is carried here\n * because `read` re-projects the whole child from the parent.\n */\n hostId: Schema.String,\n})\nexport type EditorState = typeof EditorState.Type\n\nexport const Model = Schema.Struct({\n document: RichText.Document,\n editor: EditorState,\n})\nexport type Model = typeof Model.Type\n\n/** What the child reads: the parent's document passes through, never stored. */\nexport const EditorView = Schema.Struct({\n document: RichText.Document,\n selection: Schema.NullOr(RichText.Selection),\n nextId: Schema.Number,\n history: RichText.History,\n storedMarks: Schema.NullOr(Schema.Array(Schema.String)),\n menuIndex: Schema.Number,\n slashDismissed: Schema.OptionFromNullOr(RichText.Position),\n hostId: Schema.String,\n})\nexport type EditorView = typeof EditorView.Type\n\n/** The committed edit, or the diagnostic that refused it. */\nexport type OutMessage =\n | {\n readonly _tag: 'Edited'\n readonly state: RichText.EditorState\n readonly changeSet: RichText.ChangeSet\n /** What the edit applied, in order, as `RichText.run` returns them. */\n readonly transactions: ReadonlyArray<RichText.Transaction>\n }\n | {\n /** Undo and redo replace the document wholesale; nothing was incremental. */\n readonly _tag: 'Replaced'\n readonly state: RichText.EditorState\n readonly changeSet: RichText.ChangeSet\n }\n | { readonly _tag: 'Rejected'; readonly error: string }\n\n/** Where a node stands: the block holding it (null at the top), and its index there. */\ninterface Placed {\n readonly node: RichText.Block | RichText.Text\n readonly parent: RichText.NodeId | null\n readonly index: number\n}\n\n/** Every block and run of a document by id, nested ones included, with where it stands. */\nconst nodesOf = (content: RichText.Document): ReadonlyMap<RichText.NodeId, Placed> => {\n const nodes = new Map<RichText.NodeId, Placed>()\n const visit = (blocks: ReadonlyArray<RichText.Block>, parent: RichText.NodeId | null): void => {\n for (const [index, block] of blocks.entries()) {\n nodes.set(block.id, { node: block, parent, index })\n for (const [at, run] of block.children.entries()) {\n nodes.set(run.id, { node: run, parent: block.id, index: at })\n }\n if (block.type === 'Node' && block.blocks !== undefined) visit(block.blocks, block.id)\n }\n }\n visit(content.children, null)\n return nodes\n}\n\nconst sameMarks = (left: RichText.Text, right: RichText.Text): boolean =>\n left.marks.length === right.marks.length &&\n left.marks.every((mark, index) => RichText.sameMark(mark, right.marks[index]!))\n\n/** A block's own fields, apart from what it holds: its type, level, kind and props. */\nconst ownFields = ({ children: _runs, ...block }: RichText.Block): unknown => ({\n ...block,\n blocks: undefined,\n})\n\n/**\n * What differs between two whole documents, for a patch from one to the other, in a\n * transaction's terms: the runs whose text or marks changed and the blocks holding them,\n * blocks whose own fields changed, what came and went, and whether any block moved.\n */\nexport const replaceChangeSet = (\n previous: RichText.Document,\n next: RichText.Document,\n): RichText.ChangeSet => {\n const before = nodesOf(previous)\n const after = nodesOf(next)\n const dirtyNodes = new Set<RichText.NodeId>()\n const textChanged = new Set<RichText.NodeId>()\n let structureChanged = false\n for (const [id, placed] of after) {\n const was = before.get(id)\n if (placed.node.type === 'Text') {\n const run = placed.node\n const old = was?.node.type === 'Text' ? was.node : undefined\n if (old === undefined || old.text !== run.text) textChanged.add(id)\n if (old === undefined || old.text !== run.text || !sameMarks(old, run)) {\n dirtyNodes.add(id)\n if (placed.parent !== null) dirtyNodes.add(placed.parent)\n }\n // A run moved to another block, or to another place in its own, changes both blocks'\n // runs though the run itself did not change.\n if (was !== undefined && (was.parent !== placed.parent || was.index !== placed.index)) {\n if (placed.parent !== null) dirtyNodes.add(placed.parent)\n if (was.parent !== null && after.has(was.parent)) dirtyNodes.add(was.parent)\n }\n continue\n }\n if (was === undefined || was.parent !== placed.parent || was.index !== placed.index) {\n structureChanged = true\n }\n if (\n was === undefined ||\n !Equal.equals(ownFields(was.node as RichText.Block), ownFields(placed.node))\n ) {\n dirtyNodes.add(id)\n }\n }\n const removedNodes = new Set([...before.keys()].filter(id => !after.has(id)))\n for (const id of removedNodes) {\n const was = before.get(id)!\n if (was.node.type !== 'Text') structureChanged = true\n else if (was.parent !== null && after.has(was.parent)) dirtyNodes.add(was.parent)\n }\n return {\n dirtyNodes,\n insertedNodes: new Set([...after.keys()].filter(id => !before.has(id))),\n removedNodes,\n textChanged,\n structureChanged,\n selectionChanged: false,\n }\n}\n\ntype CommandMessage = Exclude<\n Message,\n { readonly _tag: 'Undone' | 'Redone' | 'Patched' | 'ActivatedAdornment' | 'DismissedSlash' }\n>\n\nconst toCommand = (message: CommandMessage): RichText.Command => {\n switch (message._tag) {\n case 'Typed':\n return { type: 'InsertText', text: message.text }\n case 'Backspace':\n return { type: 'DeleteBackward' }\n case 'DeletedForward':\n return { type: 'DeleteForward' }\n case 'Entered':\n return { type: 'SplitBlock' }\n case 'ToggledMark':\n return { type: 'ToggleMark', mark: message.mark }\n case 'AppliedMark':\n return { type: 'SetMark', mark: message.mark }\n case 'ClearedMark':\n return { type: 'ClearMark', mark: message.mark }\n case 'RetypedBlock':\n return { type: 'RetypeBlock', to: message.block }\n case 'WrappedBlock':\n return { type: 'WrapBlock', containers: message.containers }\n case 'ConvertedBlock':\n return { type: 'ConvertBlock', to: message.to }\n case 'LiftedBlock':\n return { type: 'LiftBlock' }\n case 'MovedBlock':\n return { type: 'MoveBlock', node: message.node, to: message.to }\n case 'InsertedBlock':\n return { type: 'InsertBlock', block: message.block, to: message.to }\n case 'DeletedBlock':\n return { type: 'DeleteBlock', node: message.node }\n case 'ChangedProps':\n return { type: 'SetProps', node: message.node, props: message.props }\n case 'InsertedRow':\n return { type: 'InsertRow', where: message.where }\n case 'InsertedColumn':\n return { type: 'InsertColumn', where: message.where }\n case 'DeletedRow':\n return { type: 'DeleteRow' }\n case 'DeletedColumn':\n return { type: 'DeleteColumn' }\n case 'Indented':\n return { type: 'Indent' }\n case 'ReplacedText':\n return {\n type: 'Replace',\n query: message.query,\n replacement: message.replacement,\n caseSensitive: message.caseSensitive,\n at: message.at,\n }\n case 'InsertedFootnote':\n return { type: 'InsertFootnote', text: message.text }\n case 'RenamedFootnote':\n return { type: 'RenameFootnote', from: message.from, to: message.to }\n case 'Outdented':\n return { type: 'Outdent' }\n case 'Selected':\n return { type: 'SetSelection', selection: message.selection }\n case 'Pasted':\n return { type: 'Paste', slice: message.slice }\n }\n}\n\n/**\n * The rendering effect (§118): patch the host the view rendered, once the\n * parent's transition has committed. It commits nothing, so the one-transition\n * property the proof established is untouched.\n */\nconst patch = (hostId: string, state: RichText.EditorState, changeSet: RichText.ChangeSet) => ({\n name: 'RichText.patch',\n effect: Effect.as(\n Effect.sync(() => {\n patchEditor(hostId, state, changeSet)\n }),\n Message.Patched(),\n ),\n})\n\n/**\n * The text between the start of the caret's block and the caret, or `''` when the\n * selection names no caret. A menu and the input rules read this; nothing about the query\n * is stored. A range is read from its start, which is where what is typed over it lands,\n * whichever way it was dragged.\n */\nconst textBeforeOf = (model: EditorView): string => {\n if (model.selection?.type !== 'Range') return ''\n const start = RichText.rangeStart(model.document, model.selection)\n return start === undefined ? '' : RichText.textBefore(model.document, start)\n}\n\n/** Where the slash of the caret's live query is: none outside a query. */\nconst slashOf = (model: EditorView): Option.Option<RichText.Position> => {\n const query = slashQuery(textBeforeOf(model))\n if (query === undefined || model.selection?.type !== 'Range') return Option.none()\n const start = RichText.rangeStart(model.document, model.selection)\n const range =\n start === undefined\n ? undefined\n : RichText.textRangeBefore(model.document, start, query.length + 1)\n return range?.type === 'Range' ? Option.some(range.anchor) : Option.none()\n}\n\nconst dismissed = (model: EditorView): boolean =>\n Option.exists(model.slashDismissed, slash =>\n Option.exists(slashOf(model), live => live.node === slash.node && live.offset === slash.offset),\n )\n\n/**\n * The text a slash menu reads: the text before the caret, or nothing once Escape has closed\n * the menu of the query the caret is in. Enter resolves against it, and an application's menu\n * view reads it too, so the two agree on whether a menu is open.\n */\nexport const menuTextOf = (model: EditorView): string =>\n dismissed(model) ? '' : textBeforeOf(model)\n\n/**\n * The kinds of the node blocks around the caret's block, innermost first; a range is read\n * from its start, as `textBeforeOf` reads it.\n */\nconst withinOf = (model: EditorView): ReadonlyArray<string> => {\n if (model.selection?.type !== 'Range') return []\n const start = RichText.rangeStart(model.document, model.selection)\n const run = start === undefined ? undefined : RichText.locateRun(model.document, start.node)\n if (run === undefined) return []\n const kinds: Array<string> = []\n for (let depth = run.path.length - 1; depth > 0; depth--) {\n const block = RichText.blockAtPath(model.document, run.path.slice(0, depth))\n if (block?.type === 'Node') kinds.push(block.kind)\n }\n return kinds\n}\n\nconst Host = define({ tag: 'foldkit-richtext', properties: {}, events: {} })\n\n/**\n * Each host id's keys, by the document shown. The host's Mount reads its document once, so a\n * document that did not come from an edit here (a form's fill or reset, an entry opened, a\n * revision restored) needs a fresh host. A committed edit moves its document's key to the next\n * document (`carryKey`), and the document it leaves keeps none, so returning to it is a new host\n * too. The first document a host id shows has no key, as the server's render has none.\n */\nconst lineages = new Map<\n string,\n { next: number; readonly keys: WeakMap<RichText.Document, number> }\n>()\n\nconst lineageOf = (hostId: string) => {\n const found = lineages.get(hostId)\n if (found !== undefined) return found\n const created = { next: 0, keys: new WeakMap<RichText.Document, number>() }\n lineages.set(hostId, created)\n return created\n}\n\nconst hostKey = (hostId: string, document: RichText.Document): string | undefined => {\n const lineage = lineageOf(hostId)\n const key = lineage.keys.get(document) ?? lineage.next++\n lineage.keys.set(document, key)\n return key === 0 ? undefined : `${hostId}-${key}`\n}\n\nconst carryKey = (hostId: string, from: RichText.Document, to: RichText.Document): void => {\n const keys = lineageOf(hostId).keys\n const key = keys.get(from)\n if (key === undefined || from === to) return\n keys.delete(from)\n keys.set(to, key)\n}\n\n/**\n * Patches the editor at `hostId` to `next`, a document the parent put in place of\n * `previous`, keeping the host element instead of mounting a new one. A parent that\n * replaces its document outside an edit here (another replica's change arriving) returns\n * this, in the same transition as the replacement.\n *\n * The host is found by the document the view renders, so `previous` is the object it\n * rendered and `next.document` the object it will render; building the Command hands the\n * host on from one to the other, so build it only to return it. The patch itself starts\n * from the latest state the editor holds (what it has drawn, or a state waiting on a\n * composition), and `next.selection` becomes the browser selection;\n * a replacement that changes nothing drawn leaves the DOM alone, selection included, as an\n * exchange that only confirms edits already shown does.\n */\nexport const patchTo = (\n hostId: string,\n previous: RichText.Document,\n next: RichText.EditorState,\n): Command.Command<Message> => {\n carryKey(hostId, previous, next.document)\n return {\n name: 'RichText.patch',\n effect: Effect.as(\n Effect.sync(() => {\n const held = heldDocument(hostId)\n // No editor is attached there: it went away while the transition was in flight.\n if (held === undefined) return\n const changeSet = replaceChangeSet(held, next.document)\n const unchanged =\n !changeSet.structureChanged &&\n changeSet.dirtyNodes.size === 0 &&\n changeSet.removedNodes.size === 0\n if (!unchanged) patchEditor(hostId, next, changeSet)\n }),\n Message.Patched(),\n ),\n }\n}\n\n/**\n * Draws `decorations` over the editor at `hostId`, beside what its placement draws, until the\n * next overlay replaces them: decorations an application derives from its own state, such as\n * other people's carets, which a placement's `decorate` cannot see. Their positions name the\n * document shown, so an application sets them again when that changes. The caret stays put.\n */\nexport const overlay = (\n hostId: string,\n decorations: RichText.DecorationSet,\n): Command.Command<Message> => ({\n name: 'RichText.overlay',\n effect: Effect.as(\n Effect.sync(() => {\n placeOverlay(hostId, decorations)\n redecorateEditor(hostId)\n }),\n Message.Patched(),\n ),\n})\n\n/**\n * Focuses the editor at `hostId` with `selection` in the browser, brought into view: for a\n * control outside the editor that sends the reader into the text, such as a table of contents.\n * The browser reports the selection back as `Selected`, so the Model follows it either way.\n */\nexport const focus = (hostId: string, selection: RichText.Selection): Command.Command<Message> => ({\n name: 'RichText.focus',\n effect: Effect.as(\n Effect.sync(() => focusEditor(hostId, selection)),\n Message.Patched(),\n ),\n})\n\n/**\n * The host element the editor mounts into, and whose id the patch Command finds (§118). It is a\n * custom element so hydration leaves what is inside it alone (§145): on the server it holds the\n * document's markup, which the editor adopts; in the browser the view declares it empty, and the\n * editor owns everything below.\n */\nexport const editorView = Submodel.defineView<EditorView, Message>((model, h) => {\n const serverRendered = serverRenderedFor(model.hostId)()\n const key = serverRendered ? undefined : hostKey(model.hostId, model.document)\n return Host.withMessage(h)(\n [\n h.Id(model.hostId),\n ...(key === undefined ? [] : [h.Key(key)]),\n // A custom element is inline until styled, and the editor inside it is a block.\n h.Style({ display: 'block' }),\n h.OnMount(events({ content: model.document })),\n ],\n serverRendered\n ? [\n renderEditable(\n model.document,\n renderingFor(model.hostId),\n decorationsFor(model.hostId)(model.document),\n ),\n ]\n : [],\n )\n})\n\n/** What a Message does to the editor; `Editor.update` carries the host's key on a commit. */\nconst transition = (\n model: EditorView,\n incoming: Message,\n): Update.ReturnWithOutMessage<EditorView, Message, OutMessage> => {\n const state: RichText.EditorState = { document: model.document, selection: model.selection }\n // The vocabulary this placement resolves edits against; both fields may be absent.\n const vocabulary = vocabularyFor(model.hostId)\n // A live query decides what Enter means before anything else reads the message\n // (§123): the highlighted entry applies as the Message a click would send, instead\n // of splitting, and a query that chooses nothing falls through to `incoming` and\n // still splits. Substituting the Message here rather than recursing is what makes a\n // mark entry update the caret's stored marks through the path a toggle already uses.\n const menu =\n incoming._tag === 'Entered'\n ? slashMenu(slashEntriesFor(model.hostId) ?? slashEntries, menuTextOf(model), model.menuIndex)\n : undefined\n const message = menu?.highlighted?.message ?? incoming\n return Match.value(message).pipe(\n Match.withReturnType<Update.ReturnWithOutMessage<EditorView, Message, OutMessage>>(),\n Match.tags({\n // The patch Command's own completion: the render already happened.\n Patched: () => ({ model }),\n // A click asking the application for something, not an edit: nothing changes here.\n ActivatedAdornment: () => ({ model }),\n DismissedSlash: () => {\n const slash = slashOf(model)\n return Option.isNone(slash) || dismissed(model)\n ? { model }\n : { model: { ...model, slashDismissed: slash } }\n },\n Undone: undone => travel(model, state, undone),\n Redone: redone => travel(model, state, redone),\n }),\n Match.orElse(message => {\n let nextId = model.nextId\n // With nothing selected, a mark toggle is the caret's own state: the next\n // typed text lands with it. A caret move ends the format it was carrying.\n const collapsed =\n model.selection?.type === 'Range' &&\n model.selection.anchor.node === model.selection.focus.node &&\n model.selection.anchor.offset === model.selection.focus.offset\n // The caret never carries a mark the vocabulary cannot type — an unknown one, or one\n // like Link whose props a bare name lacks — so it is refused here rather than at the\n // first keystroke after it.\n if (\n message._tag === 'ToggledMark' &&\n collapsed &&\n !(vocabulary.marks ?? RichText.shippedRegistry).accepts(message.mark)\n ) {\n return { model, outMessage: { _tag: 'Rejected', error: 'InvalidInput' } }\n }\n const storedMarks =\n message._tag === 'ToggledMark' && collapsed\n ? model.storedMarks?.includes(message.mark)\n ? model.storedMarks.filter(mark => mark !== message.mark)\n : [...(model.storedMarks ?? []), message.mark]\n : model.storedMarks\n const command =\n message._tag === 'Typed' && storedMarks !== null\n ? ({ type: 'InsertText', text: message.text, marks: storedMarks } as const)\n : toCommand(message)\n // Choosing an entry removes the query it was typed into and applies the choice as\n // one action (§124 §5), so one transition and one undo step cover both. The range is\n // a read, not state: `menu.query` is the text the document already holds, and the\n // `+ 1` is the slash that opened it.\n const queryRange =\n menu === undefined || menu.highlighted === undefined || model.selection?.type !== 'Range'\n ? undefined\n : RichText.textRangeBefore(model.document, model.selection.anchor, menu.query.length + 1)\n const runAction = (action: RichText.Action) =>\n RichText.runAction(\n state,\n action,\n { mint: () => `e${nextId++}` },\n { marks: vocabulary.marks, nodes: vocabulary.nodes },\n )\n // What is typed can be a block marker (§124 §4): the rules are the placement's own, so\n // the editor carries none of any syntax's vocabulary itself.\n const ruled =\n queryRange === undefined && message._tag === 'Typed'\n ? RichText.resolveInputRules(inputRulesFor(model.hostId), {\n textBefore: textBeforeOf(model),\n text: message.text,\n insertion: command,\n within: withinOf(model),\n })\n : undefined\n const attempt = runAction(\n queryRange !== undefined\n ? [{ type: 'SetSelection', selection: queryRange }, { type: 'DeleteBackward' }, command]\n : (ruled?.action ?? [command]),\n )\n // A rule the vocabulary refuses — a fence typed into bold text, say — leaves the marker\n // as the text it is, rather than refusing the keystroke along with it. The refused\n // attempt's identities are given back first.\n const fallback = !attempt.ok && ruled !== undefined\n if (fallback) nextId = model.nextId\n const result = fallback ? runAction([command]) : attempt\n if (!result.ok) {\n // A refused command changes nothing, so it does not burn identities.\n return { model, outMessage: { _tag: 'Rejected', error: result.error } }\n }\n // `runAction` returns the state it was given when nothing changed: a caret the browser\n // echoes back, or a command with nothing to act on. Keeping the Model keeps the page from\n // rendering, and a caret that did not move keeps the format it carries.\n if (result.state === state && storedMarks === model.storedMarks) return { model }\n // History holds content, not cursor movement: a selection change keeps the\n // redo stack, and a no-op edit adds no step to undo.\n const contentChanged = result.state.document !== model.document\n return {\n model: {\n ...model,\n selection: result.state.selection,\n nextId,\n // A caret move ends the format it was carrying; a rule that applied may set the next.\n storedMarks:\n message._tag === 'Selected'\n ? null\n : ((fallback ? undefined : ruled?.storedMarks) ?? storedMarks),\n history: contentChanged\n ? RichText.commit(model.history, state, { group: RichText.groupFor(command) })\n : model.history,\n },\n outMessage: {\n _tag: 'Edited',\n state: result.state,\n changeSet: result.changeSet,\n transactions: result.transactions,\n },\n commands: [patch(model.hostId, result.state, result.changeSet)],\n }\n }),\n )\n}\n\n/** Undo or redo: history restores content and selection, and the host is told as a replace. */\nconst travel = (\n model: EditorView,\n state: RichText.EditorState,\n message: Extract<Message, { readonly _tag: 'Undone' | 'Redone' }>,\n): Update.ReturnWithOutMessage<EditorView, Message, OutMessage> => {\n const restored =\n message._tag === 'Undone'\n ? RichText.undo(model.history, state)\n : RichText.redo(model.history, state)\n if (restored === undefined) {\n return {\n model,\n outMessage: {\n _tag: 'Rejected',\n error: message._tag === 'Undone' ? 'NothingToUndo' : 'NothingToRedo',\n },\n }\n }\n const changeSet = replaceChangeSet(model.document, restored.state.document)\n return {\n model: {\n ...model,\n selection: restored.state.selection,\n history: restored.history,\n },\n outMessage: { _tag: 'Replaced', state: restored.state, changeSet },\n commands: [patch(model.hostId, restored.state, changeSet)],\n }\n}\n\nexport const Editor = Bundle.make({\n name: 'RichTextEditor',\n Model: EditorView,\n Message,\n args: Schema.Struct({ hostId: Schema.String }),\n // A read-only projection has no initial content of its own; the placement\n // writes only the interaction fields back, so this never becomes the document.\n // The host id is the one thing the child seeds: it is per-placement, and `read`\n // re-projects everything else.\n init: args => ({\n model: {\n document: RichText.Document.make({ version: 1, children: [] }),\n selection: null,\n nextId: 0,\n history: RichText.emptyHistory,\n storedMarks: null,\n menuIndex: 0,\n slashDismissed: Option.none(),\n hostId: args.hostId,\n },\n }),\n update: (model, incoming): Update.ReturnWithOutMessage<EditorView, Message, OutMessage> => {\n const result = transition(model, incoming)\n const out = result.outMessage\n // An edit or a replacement carries the state it committed; a rejection, none.\n const committed = out !== undefined && 'state' in out ? out.state : undefined\n if (committed !== undefined) carryKey(model.hostId, model.document, committed.document)\n // A dismissal ends with the query it closed, so a slash typed later opens a menu again.\n // The child's document is the parent's, so the edit is read from what it committed.\n const after = { ...result.model, document: committed?.document ?? result.model.document }\n return Option.isSome(result.model.slashDismissed) && !dismissed(after)\n ? { ...result, model: { ...result.model, slashDismissed: Option.none() } }\n : result\n },\n // The host element belongs to the view; everything below it belongs to the\n // interpreter the mount attaches there.\n view: editorView,\n})\n\nconst GotEditor = Link.wrapper('GotEditorMessage', Message)\n\nexport const ParentMessage = defineMessageUnion({ ...GotEditor.cases })\nexport type ParentMessage = typeof ParentMessage.Type\n\nconst editorLink: Link<\n Model,\n Wrapped<'GotEditorMessage', Message>,\n EditorView,\n Message\n> = Link.make({\n // The child sees the parent's document; the parent owns it.\n read: parent =>\n Option.some({\n document: parent.document,\n selection: parent.editor.selection,\n nextId: parent.editor.nextId,\n history: parent.editor.history,\n storedMarks: parent.editor.storedMarks,\n menuIndex: parent.editor.menuIndex,\n slashDismissed: parent.editor.slashDismissed,\n hostId: parent.editor.hostId,\n }),\n // Only interaction state is written back: the document is not the child's. `read` builds a\n // new view each time, so the Bundle cannot see that a child returned what it read; a child\n // whose fields are the parent's own leaves the parent as it was. The placement's `init`\n // writes into a parent that has no `editor` yet.\n write: (parent, { document: _document, ...editor }) => {\n const current: EditorState | undefined = parent.editor\n return current !== undefined &&\n (Object.keys(editor) as Array<keyof EditorState>).every(key => editor[key] === current[key])\n ? parent\n : { ...parent, editor }\n },\n wrapper: GotEditor,\n path: ['editor'],\n})\n\n/**\n * What a placement gives its editor. Each is placed by host id rather than passed as an arg\n * (§122): each holds functions or schemas, which a schema-decoded arg cannot describe.\n */\nexport interface EditorPlacement {\n /** How this editor's marks and node kinds render (§121). Defaults to `noRendering`. */\n readonly rendering?: RichText.Rendering | undefined\n /** The vocabulary its edits resolve against (§125). Defaults to none. */\n readonly vocabulary?: Vocabulary | undefined\n /** The rules applied to what is typed (§128). Defaults to none. */\n readonly inputRules?: ReadonlyArray<RichText.InputRule> | undefined\n /**\n * What is drawn over the document (§129), derived from it on every patch: code\n * highlighting, for one. Defaults to nothing.\n */\n readonly decorate?: Decorate | undefined\n /** What the editor shows while its document is blank (`RichText.isBlank`). Defaults to none. */\n readonly placeholder?: string | undefined\n /**\n * What the empty paragraph the caret is in shows, such as \"Type / for blocks\", as\n * `data-hint` on it. Defaults to none.\n */\n readonly lineHint?: string | undefined\n /**\n * Chords beside the built-in ones (Bold, Italic, Code, Strikethrough, undo and redo), checked\n * first: `{ chord: 'Mod-u', command: { type: 'ToggleMark', mark: 'Underline' } }` for a mark\n * of the application's own. Defaults to none.\n */\n readonly keymap?: ReadonlyArray<KeyBinding> | undefined\n /**\n * What its slash menu offers, which Enter resolves against: an application's own entries\n * (an image, a table, a callout) beside or instead of `slashEntries`. The application's menu\n * view draws the same list. Defaults to `slashEntries`.\n */\n readonly slashEntries?: ReadonlyArray<SlashEntry<EditorEvent>> | undefined\n /**\n * Whether this render is the server's (§145), such as `foldkit-ssr`'s `SSR.serving`. While it\n * is, the host carries the document's markup, which the browser's editor adopts instead of\n * drawing again. Defaults to never, so the host is empty until the editor mounts.\n */\n readonly serverRendered?: (() => boolean) | undefined\n}\n\n/**\n * Records everything a placement names for its host id, replacing what the id had: one call,\n * so a placement cannot half-apply. `editorAt` and the form control both place through it.\n */\nexport const placeEditor = (hostId: string, placement: EditorPlacement): void => {\n placeRendering(hostId, placement.rendering ?? RichText.noRendering)\n placeVocabulary(hostId, placement.vocabulary ?? {})\n placeInputRules(hostId, placement.inputRules ?? [])\n placeDecorations(hostId, placement.decorate ?? (() => []))\n // The overlay is set by Commands after placing, so a placement starts without the last one's.\n placeOverlay(hostId, [])\n placePlaceholders(hostId, {\n placeholder: placement.placeholder,\n lineHint: placement.lineHint,\n })\n placeSlashEntries(hostId, placement.slashEntries)\n placeKeymap(hostId, placement.keymap ?? [])\n placeServerRendered(hostId, placement.serverRendered ?? (() => false))\n}\n\n/**\n * Places one editor, bound to the host element the view renders and the patch Command\n * finds. Each placement picks its own id and names what it places; one call records all\n * of it, so a placement cannot half-apply.\n */\nexport const editorAt = (hostId: string, placement: EditorPlacement = {}) => {\n placeEditor(hostId, placement)\n return Editor.at(editorLink, {\n args: { hostId },\n // Runs with the child already written back, in the same parent transition.\n onOut: (out: OutMessage) => (parent: Model) =>\n out._tag === 'Edited' || out._tag === 'Replaced'\n ? {\n model: {\n ...parent,\n document: out.state.document,\n editor: { ...parent.editor, selection: out.state.selection },\n },\n }\n : { model: parent },\n })\n}\n\nexport const editor = editorAt('richtext-editor')\n\nexport const application = Bundle.assemble<Model, ParentMessage>()([editor])\n\n/** The parent's update: placement Messages route to the editor, others stand still. */\nexport const update = application.update()\n\n/** Wraps one editor Message as the parent Message that carries it. */\nexport const edited = (message: Message): ParentMessage => GotEditor.make(message)\nexport const typed = (text: string): ParentMessage => edited(Message.Typed({ text }))\nexport const pressed = (tag: 'Backspace' | 'DeletedForward' | 'Entered'): ParentMessage =>\n edited(Message[tag]())\nexport const toggled = (mark: string): ParentMessage => edited(Message.ToggledMark({ mark }))\nexport const applied = (mark: RichText.RunMark): ParentMessage =>\n edited(Message.AppliedMark({ mark }))\nexport const cleared = (mark: string): ParentMessage => edited(Message.ClearedMark({ mark }))\nexport const retyped = (block: RichText.TextBlock): ParentMessage =>\n edited(Message.RetypedBlock({ block }))\nexport const wrapped = (containers: ReadonlyArray<RichText.Container>): ParentMessage =>\n edited(Message.WrappedBlock({ containers }))\nexport const converted = (to: RichText.Container): ParentMessage =>\n edited(Message.ConvertedBlock({ to }))\nexport const lifted = (): ParentMessage => edited(Message.LiftedBlock())\nexport const moved = (node: RichText.NodeId, to: RichText.Beside): ParentMessage =>\n edited(Message.MovedBlock({ node, to }))\nexport const inserted = (block: RichText.Block, to?: RichText.Beside): ParentMessage =>\n edited(Message.InsertedBlock(to === undefined ? { block } : { block, to }))\nexport const deleted = (node: RichText.NodeId): ParentMessage =>\n edited(Message.DeletedBlock({ node }))\nexport const changedProps = (node: RichText.NodeId, props: Schema.JsonObject): ParentMessage =>\n edited(Message.ChangedProps({ node, props }))\nexport const selected = (selection: RichText.Selection | null): ParentMessage =>\n edited(Message.Selected({ selection }))\nexport const undone = (): ParentMessage => edited(Message.Undone())\nexport const redone = (): ParentMessage => edited(Message.Redone())\nexport const patched = (): ParentMessage => edited(Message.Patched())\n"],"mappings":"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"}
1
+ {"version":3,"file":"editor-bundle.mjs","names":[],"sources":["../src/editor-bundle.ts"],"sourcesContent":["/**\n * The controlled-editor feasibility harness (§27): the authoritative Document\n * lives in the parent Model, the editor Bundle reads it through its Link, and a\n * single parent transition commits both the document and the interaction state.\n *\n * No DOM, no persistence, no collaboration: this exists to answer whether Bundle\n * ownership can hold a rich-text editor without a second synchronized document\n * copy or a Command that commits half the transition.\n */\nimport { Effect, Equal, Match, Option, Schema } from 'effect'\nimport { define } from 'foldkit/customElement'\nimport { defineMessageUnion } from 'foldkit/message'\nimport { Bundle, Link, type Wrapped } from 'foldkit-bundle'\nimport * as RichText from 'foldkit-richtext'\nimport * as Submodel from 'foldkit/submodel'\nimport type * as Command from 'foldkit/command'\nimport type * as Update from 'foldkit/update'\nimport {\n heldDocument,\n events,\n focusEditor,\n Message,\n answerEditor,\n patchEditor,\n redecorateEditor,\n slashEntries,\n slashMenu,\n slashQuery,\n type EditorEvent,\n type SlashEntry,\n} from './editor.js'\nimport {\n decorationsFor,\n inputRulesFor,\n placeDecorations,\n placeInputRules,\n placeOverlay,\n placePlaceholders,\n placeRendering,\n placeServerRendered,\n placeKeymap,\n placeSlashEntries,\n placeVocabulary,\n renderingFor,\n serverRenderedFor,\n slashEntriesFor,\n type Vocabulary,\n vocabularyFor,\n} from './host.js'\nimport type { Decorate, KeyBinding } from './events.js'\nimport { renderEditable } from './view.js'\n\n/** Interaction state the parent owns beside the document. */\nexport const EditorState = Schema.Struct({\n selection: Schema.NullOr(RichText.Selection),\n /** Caller-owned identity source: a live edit mints, replay never does. */\n nextId: Schema.Number,\n /** Local undo history: snapshots of document plus selection. */\n history: RichText.History,\n /** Null inherits neighboring marks; an array explicitly sets them, even when empty. */\n storedMarks: Schema.NullOr(Schema.Array(Schema.String)),\n /**\n * The highlighted entry in a live slash menu (§123). The document says whether the\n * caret is in a query and what matches; this is the one thing the menu owns, and\n * `update` resolves Enter against it.\n */\n menuIndex: Schema.Number,\n /** The slash of the query whose menu Escape closed; it stays closed until that query ends. */\n slashDismissed: Schema.OptionFromNullOr(RichText.Position),\n /**\n * The host element the view renders and the patch Command finds (§118). It is\n * per-placement, so it arrives as the Bundle's args and is carried here\n * because `read` re-projects the whole child from the parent.\n */\n hostId: Schema.String,\n})\nexport type EditorState = typeof EditorState.Type\n\nexport const Model = Schema.Struct({\n document: RichText.Document,\n editor: EditorState,\n})\nexport type Model = typeof Model.Type\n\n/** What the child reads: the parent's document passes through, never stored. */\nexport const EditorView = Schema.Struct({\n document: RichText.Document,\n selection: Schema.NullOr(RichText.Selection),\n nextId: Schema.Number,\n history: RichText.History,\n storedMarks: Schema.NullOr(Schema.Array(Schema.String)),\n menuIndex: Schema.Number,\n slashDismissed: Schema.OptionFromNullOr(RichText.Position),\n hostId: Schema.String,\n})\nexport type EditorView = typeof EditorView.Type\n\n/** The committed edit, or the diagnostic that refused it. */\nexport type OutMessage =\n | {\n readonly _tag: 'Edited'\n readonly state: RichText.EditorState\n readonly changeSet: RichText.ChangeSet\n /** What the edit applied, in order, as `RichText.run` returns them. */\n readonly transactions: ReadonlyArray<RichText.Transaction>\n }\n | {\n /** Undo and redo replace the document wholesale; nothing was incremental. */\n readonly _tag: 'Replaced'\n readonly state: RichText.EditorState\n readonly changeSet: RichText.ChangeSet\n }\n | { readonly _tag: 'Rejected'; readonly error: string }\n\n/** Where a node stands: the block holding it (null at the top), and its index there. */\ninterface Placed {\n readonly node: RichText.Block | RichText.Text\n readonly parent: RichText.NodeId | null\n readonly index: number\n}\n\n/** Every block and run of a document by id, nested ones included, with where it stands. */\nconst nodesOf = (content: RichText.Document): ReadonlyMap<RichText.NodeId, Placed> => {\n const nodes = new Map<RichText.NodeId, Placed>()\n const visit = (blocks: ReadonlyArray<RichText.Block>, parent: RichText.NodeId | null): void => {\n for (const [index, block] of blocks.entries()) {\n nodes.set(block.id, { node: block, parent, index })\n for (const [at, run] of block.children.entries()) {\n nodes.set(run.id, { node: run, parent: block.id, index: at })\n }\n if (block.type === 'Node' && block.blocks !== undefined) visit(block.blocks, block.id)\n }\n }\n visit(content.children, null)\n return nodes\n}\n\nconst sameMarks = (left: RichText.Text, right: RichText.Text): boolean =>\n left.marks.length === right.marks.length &&\n left.marks.every((mark, index) => RichText.sameMark(mark, right.marks[index]!))\n\n/** A block's own fields, apart from what it holds: its type, level, kind and props. */\nconst ownFields = ({ children: _runs, ...block }: RichText.Block): unknown => ({\n ...block,\n blocks: undefined,\n})\n\n/**\n * What differs between two whole documents, for a patch from one to the other, in a\n * transaction's terms: the runs whose text or marks changed and the blocks holding them,\n * blocks whose own fields changed, what came and went, and whether any block moved.\n */\nexport const replaceChangeSet = (\n previous: RichText.Document,\n next: RichText.Document,\n): RichText.ChangeSet => {\n const before = nodesOf(previous)\n const after = nodesOf(next)\n const dirtyNodes = new Set<RichText.NodeId>()\n const textChanged = new Set<RichText.NodeId>()\n let structureChanged = false\n for (const [id, placed] of after) {\n const was = before.get(id)\n if (placed.node.type === 'Text') {\n const run = placed.node\n const old = was?.node.type === 'Text' ? was.node : undefined\n if (old === undefined || old.text !== run.text) textChanged.add(id)\n if (old === undefined || old.text !== run.text || !sameMarks(old, run)) {\n dirtyNodes.add(id)\n if (placed.parent !== null) dirtyNodes.add(placed.parent)\n }\n // A run moved to another block, or to another place in its own, changes both blocks'\n // runs though the run itself did not change.\n if (was !== undefined && (was.parent !== placed.parent || was.index !== placed.index)) {\n if (placed.parent !== null) dirtyNodes.add(placed.parent)\n if (was.parent !== null && after.has(was.parent)) dirtyNodes.add(was.parent)\n }\n continue\n }\n if (was === undefined || was.parent !== placed.parent || was.index !== placed.index) {\n structureChanged = true\n }\n if (\n was === undefined ||\n !Equal.equals(ownFields(was.node as RichText.Block), ownFields(placed.node))\n ) {\n dirtyNodes.add(id)\n }\n }\n const removedNodes = new Set([...before.keys()].filter(id => !after.has(id)))\n for (const id of removedNodes) {\n const was = before.get(id)!\n if (was.node.type !== 'Text') structureChanged = true\n else if (was.parent !== null && after.has(was.parent)) dirtyNodes.add(was.parent)\n }\n return {\n dirtyNodes,\n insertedNodes: new Set([...after.keys()].filter(id => !before.has(id))),\n removedNodes,\n textChanged,\n structureChanged,\n selectionChanged: false,\n }\n}\n\ntype CommandMessage = Exclude<\n Message,\n { readonly _tag: 'Undone' | 'Redone' | 'Patched' | 'ActivatedAdornment' | 'DismissedSlash' }\n>\n\nconst toCommand = (message: CommandMessage): RichText.Command => {\n switch (message._tag) {\n case 'Typed':\n return { type: 'InsertText', text: message.text }\n case 'Backspace':\n return { type: 'DeleteBackward' }\n case 'DeletedForward':\n return { type: 'DeleteForward' }\n case 'Entered':\n return { type: 'SplitBlock' }\n case 'ToggledMark':\n return { type: 'ToggleMark', mark: message.mark }\n case 'AppliedMark':\n return { type: 'SetMark', mark: message.mark }\n case 'ClearedMark':\n return { type: 'ClearMark', mark: message.mark }\n case 'RetypedBlock':\n return { type: 'RetypeBlock', to: message.block }\n case 'WrappedBlock':\n return { type: 'WrapBlock', containers: message.containers }\n case 'ConvertedBlock':\n return { type: 'ConvertBlock', to: message.to }\n case 'LiftedBlock':\n return { type: 'LiftBlock' }\n case 'MovedBlock':\n return { type: 'MoveBlock', node: message.node, to: message.to }\n case 'InsertedBlock':\n return { type: 'InsertBlock', block: message.block, to: message.to }\n case 'DeletedBlock':\n return { type: 'DeleteBlock', node: message.node }\n case 'ChangedProps':\n return { type: 'SetProps', node: message.node, props: message.props }\n case 'InsertedRow':\n return { type: 'InsertRow', where: message.where }\n case 'InsertedColumn':\n return { type: 'InsertColumn', where: message.where }\n case 'DeletedRow':\n return { type: 'DeleteRow' }\n case 'DeletedColumn':\n return { type: 'DeleteColumn' }\n case 'Indented':\n return { type: 'Indent' }\n case 'ReplacedText':\n return {\n type: 'Replace',\n query: message.query,\n replacement: message.replacement,\n caseSensitive: message.caseSensitive,\n at: message.at,\n }\n case 'InsertedFootnote':\n return { type: 'InsertFootnote', text: message.text }\n case 'RenamedFootnote':\n return { type: 'RenameFootnote', from: message.from, to: message.to }\n case 'Outdented':\n return { type: 'Outdent' }\n case 'Selected':\n return { type: 'SetSelection', selection: message.selection }\n case 'Pasted':\n return { type: 'Paste', slice: message.slice }\n }\n}\n\n/**\n * The rendering effect (§118): patch the host the view rendered, once the\n * parent's transition has committed. It commits nothing, so the one-transition\n * property the proof established is untouched.\n */\nconst patch = (hostId: string, state: RichText.EditorState, changeSet: RichText.ChangeSet) => ({\n name: 'RichText.patch',\n effect: Effect.as(\n Effect.sync(() => {\n patchEditor(hostId, state, changeSet)\n }),\n Message.Patched(),\n ),\n})\n\n/**\n * Answers an edit the editor asked for (`Attachment.answered`), last among the Commands of\n * its transition: the runtime runs them in order, so the answer follows the draw, or stands\n * alone for an edit refused or changing nothing. An application that replaces the patch\n * with its own keeps the answer after it.\n */\nconst answer = (hostId: string) => ({\n name: 'RichText.answer',\n effect: Effect.as(\n Effect.sync(() => answerEditor(hostId)),\n Message.Patched(),\n ),\n})\n\n/**\n * The text between the start of the caret's block and the caret, or `''` when the\n * selection names no caret. A menu and the input rules read this; nothing about the query\n * is stored. A range is read from its start, which is where what is typed over it lands,\n * whichever way it was dragged.\n */\nconst textBeforeOf = (model: EditorView): string => {\n if (model.selection?.type !== 'Range') return ''\n const start = RichText.rangeStart(model.document, model.selection)\n return start === undefined ? '' : RichText.textBefore(model.document, start)\n}\n\n/** Where the slash of the caret's live query is: none outside a query. */\nconst slashOf = (model: EditorView): Option.Option<RichText.Position> => {\n const query = slashQuery(textBeforeOf(model))\n if (query === undefined || model.selection?.type !== 'Range') return Option.none()\n const start = RichText.rangeStart(model.document, model.selection)\n const range =\n start === undefined\n ? undefined\n : RichText.textRangeBefore(model.document, start, query.length + 1)\n return range?.type === 'Range' ? Option.some(range.anchor) : Option.none()\n}\n\nconst dismissed = (model: EditorView): boolean =>\n Option.exists(model.slashDismissed, slash =>\n Option.exists(slashOf(model), live => live.node === slash.node && live.offset === slash.offset),\n )\n\n/**\n * The text a slash menu reads: the text before the caret, or nothing once Escape has closed\n * the menu of the query the caret is in. Enter resolves against it, and an application's menu\n * view reads it too, so the two agree on whether a menu is open.\n */\nexport const menuTextOf = (model: EditorView): string =>\n dismissed(model) ? '' : textBeforeOf(model)\n\n/**\n * The kinds of the node blocks around the caret's block, innermost first; a range is read\n * from its start, as `textBeforeOf` reads it.\n */\nconst withinOf = (model: EditorView): ReadonlyArray<string> => {\n if (model.selection?.type !== 'Range') return []\n const start = RichText.rangeStart(model.document, model.selection)\n const run = start === undefined ? undefined : RichText.locateRun(model.document, start.node)\n if (run === undefined) return []\n const kinds: Array<string> = []\n for (let depth = run.path.length - 1; depth > 0; depth--) {\n const block = RichText.blockAtPath(model.document, run.path.slice(0, depth))\n if (block?.type === 'Node') kinds.push(block.kind)\n }\n return kinds\n}\n\nconst Host = define({ tag: 'foldkit-richtext', properties: {}, events: {} })\n\n/**\n * Each host id's keys, by the document shown. The host's Mount reads its document once, so a\n * document that did not come from an edit here (a form's fill or reset, an entry opened, a\n * revision restored) needs a fresh host. A committed edit moves its document's key to the next\n * document (`carryKey`), and the document it leaves keeps none, so returning to it is a new host\n * too. The first document a host id shows has no key, as the server's render has none.\n */\nconst lineages = new Map<\n string,\n { next: number; readonly keys: WeakMap<RichText.Document, number> }\n>()\n\nconst lineageOf = (hostId: string) => {\n const found = lineages.get(hostId)\n if (found !== undefined) return found\n const created = { next: 0, keys: new WeakMap<RichText.Document, number>() }\n lineages.set(hostId, created)\n return created\n}\n\nconst hostKey = (hostId: string, document: RichText.Document): string | undefined => {\n const lineage = lineageOf(hostId)\n const key = lineage.keys.get(document) ?? lineage.next++\n lineage.keys.set(document, key)\n return key === 0 ? undefined : `${hostId}-${key}`\n}\n\nconst carryKey = (hostId: string, from: RichText.Document, to: RichText.Document): void => {\n const keys = lineageOf(hostId).keys\n const key = keys.get(from)\n if (key === undefined || from === to) return\n keys.delete(from)\n keys.set(to, key)\n}\n\n/**\n * Patches the editor at `hostId` to `next`, a document the parent put in place of\n * `previous`, keeping the host element instead of mounting a new one. A parent that\n * replaces its document outside an edit here (another replica's change arriving) returns\n * this, in the same transition as the replacement.\n *\n * The host is found by the document the view renders, so `previous` is the object it\n * rendered and `next.document` the object it will render; building the Command hands the\n * host on from one to the other, so build it only to return it. The patch itself starts\n * from the latest state the editor holds (what it has drawn, or a state waiting on a\n * composition), and `next.selection` becomes the browser selection;\n * a replacement that changes nothing drawn leaves the DOM alone, selection included, as an\n * exchange that only confirms edits already shown does.\n */\nexport const patchTo = (\n hostId: string,\n previous: RichText.Document,\n next: RichText.EditorState,\n): Command.Command<Message> => {\n carryKey(hostId, previous, next.document)\n return {\n name: 'RichText.patch',\n effect: Effect.as(\n Effect.sync(() => {\n const held = heldDocument(hostId)\n // No editor is attached there: it went away while the transition was in flight.\n if (held === undefined) return\n const changeSet = replaceChangeSet(held, next.document)\n const unchanged =\n !changeSet.structureChanged &&\n changeSet.dirtyNodes.size === 0 &&\n changeSet.removedNodes.size === 0\n if (!unchanged) patchEditor(hostId, next, changeSet)\n }),\n Message.Patched(),\n ),\n }\n}\n\n/**\n * Draws `decorations` over the editor at `hostId`, beside what its placement draws, until the\n * next overlay replaces them: decorations an application derives from its own state, such as\n * other people's carets, which a placement's `decorate` cannot see. Their positions name the\n * document shown, so an application sets them again when that changes. The caret stays put.\n */\nexport const overlay = (\n hostId: string,\n decorations: RichText.DecorationSet,\n): Command.Command<Message> => ({\n name: 'RichText.overlay',\n effect: Effect.as(\n Effect.sync(() => {\n placeOverlay(hostId, decorations)\n redecorateEditor(hostId)\n }),\n Message.Patched(),\n ),\n})\n\n/**\n * Focuses the editor at `hostId` with `selection` in the browser, brought into view: for a\n * control outside the editor that sends the reader into the text, such as a table of contents.\n * The browser reports the selection back as `Selected`, so the Model follows it either way.\n */\nexport const focus = (hostId: string, selection: RichText.Selection): Command.Command<Message> => ({\n name: 'RichText.focus',\n effect: Effect.as(\n Effect.sync(() => focusEditor(hostId, selection)),\n Message.Patched(),\n ),\n})\n\n/**\n * The host element the editor mounts into, and whose id the patch Command finds (§118). It is a\n * custom element so hydration leaves what is inside it alone (§145): on the server it holds the\n * document's markup, which the editor adopts; in the browser the view declares it empty, and the\n * editor owns everything below.\n */\nexport const editorView = Submodel.defineView<EditorView, Message>((model, h) => {\n const serverRendered = serverRenderedFor(model.hostId)()\n const key = serverRendered ? undefined : hostKey(model.hostId, model.document)\n return Host.withMessage(h)(\n [\n h.Id(model.hostId),\n ...(key === undefined ? [] : [h.Key(key)]),\n // A custom element is inline until styled, and the editor inside it is a block.\n h.Style({ display: 'block' }),\n h.OnMount(events({ content: model.document })),\n ],\n serverRendered\n ? [\n renderEditable(\n model.document,\n renderingFor(model.hostId),\n decorationsFor(model.hostId)(model.document),\n ),\n ]\n : [],\n )\n})\n\n/** What a Message does to the editor; `Editor.update` carries the host's key on a commit. */\nconst transition = (\n model: EditorView,\n incoming: Message,\n): Update.ReturnWithOutMessage<EditorView, Message, OutMessage> => {\n const state: RichText.EditorState = { document: model.document, selection: model.selection }\n // The vocabulary this placement resolves edits against; both fields may be absent.\n const vocabulary = vocabularyFor(model.hostId)\n // A live query decides what Enter means before anything else reads the message\n // (§123): the highlighted entry applies as the Message a click would send, instead\n // of splitting, and a query that chooses nothing falls through to `incoming` and\n // still splits. Substituting the Message here rather than recursing is what makes a\n // mark entry update the caret's stored marks through the path a toggle already uses.\n const menu =\n incoming._tag === 'Entered'\n ? slashMenu(slashEntriesFor(model.hostId) ?? slashEntries, menuTextOf(model), model.menuIndex)\n : undefined\n const message = menu?.highlighted?.message ?? incoming\n return Match.value(message).pipe(\n Match.withReturnType<Update.ReturnWithOutMessage<EditorView, Message, OutMessage>>(),\n Match.tags({\n // The patch Command's own completion: the render already happened.\n Patched: () => ({ model }),\n // A click asking the application for something, not an edit: nothing changes here.\n ActivatedAdornment: () => ({ model }),\n DismissedSlash: () => {\n const slash = slashOf(model)\n return Option.isNone(slash) || dismissed(model)\n ? { model }\n : { model: { ...model, slashDismissed: slash } }\n },\n Undone: undone => travel(model, state, undone),\n Redone: redone => travel(model, state, redone),\n }),\n Match.orElse(message => {\n // Every edit the editor asks for is answered, once drawn or refused; a reported caret\n // is not an ask.\n const answering = message._tag === 'Selected' ? [] : [answer(model.hostId)]\n let nextId = model.nextId\n // With nothing selected, a mark toggle is the caret's own state: the next\n // typed text lands with it. A caret move ends the format it was carrying.\n const collapsed =\n model.selection?.type === 'Range' &&\n model.selection.anchor.node === model.selection.focus.node &&\n model.selection.anchor.offset === model.selection.focus.offset\n // The caret never carries a mark the vocabulary cannot type — an unknown one, or one\n // like Link whose props a bare name lacks — so it is refused here rather than at the\n // first keystroke after it.\n if (\n message._tag === 'ToggledMark' &&\n collapsed &&\n !(vocabulary.marks ?? RichText.shippedRegistry).accepts(message.mark)\n ) {\n return {\n model,\n outMessage: { _tag: 'Rejected', error: 'InvalidInput' },\n commands: answering,\n }\n }\n const storedMarks =\n message._tag === 'ToggledMark' && collapsed\n ? model.storedMarks?.includes(message.mark)\n ? model.storedMarks.filter(mark => mark !== message.mark)\n : [...(model.storedMarks ?? []), message.mark]\n : model.storedMarks\n const command =\n message._tag === 'Typed' && storedMarks !== null\n ? ({ type: 'InsertText', text: message.text, marks: storedMarks } as const)\n : toCommand(message)\n // Choosing an entry removes the query it was typed into and applies the choice as\n // one action (§124 §5), so one transition and one undo step cover both. The range is\n // a read, not state: `menu.query` is the text the document already holds, and the\n // `+ 1` is the slash that opened it.\n const queryRange =\n menu === undefined || menu.highlighted === undefined || model.selection?.type !== 'Range'\n ? undefined\n : RichText.textRangeBefore(model.document, model.selection.anchor, menu.query.length + 1)\n const runAction = (action: RichText.Action) =>\n RichText.runAction(\n state,\n action,\n { mint: () => `e${nextId++}` },\n { marks: vocabulary.marks, nodes: vocabulary.nodes },\n )\n // What is typed can be a block marker (§124 §4): the rules are the placement's own, so\n // the editor carries none of any syntax's vocabulary itself.\n const ruled =\n queryRange === undefined && message._tag === 'Typed'\n ? RichText.resolveInputRules(inputRulesFor(model.hostId), {\n textBefore: textBeforeOf(model),\n text: message.text,\n insertion: command,\n within: withinOf(model),\n })\n : undefined\n const attempt = runAction(\n queryRange !== undefined\n ? [{ type: 'SetSelection', selection: queryRange }, { type: 'DeleteBackward' }, command]\n : (ruled?.action ?? [command]),\n )\n // A rule the vocabulary refuses — a fence typed into bold text, say — leaves the marker\n // as the text it is, rather than refusing the keystroke along with it. The refused\n // attempt's identities are given back first.\n const fallback = !attempt.ok && ruled !== undefined\n if (fallback) nextId = model.nextId\n const result = fallback ? runAction([command]) : attempt\n if (!result.ok) {\n // A refused command changes nothing, so it does not burn identities.\n return { model, outMessage: { _tag: 'Rejected', error: result.error }, commands: answering }\n }\n // `runAction` returns the state it was given when nothing changed: a caret the browser\n // echoes back, or a command with nothing to act on. Keeping the Model keeps the page from\n // rendering, and a caret that did not move keeps the format it carries.\n if (result.state === state && storedMarks === model.storedMarks) {\n return { model, commands: answering }\n }\n // History holds content, not cursor movement: a selection change keeps the\n // redo stack, and a no-op edit adds no step to undo.\n const contentChanged = result.state.document !== model.document\n return {\n model: {\n ...model,\n selection: result.state.selection,\n nextId,\n // A caret move ends the format it was carrying; a rule that applied may set the next.\n storedMarks:\n message._tag === 'Selected'\n ? null\n : ((fallback ? undefined : ruled?.storedMarks) ?? storedMarks),\n history: contentChanged\n ? RichText.commit(model.history, state, { group: RichText.groupFor(command) })\n : model.history,\n },\n outMessage: {\n _tag: 'Edited',\n state: result.state,\n changeSet: result.changeSet,\n transactions: result.transactions,\n },\n commands: [patch(model.hostId, result.state, result.changeSet), ...answering],\n }\n }),\n )\n}\n\n/** Undo or redo: history restores content and selection, and the host is told as a replace. */\nconst travel = (\n model: EditorView,\n state: RichText.EditorState,\n message: Extract<Message, { readonly _tag: 'Undone' | 'Redone' }>,\n): Update.ReturnWithOutMessage<EditorView, Message, OutMessage> => {\n const restored =\n message._tag === 'Undone'\n ? RichText.undo(model.history, state)\n : RichText.redo(model.history, state)\n if (restored === undefined) {\n return {\n model,\n outMessage: {\n _tag: 'Rejected',\n error: message._tag === 'Undone' ? 'NothingToUndo' : 'NothingToRedo',\n },\n }\n }\n const changeSet = replaceChangeSet(model.document, restored.state.document)\n return {\n model: {\n ...model,\n selection: restored.state.selection,\n history: restored.history,\n },\n outMessage: { _tag: 'Replaced', state: restored.state, changeSet },\n commands: [patch(model.hostId, restored.state, changeSet)],\n }\n}\n\nexport const Editor = Bundle.make({\n name: 'RichTextEditor',\n Model: EditorView,\n Message,\n args: Schema.Struct({ hostId: Schema.String }),\n // A read-only projection has no initial content of its own; the placement\n // writes only the interaction fields back, so this never becomes the document.\n // The host id is the one thing the child seeds: it is per-placement, and `read`\n // re-projects everything else.\n init: args => ({\n model: {\n document: RichText.Document.make({ version: 1, children: [] }),\n selection: null,\n nextId: 0,\n history: RichText.emptyHistory,\n storedMarks: null,\n menuIndex: 0,\n slashDismissed: Option.none(),\n hostId: args.hostId,\n },\n }),\n update: (model, incoming): Update.ReturnWithOutMessage<EditorView, Message, OutMessage> => {\n const result = transition(model, incoming)\n const out = result.outMessage\n // An edit or a replacement carries the state it committed; a rejection, none.\n const committed = out !== undefined && 'state' in out ? out.state : undefined\n if (committed !== undefined) carryKey(model.hostId, model.document, committed.document)\n // A dismissal ends with the query it closed, so a slash typed later opens a menu again.\n // The child's document is the parent's, so the edit is read from what it committed.\n const after = { ...result.model, document: committed?.document ?? result.model.document }\n return Option.isSome(result.model.slashDismissed) && !dismissed(after)\n ? { ...result, model: { ...result.model, slashDismissed: Option.none() } }\n : result\n },\n // The host element belongs to the view; everything below it belongs to the\n // interpreter the mount attaches there.\n view: editorView,\n})\n\nconst GotEditor = Link.wrapper('GotEditorMessage', Message)\n\nexport const ParentMessage = defineMessageUnion({ ...GotEditor.cases })\nexport type ParentMessage = typeof ParentMessage.Type\n\nconst editorLink: Link<\n Model,\n Wrapped<'GotEditorMessage', Message>,\n EditorView,\n Message\n> = Link.make({\n // The child sees the parent's document; the parent owns it.\n read: parent =>\n Option.some({\n document: parent.document,\n selection: parent.editor.selection,\n nextId: parent.editor.nextId,\n history: parent.editor.history,\n storedMarks: parent.editor.storedMarks,\n menuIndex: parent.editor.menuIndex,\n slashDismissed: parent.editor.slashDismissed,\n hostId: parent.editor.hostId,\n }),\n // Only interaction state is written back: the document is not the child's. `read` builds a\n // new view each time, so the Bundle cannot see that a child returned what it read; a child\n // whose fields are the parent's own leaves the parent as it was. The placement's `init`\n // writes into a parent that has no `editor` yet.\n write: (parent, { document: _document, ...editor }) => {\n const current: EditorState | undefined = parent.editor\n return current !== undefined &&\n (Object.keys(editor) as Array<keyof EditorState>).every(key => editor[key] === current[key])\n ? parent\n : { ...parent, editor }\n },\n wrapper: GotEditor,\n path: ['editor'],\n})\n\n/**\n * What a placement gives its editor. Each is placed by host id rather than passed as an arg\n * (§122): each holds functions or schemas, which a schema-decoded arg cannot describe.\n */\nexport interface EditorPlacement {\n /** How this editor's marks and node kinds render (§121). Defaults to `noRendering`. */\n readonly rendering?: RichText.Rendering | undefined\n /** The vocabulary its edits resolve against (§125). Defaults to none. */\n readonly vocabulary?: Vocabulary | undefined\n /** The rules applied to what is typed (§128). Defaults to none. */\n readonly inputRules?: ReadonlyArray<RichText.InputRule> | undefined\n /**\n * What is drawn over the document (§129), derived from it on every patch: code\n * highlighting, for one. Defaults to nothing.\n */\n readonly decorate?: Decorate | undefined\n /** What the editor shows while its document is blank (`RichText.isBlank`). Defaults to none. */\n readonly placeholder?: string | undefined\n /**\n * What the empty paragraph the caret is in shows, such as \"Type / for blocks\", as\n * `data-hint` on it. Defaults to none.\n */\n readonly lineHint?: string | undefined\n /**\n * Chords beside the built-in ones (Bold, Italic, Code, Strikethrough, undo and redo), checked\n * first: `{ chord: 'Mod-u', command: { type: 'ToggleMark', mark: 'Underline' } }` for a mark\n * of the application's own. Defaults to none.\n */\n readonly keymap?: ReadonlyArray<KeyBinding> | undefined\n /**\n * What its slash menu offers, which Enter resolves against: an application's own entries\n * (an image, a table, a callout) beside or instead of `slashEntries`. The application's menu\n * view draws the same list. Defaults to `slashEntries`.\n */\n readonly slashEntries?: ReadonlyArray<SlashEntry<EditorEvent>> | undefined\n /**\n * Whether this render is the server's (§145), such as `foldkit-ssr`'s `SSR.serving`. While it\n * is, the host carries the document's markup, which the browser's editor adopts instead of\n * drawing again. Defaults to never, so the host is empty until the editor mounts.\n */\n readonly serverRendered?: (() => boolean) | undefined\n}\n\n/**\n * Records everything a placement names for its host id, replacing what the id had: one call,\n * so a placement cannot half-apply. `editorAt` and the form control both place through it.\n */\nexport const placeEditor = (hostId: string, placement: EditorPlacement): void => {\n placeRendering(hostId, placement.rendering ?? RichText.noRendering)\n placeVocabulary(hostId, placement.vocabulary ?? {})\n placeInputRules(hostId, placement.inputRules ?? [])\n placeDecorations(hostId, placement.decorate ?? (() => []))\n // The overlay is set by Commands after placing, so a placement starts without the last one's.\n placeOverlay(hostId, [])\n placePlaceholders(hostId, {\n placeholder: placement.placeholder,\n lineHint: placement.lineHint,\n })\n placeSlashEntries(hostId, placement.slashEntries)\n placeKeymap(hostId, placement.keymap ?? [])\n placeServerRendered(hostId, placement.serverRendered ?? (() => false))\n}\n\n/**\n * Places one editor, bound to the host element the view renders and the patch Command\n * finds. Each placement picks its own id and names what it places; one call records all\n * of it, so a placement cannot half-apply.\n */\nexport const editorAt = (hostId: string, placement: EditorPlacement = {}) => {\n placeEditor(hostId, placement)\n return Editor.at(editorLink, {\n args: { hostId },\n // Runs with the child already written back, in the same parent transition.\n onOut: (out: OutMessage) => (parent: Model) =>\n out._tag === 'Edited' || out._tag === 'Replaced'\n ? {\n model: {\n ...parent,\n document: out.state.document,\n editor: { ...parent.editor, selection: out.state.selection },\n },\n }\n : { model: parent },\n })\n}\n\nexport const editor = editorAt('richtext-editor')\n\nexport const application = Bundle.assemble<Model, ParentMessage>()([editor])\n\n/** The parent's update: placement Messages route to the editor, others stand still. */\nexport const update = application.update()\n\n/** Wraps one editor Message as the parent Message that carries it. */\nexport const edited = (message: Message): ParentMessage => GotEditor.make(message)\nexport const typed = (text: string): ParentMessage => edited(Message.Typed({ text }))\nexport const pressed = (tag: 'Backspace' | 'DeletedForward' | 'Entered'): ParentMessage =>\n edited(Message[tag]())\nexport const toggled = (mark: string): ParentMessage => edited(Message.ToggledMark({ mark }))\nexport const applied = (mark: RichText.RunMark): ParentMessage =>\n edited(Message.AppliedMark({ mark }))\nexport const cleared = (mark: string): ParentMessage => edited(Message.ClearedMark({ mark }))\nexport const retyped = (block: RichText.TextBlock): ParentMessage =>\n edited(Message.RetypedBlock({ block }))\nexport const wrapped = (containers: ReadonlyArray<RichText.Container>): ParentMessage =>\n edited(Message.WrappedBlock({ containers }))\nexport const converted = (to: RichText.Container): ParentMessage =>\n edited(Message.ConvertedBlock({ to }))\nexport const lifted = (): ParentMessage => edited(Message.LiftedBlock())\nexport const moved = (node: RichText.NodeId, to: RichText.Beside): ParentMessage =>\n edited(Message.MovedBlock({ node, to }))\nexport const inserted = (block: RichText.Block, to?: RichText.Beside): ParentMessage =>\n edited(Message.InsertedBlock(to === undefined ? { block } : { block, to }))\nexport const deleted = (node: RichText.NodeId): ParentMessage =>\n edited(Message.DeletedBlock({ node }))\nexport const changedProps = (node: RichText.NodeId, props: Schema.JsonObject): ParentMessage =>\n edited(Message.ChangedProps({ node, props }))\nexport const selected = (selection: RichText.Selection | null): ParentMessage =>\n edited(Message.Selected({ selection }))\nexport const undone = (): ParentMessage => edited(Message.Undone())\nexport const redone = (): ParentMessage => edited(Message.Redone())\nexport const patched = (): ParentMessage => edited(Message.Patched())\n"],"mappings":"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"}
package/dist/editor.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as SlashMenu, c as focusEditor, d as patchEditor, f as redecorateEditor, g as toMessage, h as slashQuery, i as SlashEntry, l as heldDocument, m as slashMenu, n as EditorEvent, o as attachEditor, p as slashEntries, r as Message, s as events, t as EditorDrawing, u as matchingEntries } from "./editor-gCZiXgG4.mjs";
2
- export { EditorDrawing, EditorEvent, Message, SlashEntry, SlashMenu, attachEditor, events, focusEditor, heldDocument, matchingEntries, patchEditor, redecorateEditor, slashEntries, slashMenu, slashQuery, toMessage };
1
+ import { _ as toMessage, a as SlashMenu, c as events, d as matchingEntries, f as patchEditor, g as slashQuery, h as slashMenu, i as SlashEntry, l as focusEditor, m as slashEntries, n as EditorEvent, o as answerEditor, p as redecorateEditor, r as Message, s as attachEditor, t as EditorDrawing, u as heldDocument } from "./editor-Cmo24yol.mjs";
2
+ export { EditorDrawing, EditorEvent, Message, SlashEntry, SlashMenu, answerEditor, attachEditor, events, focusEditor, heldDocument, matchingEntries, patchEditor, redecorateEditor, slashEntries, slashMenu, slashQuery, toMessage };
package/dist/editor.mjs CHANGED
@@ -341,6 +341,11 @@ const patchEditor = (hostId, state, changeSet) => {
341
341
  attachment.sync(state, changeSet);
342
342
  return true;
343
343
  };
344
+ /** Tells the editor at `hostId` that an edit it asked for is drawn or refused (`Attachment.answered`). */
345
+ const answerEditor = (hostId) => {
346
+ const host = document.getElementById(hostId);
347
+ if (host !== null) attachmentIn(host)?.answered();
348
+ };
344
349
  /** Draws the decorations of the editor at `hostId` again; false when none is attached there. */
345
350
  const redecorateEditor = (hostId) => {
346
351
  const host = document.getElementById(hostId);
@@ -411,6 +416,6 @@ const events = Mount.defineStream("RichTextDomEvents", {
411
416
  })), () => Effect.sync(() => releaseMount(element))))
412
417
  });
413
418
  //#endregion
414
- export { Message, attachEditor, events, focusEditor, heldDocument, matchingEntries, patchEditor, redecorateEditor, slashEntries, slashMenu, slashQuery, toMessage };
419
+ export { Message, answerEditor, attachEditor, events, focusEditor, heldDocument, matchingEntries, patchEditor, redecorateEditor, slashEntries, slashMenu, slashQuery, toMessage };
415
420
 
416
421
  //# sourceMappingURL=editor.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.mjs","names":[],"sources":["../src/editor.ts"],"sourcesContent":["/**\n * The editor's Message vocabulary and the mount that produces it (§§31, 118).\n *\n * The DOM adapter reports what the browser asked for as commands, a caret, and a\n * history chord. This is what those mean to an editor's `update`, so one set of\n * Messages arrives whether a person typed, pasted, or moved the caret. The Bundle\n * proof in `controlled.ts` consumed these by hand; `events` is where the browser\n * produces them.\n */\nimport { Effect, Queue, Schema, Stream } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\nimport * as Mount from 'foldkit/mount'\nimport * as RichText from 'foldkit-richtext'\nimport {\n attachmentIn,\n decorationsFor,\n mountInto,\n keymapFor,\n placeholdersFor,\n releaseMount,\n renderingFor,\n vocabularyFor,\n} from './host.js'\nimport type { Decorate, KeyBinding } from './events.js'\n\nexport const Message = defineMessageUnion({\n Typed: { text: Schema.String },\n Backspace: {},\n DeletedForward: {},\n Entered: {},\n ToggledMark: { mark: Schema.String },\n /** Exactly this mark over the selection, or over the mark's extent at a caret: a link's new `href`. */\n AppliedMark: { mark: RichText.RunMark },\n /**\n * The named mark off the selection, or off the mark's extent at a caret: unlinking. A mark\n * value clears only the runs carrying exactly it.\n */\n ClearedMark: { mark: RichText.RunMark },\n RetypedBlock: { block: RichText.TextBlock },\n /** The caret's block, wrapped in containers listed outermost first: a quote, a list item. */\n WrappedBlock: { containers: Schema.Array(RichText.Container) },\n /** The caret's paragraph or heading, replaced by a kind that holds text: a code block. */\n ConvertedBlock: { to: RichText.Container },\n /** The caret's block, lifted out of its container: the inverse of a wrap. */\n LiftedBlock: {},\n /** A block moved before or after a sibling in its container: a block handle's up and down. */\n MovedBlock: { node: RichText.NodeId, to: RichText.Beside },\n /** A block put beside another, under fresh identities: an insert menu's choice, a Duplicate. */\n InsertedBlock: { block: RichText.Block, to: Schema.optionalKey(RichText.Beside) },\n /** A block and what it holds, deleted: a block handle's Delete. */\n DeletedBlock: { node: RichText.NodeId },\n /** A row above or below the caret's table cell. */\n InsertedRow: { where: Schema.Literals(['before', 'after']) },\n /** A column before or after the caret's table cell. */\n InsertedColumn: { where: Schema.Literals(['before', 'after']) },\n /** The caret's table row, deleted. */\n DeletedRow: {},\n /** The caret's table column, deleted. */\n DeletedColumn: {},\n /** Tab: indentation in code, the next cell in a table. */\n Indented: {},\n /**\n * Find and replace: the match at index `at` of `query`, or every match when `at` is absent,\n * becomes `replacement`, as one undo step.\n */\n ReplacedText: {\n query: Schema.String,\n replacement: Schema.String,\n caseSensitive: Schema.optionalKey(Schema.Boolean),\n at: Schema.optionalKey(Schema.Number),\n },\n /** `InsertFootnote`: a reference at the caret, its definition last, the caret in it. */\n InsertedFootnote: { text: Schema.optionalKey(Schema.String) },\n /** `RenameFootnote`: a footnote's label, on its definition and every reference. */\n RenamedFootnote: { from: Schema.String, to: Schema.String },\n /** Shift+Tab: less indentation in code, the previous cell in a table. */\n Outdented: {},\n /**\n * An adornment with an `action` was clicked: a code block's Copy, say. Not an edit, so the\n * editor changes nothing; it is the application's to act on.\n */\n ActivatedAdornment: { node: RichText.NodeId, action: Schema.String },\n /** Escape over a slash menu: it closes until its query ends, and Enter splits again. */\n DismissedSlash: {},\n /** Props of a node block, set: a task's checkbox, a toggle's arrow, an image's caption. */\n ChangedProps: { node: RichText.NodeId, props: Schema.JsonObject },\n Selected: { selection: Schema.NullOr(RichText.Selection) },\n Pasted: { slice: RichText.Slice },\n Undone: {},\n Redone: {},\n /** The patch Command's completion: Foldkit Commands report a Message, and a\n * render has nothing to say beyond that it happened. */\n Patched: {},\n})\nexport type Message = typeof Message.Type\n\n/**\n * What the DOM can ask for: the vocabulary without the patch acknowledgement, which only the\n * Command produces, and a slash menu's dismissal, which the application's menu sends. The adapter's stream is typed by this, so a\n * mount's result union names every Message it can actually emit.\n */\nexport type EditorEvent = Exclude<Message, { readonly _tag: 'Patched' | 'DismissedSlash' }>\n\n/**\n * What a browser intent means to an editor. The adapter reports only plain\n * insertions, so an insertion carrying marks is refused rather than quietly\n * losing them: what a marked insertion means is the editor's decision, not the\n * adapter's, and the adapter never has one to report.\n */\nexport const toMessage = (command: RichText.Command): EditorEvent | undefined => {\n switch (command.type) {\n case 'InsertText':\n return command.marks === undefined ? Message.Typed({ text: command.text }) : undefined\n case 'DeleteBackward':\n return Message.Backspace()\n case 'DeleteForward':\n return Message.DeletedForward()\n case 'SplitBlock':\n return Message.Entered()\n case 'ToggleMark':\n // The adapter toggles by name; a mark value carrying props is not\n // expressible as a toggle, so it is refused rather than stripped.\n return typeof command.mark === 'string'\n ? Message.ToggledMark({ mark: command.mark })\n : undefined\n case 'Paste':\n return Message.Pasted({ slice: command.slice })\n case 'SetProps':\n return Message.ChangedProps({ node: command.node, props: command.props })\n case 'Indent':\n return Message.Indented()\n case 'Outdent':\n return Message.Outdented()\n default:\n return undefined\n }\n}\n\n/**\n * The slash menu's vocabulary (§123, §124 §11): what opens a menu, what it offers,\n * what a query matches, and what a chosen entry sends. An entry carries one of this\n * module's Messages, not a command, so the Bundle resolves Enter by handling the chosen\n * entry as the Message a click would send — which is also what makes a mark entry update\n * the caret's stored marks rather than run a collapsed toggle the command layer treats as\n * a no-op.\n *\n * Whether a caret is in a query is a read of the document (`RichText.textBefore`),\n * not a flag. Nothing here holds state.\n */\nexport interface SlashEntry<Payload> {\n /** Stable id, not the label: how a list keys the entry and moves by it. */\n readonly id: string\n /** What the menu shows. */\n readonly label: string\n /** Words a query may match besides the label. */\n readonly keywords: ReadonlyArray<string>\n /** What choosing this entry sends: an editor Message here, a caller's in a view. */\n readonly message: Payload\n /** A line under the label saying what the entry makes. */\n readonly description?: string | undefined\n /** The heading the entry is listed under while no query narrows the menu. */\n readonly group?: string | undefined\n /** The icon a menu draws for it, by name; a view's own set says what names it knows. */\n readonly icon?: string | undefined\n}\n\n/**\n * The query the caret is in, or `undefined` when the text before it is not a slash\n * command. A command opens at a block's start or after whitespace — `see /head` opens,\n * `see/head` is text — and reads letters, digits, and `-`, so the query is a word\n * rather than everything typed since the slash.\n */\nexport const slashQuery = (textBefore: string): string | undefined =>\n /(?:^|\\s)\\/([\\p{L}\\p{N}-]*)$/u.exec(textBefore)?.[1]\n\nconst HEADINGS: ReadonlyArray<{\n readonly level: 1 | 2 | 3\n readonly label: string\n readonly keywords: ReadonlyArray<string>\n readonly description: string\n}> = [\n { level: 1, label: 'Heading 1', keywords: ['h1', 'title'], description: 'A title' },\n { level: 2, label: 'Heading 2', keywords: ['h2', 'subtitle'], description: 'A section' },\n { level: 3, label: 'Heading 3', keywords: ['h3', 'section'], description: 'A subsection' },\n]\n\n/** What a mark is also searched by, and what its entry says it does. */\nconst MARK_ENTRIES: Readonly<\n Record<string, { readonly keywords: ReadonlyArray<string>; readonly description: string }>\n> = {\n Bold: { keywords: ['strong', 'b'], description: 'Strong emphasis' },\n Italic: { keywords: ['em', 'i'], description: 'Emphasis' },\n Code: { keywords: ['monospace'], description: 'Code within a line' },\n}\n\n/**\n * The entries the editor offers, in menu order: the text blocks a caret can become, the\n * standard vocabulary's quote, lists, and code block, then the marks it can carry. Each is a\n * Message this module already defines, so a chosen entry needs no editing vocabulary of its\n * own. The standard kinds are named, not required: a placement whose vocabulary lacks them\n * refuses the entry's edit, as it refuses any edit it does not declare.\n */\nexport const slashEntries: ReadonlyArray<SlashEntry<EditorEvent>> = [\n {\n id: 'paragraph',\n label: 'Paragraph',\n keywords: ['text', 'body'],\n message: Message.RetypedBlock({ block: { type: 'Paragraph' } }),\n description: 'Plain text',\n group: 'Text',\n icon: 'paragraph',\n },\n ...HEADINGS.map(heading => ({\n id: `heading-${heading.level}`,\n label: heading.label,\n keywords: heading.keywords,\n message: Message.RetypedBlock({ block: { type: 'Heading', level: heading.level } }),\n description: heading.description,\n group: 'Text',\n icon: `heading-${heading.level}`,\n })),\n {\n id: 'quote',\n label: 'Quote',\n keywords: ['blockquote', 'citation'],\n message: Message.WrappedBlock({ containers: [{ kind: 'Quote' }] }),\n description: 'Words set apart',\n group: 'Text',\n icon: 'quote',\n },\n {\n id: 'bulleted-list',\n label: 'Bulleted list',\n keywords: ['ul', 'unordered', 'bullet'],\n message: Message.WrappedBlock({ containers: [{ kind: 'List' }, { kind: 'ListItem' }] }),\n description: 'Points in no order',\n group: 'Lists',\n icon: 'bulleted-list',\n },\n {\n id: 'numbered-list',\n label: 'Numbered list',\n keywords: ['ol', 'ordered'],\n message: Message.WrappedBlock({\n containers: [{ kind: 'List', props: { ordered: true } }, { kind: 'ListItem' }],\n }),\n description: 'Steps in order',\n group: 'Lists',\n icon: 'numbered-list',\n },\n {\n // `code` is the Code mark's id; the block is a different entry.\n id: 'code-block',\n label: 'Code block',\n keywords: ['pre', 'fence', 'snippet'],\n message: Message.ConvertedBlock({ to: { kind: 'CodeBlock' } }),\n description: 'Code, kept as typed',\n group: 'Blocks',\n icon: 'code-block',\n },\n ...RichText.shippedMarks.map(definition => ({\n id: definition.name.toLowerCase(),\n label: definition.name,\n keywords: MARK_ENTRIES[definition.name]?.keywords ?? [],\n message: Message.ToggledMark({ mark: definition.name }),\n description: MARK_ENTRIES[definition.name]?.description,\n group: 'Formatting',\n icon: definition.name.toLowerCase(),\n })),\n]\n\n/** How well an entry answers a query: lower is better, `undefined` is no match. */\nconst rank = (entry: SlashEntry<unknown>, needle: string): number | undefined => {\n const label = entry.label.toLowerCase()\n if (label.startsWith(needle)) return 0\n if (label.split(/\\s+/).some(word => word.startsWith(needle))) return 1\n if (entry.keywords.some(word => word.toLowerCase().startsWith(needle))) return 2\n if ([label, ...entry.keywords].some(word => word.toLowerCase().includes(needle))) return 3\n return undefined\n}\n\n/**\n * What `/` alone offers: every entry, each group's together in the order its first entry comes,\n * so the list a menu draws under its headings is the list the keys move through.\n */\nconst grouped = <Payload>(\n entries: ReadonlyArray<SlashEntry<Payload>>,\n): ReadonlyArray<SlashEntry<Payload>> => {\n const groups = new Map<string | undefined, Array<SlashEntry<Payload>>>()\n for (const entry of entries) {\n const group = groups.get(entry.group)\n if (group === undefined) groups.set(entry.group, [entry])\n else group.push(entry)\n }\n return [...groups.values()].flat()\n}\n\n/**\n * The entries a query matches, case-insensitively, the best first: a label it starts, a word of\n * a label it starts, a keyword it starts, then any it appears in, each in catalogue order.\n * Every entry, grouped, when the query is empty, which is what `/` alone offers.\n */\nexport const matchingEntries = <Payload>(\n entries: ReadonlyArray<SlashEntry<Payload>>,\n query: string,\n): ReadonlyArray<SlashEntry<Payload>> => {\n const needle = query.trim().toLowerCase()\n if (needle.length === 0) return grouped(entries)\n return entries\n .flatMap(entry => {\n const score = rank(entry, needle)\n return score === undefined ? [] : [{ entry, score }]\n })\n .sort((left, right) => left.score - right.score)\n .map(({ entry }) => entry)\n}\n\n/** What a menu shows for one caret: its query, what matches, and what Enter would send. */\nexport interface SlashMenu<Payload> {\n readonly query: string\n readonly matches: ReadonlyArray<SlashEntry<Payload>>\n /** The entry Enter would choose; undefined when nothing matches the query. */\n readonly highlighted: SlashEntry<Payload> | undefined\n}\n\n/**\n * The menu the caret is in, or `undefined` when its text is not a slash command — the\n * one value that decides both whether to render a menu and what Enter means, so the\n * view and `update` cannot disagree.\n *\n * `index` is what the menu last highlighted. A stale index — fewer matches than it\n * named, or a negative one — falls back to the first match, because a query that\n * narrows must not leave Enter with nothing to choose. A query that matches nothing is\n * still a menu: it renders as empty, and `highlighted` is undefined, which is what\n * keeps `/zzz` from choosing anything.\n */\nexport const slashMenu = <Payload>(\n entries: ReadonlyArray<SlashEntry<Payload>>,\n textBefore: string,\n index: number,\n): SlashMenu<Payload> | undefined => {\n const query = slashQuery(textBefore)\n if (query === undefined) return undefined\n const matches = matchingEntries(entries, query)\n return { query, matches, highlighted: matches[index] ?? matches[0] }\n}\n\n/** How an attached editor draws: its rendering registry and what it draws over the document. */\nexport interface EditorDrawing {\n readonly rendering?: RichText.Rendering | undefined\n readonly decorate?: Decorate | undefined\n /** What a blank document shows. */\n readonly placeholder?: string | undefined\n /** What the empty paragraph the caret is in shows. */\n readonly lineHint?: string | undefined\n /** The node vocabulary, which says where Tab means something (`RichText.takesTab`). */\n readonly nodes?: RichText.NodeRegistry | undefined\n /** Chords beside the built-in ones, checked first (`AttachOptions.keymap`). */\n readonly keymap?: ReadonlyArray<KeyBinding> | undefined\n}\n\n/**\n * Attaches the translation to a host element and reports each Message through\n * `emit`. Separate from the mount so a test can drive the DOM without pulling a\n * stream, and so a caller embedding the editor directly can say how it draws.\n */\nexport const attachEditor = (\n host: Element,\n content: RichText.Document,\n emit: (message: EditorEvent) => void,\n drawing: EditorDrawing = {},\n) =>\n mountInto(\n host,\n content,\n {\n onIntent: command => {\n const message = toMessage(command)\n if (message !== undefined) emit(message)\n },\n onHistory: direction => emit(direction === 'undo' ? Message.Undone() : Message.Redone()),\n onSelection: selection => emit(Message.Selected({ selection })),\n onAction: (node, action) => emit(Message.ActivatedAdornment({ node, action })),\n decorate: drawing.decorate,\n nodes: drawing.nodes,\n placeholder: drawing.placeholder,\n lineHint: drawing.lineHint,\n keymap: drawing.keymap,\n },\n drawing.rendering,\n )\n\n/**\n * The patch Command's work: find the element the view gave an id to and sync the\n * attachment it holds. A missing host is not an error — the editor went away\n * while the transition was in flight — so it reports whether it patched.\n */\nexport const patchEditor = (\n hostId: string,\n state: RichText.EditorState,\n changeSet: RichText.ChangeSet,\n): boolean => {\n const host = document.getElementById(hostId)\n if (host === null) return false\n const attachment = attachmentIn(host)\n if (attachment === undefined) return false\n attachment.sync(state, changeSet)\n return true\n}\n\n/** Draws the decorations of the editor at `hostId` again; false when none is attached there. */\nexport const redecorateEditor = (hostId: string): boolean => {\n const host = document.getElementById(hostId)\n const attachment = host === null ? undefined : attachmentIn(host)\n attachment?.redecorate()\n return attachment !== undefined\n}\n\n/**\n * Focuses the editor at `hostId` with `selection` in the browser (`Attachment.focus`); false\n * when none is attached there.\n */\nexport const focusEditor = (hostId: string, selection: RichText.Selection): boolean => {\n const host = document.getElementById(hostId)\n const attachment = host === null ? undefined : attachmentIn(host)\n attachment?.focus(selection)\n return attachment !== undefined\n}\n\n/**\n * The latest document the editor at `hostId` holds (`Attachment.held`), or undefined when none\n * is attached there.\n */\nexport const heldDocument = (hostId: string): RichText.Document | undefined => {\n const host = document.getElementById(hostId)\n return host === null ? undefined : attachmentIn(host)?.held()\n}\n\n/** The editor's events as a mount: one attachment per element, released with it.\n * The rendering registry is looked up by the host id the placement recorded\n * (§122), so it reaches the mount without entering a Model or a mount's args. */\nexport const events = Mount.defineStream('RichTextDomEvents', {\n args: { content: RichText.Document },\n messages: [\n Message.Typed,\n Message.Backspace,\n Message.DeletedForward,\n Message.Entered,\n Message.ToggledMark,\n Message.AppliedMark,\n Message.ClearedMark,\n Message.RetypedBlock,\n Message.WrappedBlock,\n Message.ConvertedBlock,\n Message.LiftedBlock,\n Message.MovedBlock,\n Message.InsertedBlock,\n Message.DeletedBlock,\n Message.ChangedProps,\n Message.InsertedRow,\n Message.InsertedColumn,\n Message.DeletedRow,\n Message.DeletedColumn,\n Message.Indented,\n Message.Outdented,\n Message.ReplacedText,\n Message.InsertedFootnote,\n Message.RenamedFootnote,\n Message.ActivatedAdornment,\n Message.Selected,\n Message.Pasted,\n Message.Undone,\n Message.Redone,\n ],\n execute: ({ element, content }) =>\n Stream.callback<EditorEvent>(queue =>\n Effect.acquireRelease(\n Effect.sync(() =>\n attachEditor(element, content, message => Queue.offerUnsafe(queue, message), {\n rendering: renderingFor(element.id),\n decorate: decorationsFor(element.id),\n ...placeholdersFor(element.id),\n nodes: vocabularyFor(element.id).nodes,\n keymap: keymapFor(element.id),\n }),\n ),\n () => Effect.sync(() => releaseMount(element)),\n ),\n ),\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"editor.mjs","names":[],"sources":["../src/editor.ts"],"sourcesContent":["/**\n * The editor's Message vocabulary and the mount that produces it (§§31, 118).\n *\n * The DOM adapter reports what the browser asked for as commands, a caret, and a\n * history chord. This is what those mean to an editor's `update`, so one set of\n * Messages arrives whether a person typed, pasted, or moved the caret. The Bundle\n * proof in `controlled.ts` consumed these by hand; `events` is where the browser\n * produces them.\n */\nimport { Effect, Queue, Schema, Stream } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\nimport * as Mount from 'foldkit/mount'\nimport * as RichText from 'foldkit-richtext'\nimport {\n attachmentIn,\n decorationsFor,\n mountInto,\n keymapFor,\n placeholdersFor,\n releaseMount,\n renderingFor,\n vocabularyFor,\n} from './host.js'\nimport type { Decorate, KeyBinding } from './events.js'\n\nexport const Message = defineMessageUnion({\n Typed: { text: Schema.String },\n Backspace: {},\n DeletedForward: {},\n Entered: {},\n ToggledMark: { mark: Schema.String },\n /** Exactly this mark over the selection, or over the mark's extent at a caret: a link's new `href`. */\n AppliedMark: { mark: RichText.RunMark },\n /**\n * The named mark off the selection, or off the mark's extent at a caret: unlinking. A mark\n * value clears only the runs carrying exactly it.\n */\n ClearedMark: { mark: RichText.RunMark },\n RetypedBlock: { block: RichText.TextBlock },\n /** The caret's block, wrapped in containers listed outermost first: a quote, a list item. */\n WrappedBlock: { containers: Schema.Array(RichText.Container) },\n /** The caret's paragraph or heading, replaced by a kind that holds text: a code block. */\n ConvertedBlock: { to: RichText.Container },\n /** The caret's block, lifted out of its container: the inverse of a wrap. */\n LiftedBlock: {},\n /** A block moved before or after a sibling in its container: a block handle's up and down. */\n MovedBlock: { node: RichText.NodeId, to: RichText.Beside },\n /** A block put beside another, under fresh identities: an insert menu's choice, a Duplicate. */\n InsertedBlock: { block: RichText.Block, to: Schema.optionalKey(RichText.Beside) },\n /** A block and what it holds, deleted: a block handle's Delete. */\n DeletedBlock: { node: RichText.NodeId },\n /** A row above or below the caret's table cell. */\n InsertedRow: { where: Schema.Literals(['before', 'after']) },\n /** A column before or after the caret's table cell. */\n InsertedColumn: { where: Schema.Literals(['before', 'after']) },\n /** The caret's table row, deleted. */\n DeletedRow: {},\n /** The caret's table column, deleted. */\n DeletedColumn: {},\n /** Tab: indentation in code, the next cell in a table. */\n Indented: {},\n /**\n * Find and replace: the match at index `at` of `query`, or every match when `at` is absent,\n * becomes `replacement`, as one undo step.\n */\n ReplacedText: {\n query: Schema.String,\n replacement: Schema.String,\n caseSensitive: Schema.optionalKey(Schema.Boolean),\n at: Schema.optionalKey(Schema.Number),\n },\n /** `InsertFootnote`: a reference at the caret, its definition last, the caret in it. */\n InsertedFootnote: { text: Schema.optionalKey(Schema.String) },\n /** `RenameFootnote`: a footnote's label, on its definition and every reference. */\n RenamedFootnote: { from: Schema.String, to: Schema.String },\n /** Shift+Tab: less indentation in code, the previous cell in a table. */\n Outdented: {},\n /**\n * An adornment with an `action` was clicked: a code block's Copy, say. Not an edit, so the\n * editor changes nothing; it is the application's to act on.\n */\n ActivatedAdornment: { node: RichText.NodeId, action: Schema.String },\n /** Escape over a slash menu: it closes until its query ends, and Enter splits again. */\n DismissedSlash: {},\n /** Props of a node block, set: a task's checkbox, a toggle's arrow, an image's caption. */\n ChangedProps: { node: RichText.NodeId, props: Schema.JsonObject },\n Selected: { selection: Schema.NullOr(RichText.Selection) },\n Pasted: { slice: RichText.Slice },\n Undone: {},\n Redone: {},\n /** The patch Command's completion: Foldkit Commands report a Message, and a\n * render has nothing to say beyond that it happened. */\n Patched: {},\n})\nexport type Message = typeof Message.Type\n\n/**\n * What the DOM can ask for: the vocabulary without the patch acknowledgement, which only the\n * Command produces, and a slash menu's dismissal, which the application's menu sends. The adapter's stream is typed by this, so a\n * mount's result union names every Message it can actually emit.\n */\nexport type EditorEvent = Exclude<Message, { readonly _tag: 'Patched' | 'DismissedSlash' }>\n\n/**\n * What a browser intent means to an editor. The adapter reports only plain\n * insertions, so an insertion carrying marks is refused rather than quietly\n * losing them: what a marked insertion means is the editor's decision, not the\n * adapter's, and the adapter never has one to report.\n */\nexport const toMessage = (command: RichText.Command): EditorEvent | undefined => {\n switch (command.type) {\n case 'InsertText':\n return command.marks === undefined ? Message.Typed({ text: command.text }) : undefined\n case 'DeleteBackward':\n return Message.Backspace()\n case 'DeleteForward':\n return Message.DeletedForward()\n case 'SplitBlock':\n return Message.Entered()\n case 'ToggleMark':\n // The adapter toggles by name; a mark value carrying props is not\n // expressible as a toggle, so it is refused rather than stripped.\n return typeof command.mark === 'string'\n ? Message.ToggledMark({ mark: command.mark })\n : undefined\n case 'Paste':\n return Message.Pasted({ slice: command.slice })\n case 'SetProps':\n return Message.ChangedProps({ node: command.node, props: command.props })\n case 'Indent':\n return Message.Indented()\n case 'Outdent':\n return Message.Outdented()\n default:\n return undefined\n }\n}\n\n/**\n * The slash menu's vocabulary (§123, §124 §11): what opens a menu, what it offers,\n * what a query matches, and what a chosen entry sends. An entry carries one of this\n * module's Messages, not a command, so the Bundle resolves Enter by handling the chosen\n * entry as the Message a click would send — which is also what makes a mark entry update\n * the caret's stored marks rather than run a collapsed toggle the command layer treats as\n * a no-op.\n *\n * Whether a caret is in a query is a read of the document (`RichText.textBefore`),\n * not a flag. Nothing here holds state.\n */\nexport interface SlashEntry<Payload> {\n /** Stable id, not the label: how a list keys the entry and moves by it. */\n readonly id: string\n /** What the menu shows. */\n readonly label: string\n /** Words a query may match besides the label. */\n readonly keywords: ReadonlyArray<string>\n /** What choosing this entry sends: an editor Message here, a caller's in a view. */\n readonly message: Payload\n /** A line under the label saying what the entry makes. */\n readonly description?: string | undefined\n /** The heading the entry is listed under while no query narrows the menu. */\n readonly group?: string | undefined\n /** The icon a menu draws for it, by name; a view's own set says what names it knows. */\n readonly icon?: string | undefined\n}\n\n/**\n * The query the caret is in, or `undefined` when the text before it is not a slash\n * command. A command opens at a block's start or after whitespace — `see /head` opens,\n * `see/head` is text — and reads letters, digits, and `-`, so the query is a word\n * rather than everything typed since the slash.\n */\nexport const slashQuery = (textBefore: string): string | undefined =>\n /(?:^|\\s)\\/([\\p{L}\\p{N}-]*)$/u.exec(textBefore)?.[1]\n\nconst HEADINGS: ReadonlyArray<{\n readonly level: 1 | 2 | 3\n readonly label: string\n readonly keywords: ReadonlyArray<string>\n readonly description: string\n}> = [\n { level: 1, label: 'Heading 1', keywords: ['h1', 'title'], description: 'A title' },\n { level: 2, label: 'Heading 2', keywords: ['h2', 'subtitle'], description: 'A section' },\n { level: 3, label: 'Heading 3', keywords: ['h3', 'section'], description: 'A subsection' },\n]\n\n/** What a mark is also searched by, and what its entry says it does. */\nconst MARK_ENTRIES: Readonly<\n Record<string, { readonly keywords: ReadonlyArray<string>; readonly description: string }>\n> = {\n Bold: { keywords: ['strong', 'b'], description: 'Strong emphasis' },\n Italic: { keywords: ['em', 'i'], description: 'Emphasis' },\n Code: { keywords: ['monospace'], description: 'Code within a line' },\n}\n\n/**\n * The entries the editor offers, in menu order: the text blocks a caret can become, the\n * standard vocabulary's quote, lists, and code block, then the marks it can carry. Each is a\n * Message this module already defines, so a chosen entry needs no editing vocabulary of its\n * own. The standard kinds are named, not required: a placement whose vocabulary lacks them\n * refuses the entry's edit, as it refuses any edit it does not declare.\n */\nexport const slashEntries: ReadonlyArray<SlashEntry<EditorEvent>> = [\n {\n id: 'paragraph',\n label: 'Paragraph',\n keywords: ['text', 'body'],\n message: Message.RetypedBlock({ block: { type: 'Paragraph' } }),\n description: 'Plain text',\n group: 'Text',\n icon: 'paragraph',\n },\n ...HEADINGS.map(heading => ({\n id: `heading-${heading.level}`,\n label: heading.label,\n keywords: heading.keywords,\n message: Message.RetypedBlock({ block: { type: 'Heading', level: heading.level } }),\n description: heading.description,\n group: 'Text',\n icon: `heading-${heading.level}`,\n })),\n {\n id: 'quote',\n label: 'Quote',\n keywords: ['blockquote', 'citation'],\n message: Message.WrappedBlock({ containers: [{ kind: 'Quote' }] }),\n description: 'Words set apart',\n group: 'Text',\n icon: 'quote',\n },\n {\n id: 'bulleted-list',\n label: 'Bulleted list',\n keywords: ['ul', 'unordered', 'bullet'],\n message: Message.WrappedBlock({ containers: [{ kind: 'List' }, { kind: 'ListItem' }] }),\n description: 'Points in no order',\n group: 'Lists',\n icon: 'bulleted-list',\n },\n {\n id: 'numbered-list',\n label: 'Numbered list',\n keywords: ['ol', 'ordered'],\n message: Message.WrappedBlock({\n containers: [{ kind: 'List', props: { ordered: true } }, { kind: 'ListItem' }],\n }),\n description: 'Steps in order',\n group: 'Lists',\n icon: 'numbered-list',\n },\n {\n // `code` is the Code mark's id; the block is a different entry.\n id: 'code-block',\n label: 'Code block',\n keywords: ['pre', 'fence', 'snippet'],\n message: Message.ConvertedBlock({ to: { kind: 'CodeBlock' } }),\n description: 'Code, kept as typed',\n group: 'Blocks',\n icon: 'code-block',\n },\n ...RichText.shippedMarks.map(definition => ({\n id: definition.name.toLowerCase(),\n label: definition.name,\n keywords: MARK_ENTRIES[definition.name]?.keywords ?? [],\n message: Message.ToggledMark({ mark: definition.name }),\n description: MARK_ENTRIES[definition.name]?.description,\n group: 'Formatting',\n icon: definition.name.toLowerCase(),\n })),\n]\n\n/** How well an entry answers a query: lower is better, `undefined` is no match. */\nconst rank = (entry: SlashEntry<unknown>, needle: string): number | undefined => {\n const label = entry.label.toLowerCase()\n if (label.startsWith(needle)) return 0\n if (label.split(/\\s+/).some(word => word.startsWith(needle))) return 1\n if (entry.keywords.some(word => word.toLowerCase().startsWith(needle))) return 2\n if ([label, ...entry.keywords].some(word => word.toLowerCase().includes(needle))) return 3\n return undefined\n}\n\n/**\n * What `/` alone offers: every entry, each group's together in the order its first entry comes,\n * so the list a menu draws under its headings is the list the keys move through.\n */\nconst grouped = <Payload>(\n entries: ReadonlyArray<SlashEntry<Payload>>,\n): ReadonlyArray<SlashEntry<Payload>> => {\n const groups = new Map<string | undefined, Array<SlashEntry<Payload>>>()\n for (const entry of entries) {\n const group = groups.get(entry.group)\n if (group === undefined) groups.set(entry.group, [entry])\n else group.push(entry)\n }\n return [...groups.values()].flat()\n}\n\n/**\n * The entries a query matches, case-insensitively, the best first: a label it starts, a word of\n * a label it starts, a keyword it starts, then any it appears in, each in catalogue order.\n * Every entry, grouped, when the query is empty, which is what `/` alone offers.\n */\nexport const matchingEntries = <Payload>(\n entries: ReadonlyArray<SlashEntry<Payload>>,\n query: string,\n): ReadonlyArray<SlashEntry<Payload>> => {\n const needle = query.trim().toLowerCase()\n if (needle.length === 0) return grouped(entries)\n return entries\n .flatMap(entry => {\n const score = rank(entry, needle)\n return score === undefined ? [] : [{ entry, score }]\n })\n .sort((left, right) => left.score - right.score)\n .map(({ entry }) => entry)\n}\n\n/** What a menu shows for one caret: its query, what matches, and what Enter would send. */\nexport interface SlashMenu<Payload> {\n readonly query: string\n readonly matches: ReadonlyArray<SlashEntry<Payload>>\n /** The entry Enter would choose; undefined when nothing matches the query. */\n readonly highlighted: SlashEntry<Payload> | undefined\n}\n\n/**\n * The menu the caret is in, or `undefined` when its text is not a slash command — the\n * one value that decides both whether to render a menu and what Enter means, so the\n * view and `update` cannot disagree.\n *\n * `index` is what the menu last highlighted. A stale index — fewer matches than it\n * named, or a negative one — falls back to the first match, because a query that\n * narrows must not leave Enter with nothing to choose. A query that matches nothing is\n * still a menu: it renders as empty, and `highlighted` is undefined, which is what\n * keeps `/zzz` from choosing anything.\n */\nexport const slashMenu = <Payload>(\n entries: ReadonlyArray<SlashEntry<Payload>>,\n textBefore: string,\n index: number,\n): SlashMenu<Payload> | undefined => {\n const query = slashQuery(textBefore)\n if (query === undefined) return undefined\n const matches = matchingEntries(entries, query)\n return { query, matches, highlighted: matches[index] ?? matches[0] }\n}\n\n/** How an attached editor draws: its rendering registry and what it draws over the document. */\nexport interface EditorDrawing {\n readonly rendering?: RichText.Rendering | undefined\n readonly decorate?: Decorate | undefined\n /** What a blank document shows. */\n readonly placeholder?: string | undefined\n /** What the empty paragraph the caret is in shows. */\n readonly lineHint?: string | undefined\n /** The node vocabulary, which says where Tab means something (`RichText.takesTab`). */\n readonly nodes?: RichText.NodeRegistry | undefined\n /** Chords beside the built-in ones, checked first (`AttachOptions.keymap`). */\n readonly keymap?: ReadonlyArray<KeyBinding> | undefined\n}\n\n/**\n * Attaches the translation to a host element and reports each Message through\n * `emit`. Separate from the mount so a test can drive the DOM without pulling a\n * stream, and so a caller embedding the editor directly can say how it draws.\n */\nexport const attachEditor = (\n host: Element,\n content: RichText.Document,\n emit: (message: EditorEvent) => void,\n drawing: EditorDrawing = {},\n) =>\n mountInto(\n host,\n content,\n {\n onIntent: command => {\n const message = toMessage(command)\n if (message !== undefined) emit(message)\n },\n onHistory: direction => emit(direction === 'undo' ? Message.Undone() : Message.Redone()),\n onSelection: selection => emit(Message.Selected({ selection })),\n onAction: (node, action) => emit(Message.ActivatedAdornment({ node, action })),\n decorate: drawing.decorate,\n nodes: drawing.nodes,\n placeholder: drawing.placeholder,\n lineHint: drawing.lineHint,\n keymap: drawing.keymap,\n },\n drawing.rendering,\n )\n\n/**\n * The patch Command's work: find the element the view gave an id to and sync the\n * attachment it holds. A missing host is not an error — the editor went away\n * while the transition was in flight — so it reports whether it patched.\n */\nexport const patchEditor = (\n hostId: string,\n state: RichText.EditorState,\n changeSet: RichText.ChangeSet,\n): boolean => {\n const host = document.getElementById(hostId)\n if (host === null) return false\n const attachment = attachmentIn(host)\n if (attachment === undefined) return false\n attachment.sync(state, changeSet)\n return true\n}\n\n/** Tells the editor at `hostId` that an edit it asked for is drawn or refused (`Attachment.answered`). */\nexport const answerEditor = (hostId: string): void => {\n const host = document.getElementById(hostId)\n if (host !== null) attachmentIn(host)?.answered()\n}\n\n/** Draws the decorations of the editor at `hostId` again; false when none is attached there. */\nexport const redecorateEditor = (hostId: string): boolean => {\n const host = document.getElementById(hostId)\n const attachment = host === null ? undefined : attachmentIn(host)\n attachment?.redecorate()\n return attachment !== undefined\n}\n\n/**\n * Focuses the editor at `hostId` with `selection` in the browser (`Attachment.focus`); false\n * when none is attached there.\n */\nexport const focusEditor = (hostId: string, selection: RichText.Selection): boolean => {\n const host = document.getElementById(hostId)\n const attachment = host === null ? undefined : attachmentIn(host)\n attachment?.focus(selection)\n return attachment !== undefined\n}\n\n/**\n * The latest document the editor at `hostId` holds (`Attachment.held`), or undefined when none\n * is attached there.\n */\nexport const heldDocument = (hostId: string): RichText.Document | undefined => {\n const host = document.getElementById(hostId)\n return host === null ? undefined : attachmentIn(host)?.held()\n}\n\n/** The editor's events as a mount: one attachment per element, released with it.\n * The rendering registry is looked up by the host id the placement recorded\n * (§122), so it reaches the mount without entering a Model or a mount's args. */\nexport const events = Mount.defineStream('RichTextDomEvents', {\n args: { content: RichText.Document },\n messages: [\n Message.Typed,\n Message.Backspace,\n Message.DeletedForward,\n Message.Entered,\n Message.ToggledMark,\n Message.AppliedMark,\n Message.ClearedMark,\n Message.RetypedBlock,\n Message.WrappedBlock,\n Message.ConvertedBlock,\n Message.LiftedBlock,\n Message.MovedBlock,\n Message.InsertedBlock,\n Message.DeletedBlock,\n Message.ChangedProps,\n Message.InsertedRow,\n Message.InsertedColumn,\n Message.DeletedRow,\n Message.DeletedColumn,\n Message.Indented,\n Message.Outdented,\n Message.ReplacedText,\n Message.InsertedFootnote,\n Message.RenamedFootnote,\n Message.ActivatedAdornment,\n Message.Selected,\n Message.Pasted,\n Message.Undone,\n Message.Redone,\n ],\n execute: ({ element, content }) =>\n Stream.callback<EditorEvent>(queue =>\n Effect.acquireRelease(\n Effect.sync(() =>\n attachEditor(element, content, message => Queue.offerUnsafe(queue, message), {\n rendering: renderingFor(element.id),\n decorate: decorationsFor(element.id),\n ...placeholdersFor(element.id),\n nodes: vocabularyFor(element.id).nodes,\n keymap: keymapFor(element.id),\n }),\n ),\n () => Effect.sync(() => releaseMount(element)),\n ),\n ),\n})\n"],"mappings":"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"}
@@ -105,6 +105,11 @@ interface Attachment {
105
105
  readonly held: () => RichText.Document;
106
106
  /** True between compositionstart and compositionend. */
107
107
  readonly composing: () => boolean;
108
+ /**
109
+ * Tells it an edit it asked for is drawn, or refused: input that came after the ask was held
110
+ * until then, and goes on when every ask is answered. The editor answers each, in order.
111
+ */
112
+ readonly answered: () => void;
108
113
  readonly detach: () => void;
109
114
  }
110
115
  /**
@@ -115,4 +120,4 @@ interface Attachment {
115
120
  declare const attach: (dom: EditorDom, options: AttachOptions) => Attachment;
116
121
  //#endregion
117
122
  export { KeyBinding as a, intentFor as c, Intent as i, readSelection as l, Attachment as n, SLICE_CLIPBOARD_TYPE as o, Decorate as r, attach as s, AttachOptions as t, restoreSelection as u };
118
- //# sourceMappingURL=events-DLi6ecvD.d.mts.map
123
+ //# sourceMappingURL=events-De4SvZil.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events-DLi6ecvD.d.mts","names":[],"sources":["../src/events.ts"],"mappings":";;;UAkBiB;;WAEN,UAAU,SAAS;;WAEnB;WACA;;;;;;;;UASM;;WAEN;WACA,SAAS,SAAS;;;;;;;;;;cAkDhB,YAAS,OACb,OAAK,qBAAA,SAEJ,cAAc,gBACrB;cAmEU,gBAAa,KAAS,cAAY,SAAS;;;;;;cA4B3C,mBAAgB,KAAS,WAAS,WAAa,SAAS;;cA4BxD;UAOI;;WAEN,WAAW,SAAS,SAAS;;WAE7B,aAAa;;;;;;WAMb,eAAe,WAAW,SAAS;;;;;WAKnC,MAAM,SAAS;;WAEf,SAAS,cAAc;;;;;WAKvB,WAAW;;WAEX;;;;;;WAMA;;;;;WAKA,QAAQ,SAAS;;WAEjB,aAAa,MAAM,SAAS,QAAQ;;;KAInC,YAAY,UAAU,SAAS,aAAa,SAAS;UAYhD;;WAEN,eAAe;;;;;WAKf,OAAO,OAAO,SAAS,aAAa,WAAW,SAAS;;;;;;WAMxD;;;;;;WAMA,QAAQ,WAAW,SAAS;;;;;WAK5B,YAAY,SAAS;;WAErB;WACA;;;;;;;cAmFE,SAAM,KAAS,WAAS,SAAW,kBAAgB"}
1
+ {"version":3,"file":"events-De4SvZil.d.mts","names":[],"sources":["../src/events.ts"],"mappings":";;;UAkBiB;;WAEN,UAAU,SAAS;;WAEnB;WACA;;;;;;;;UASM;;WAEN;WACA,SAAS,SAAS;;;;;;;;;;cAkDhB,YAAS,OACb,OAAK,qBAAA,SAEJ,cAAc,gBACrB;cAmEU,gBAAa,KAAS,cAAY,SAAS;;;;;;cA4B3C,mBAAgB,KAAS,WAAS,WAAa,SAAS;;cA4BxD;UAOI;;WAEN,WAAW,SAAS,SAAS;;WAE7B,aAAa;;;;;;WAMb,eAAe,WAAW,SAAS;;;;;WAKnC,MAAM,SAAS;;WAEf,SAAS,cAAc;;;;;WAKvB,WAAW;;WAEX;;;;;;WAMA;;;;;WAKA,QAAQ,SAAS;;WAEjB,aAAa,MAAM,SAAS,QAAQ;;;KAInC,YAAY,UAAU,SAAS,aAAa,SAAS;UAYhD;;WAEN,eAAe;;;;;WAKf,OAAO,OAAO,SAAS,aAAa,WAAW,SAAS;;;;;;WAMxD;;;;;;WAMA,QAAQ,WAAW,SAAS;;;;;WAK5B,YAAY,SAAS;;WAErB;;;;;WAKA;WACA;;;;;;;cA8GE,SAAM,KAAS,WAAS,SAAW,kBAAgB"}
package/dist/events.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as KeyBinding, c as intentFor, i as Intent, l as readSelection, n as Attachment, o as SLICE_CLIPBOARD_TYPE, r as Decorate, s as attach, t as AttachOptions, u as restoreSelection } from "./events-DLi6ecvD.mjs";
1
+ import { a as KeyBinding, c as intentFor, i as Intent, l as readSelection, n as Attachment, o as SLICE_CLIPBOARD_TYPE, r as Decorate, s as attach, t as AttachOptions, u as restoreSelection } from "./events-De4SvZil.mjs";
2
2
  export { AttachOptions, Attachment, Decorate, Intent, KeyBinding, SLICE_CLIPBOARD_TYPE, attach, intentFor, readSelection, restoreSelection };