@thomasfosterau/effect-richtext 0.0.0 → 0.1.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.
Files changed (176) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +117 -1
  3. package/dist/_virtual/_rolldown/runtime.js +12 -0
  4. package/dist/commands/commands.d.ts +323 -0
  5. package/dist/commands/commands.js +722 -0
  6. package/dist/commands/internal.js +43 -0
  7. package/dist/commands/keymaps.d.ts +46 -0
  8. package/dist/commands/keymaps.js +64 -0
  9. package/dist/commands.d.ts +3 -0
  10. package/dist/commands.js +3 -0
  11. package/dist/compat/commands.d.ts +250 -0
  12. package/dist/compat/commands.js +275 -0
  13. package/dist/compat/internal/core.d.ts +20 -0
  14. package/dist/compat/internal/core.js +148 -0
  15. package/dist/compat/internal/props.js +82 -0
  16. package/dist/compat/keymap.d.ts +21 -0
  17. package/dist/compat/keymap.js +38 -0
  18. package/dist/compat/model.d.ts +893 -0
  19. package/dist/compat/model.js +1212 -0
  20. package/dist/compat/orderedmap.d.ts +74 -0
  21. package/dist/compat/orderedmap.js +124 -0
  22. package/dist/compat/schema-basic.d.ts +38 -0
  23. package/dist/compat/schema-basic.js +238 -0
  24. package/dist/compat/schema-list.d.ts +81 -0
  25. package/dist/compat/schema-list.js +156 -0
  26. package/dist/compat/state.d.ts +415 -0
  27. package/dist/compat/state.js +689 -0
  28. package/dist/compat/test-builder.d.ts +98 -0
  29. package/dist/compat/test-builder.js +197 -0
  30. package/dist/compat/transform.d.ts +458 -0
  31. package/dist/compat/transform.js +803 -0
  32. package/dist/compat/view.d.ts +411 -0
  33. package/dist/compat/view.js +409 -0
  34. package/dist/dropcursor.d.ts +46 -0
  35. package/dist/dropcursor.js +176 -0
  36. package/dist/extensions/defaults.d.ts +716 -0
  37. package/dist/extensions/defaults.js +209 -0
  38. package/dist/extensions/editor.d.ts +246 -0
  39. package/dist/extensions/editor.js +271 -0
  40. package/dist/extensions/extension.d.ts +375 -0
  41. package/dist/extensions/extension.js +233 -0
  42. package/dist/extensions.d.ts +4 -0
  43. package/dist/extensions.js +4 -0
  44. package/dist/gapcursor.d.ts +66 -0
  45. package/dist/gapcursor.js +273 -0
  46. package/dist/history.d.ts +178 -0
  47. package/dist/history.js +412 -0
  48. package/dist/html.d.ts +158 -0
  49. package/dist/html.js +164 -0
  50. package/dist/inputrules.d.ts +271 -0
  51. package/dist/inputrules.js +321 -0
  52. package/dist/internal/attempt.js +15 -0
  53. package/dist/internal/json.js +29 -0
  54. package/dist/keymap/keymap.d.ts +130 -0
  55. package/dist/keymap/keymap.js +159 -0
  56. package/dist/keymap.d.ts +2 -0
  57. package/dist/keymap.js +1 -0
  58. package/dist/markdown/errors.d.ts +23 -0
  59. package/dist/markdown/errors.js +26 -0
  60. package/dist/markdown/from_markdown.d.ts +185 -0
  61. package/dist/markdown/from_markdown.js +266 -0
  62. package/dist/markdown/schema.d.ts +522 -0
  63. package/dist/markdown/schema.js +292 -0
  64. package/dist/markdown/to_markdown.d.ts +251 -0
  65. package/dist/markdown/to_markdown.js +413 -0
  66. package/dist/markdown.d.ts +5 -0
  67. package/dist/markdown.js +5 -0
  68. package/dist/model/attrsCodec.js +48 -0
  69. package/dist/model/comparedeep.js +17 -0
  70. package/dist/model/content.d.ts +232 -0
  71. package/dist/model/content.js +630 -0
  72. package/dist/model/diff.js +66 -0
  73. package/dist/model/dom.d.ts +3 -0
  74. package/dist/model/errors.d.ts +90 -0
  75. package/dist/model/errors.js +76 -0
  76. package/dist/model/fragment.d.ts +131 -0
  77. package/dist/model/fragment.js +262 -0
  78. package/dist/model/from_dom.d.ts +299 -0
  79. package/dist/model/from_dom.js +618 -0
  80. package/dist/model/json.d.ts +37 -0
  81. package/dist/model/json.js +126 -0
  82. package/dist/model/mark.d.ts +73 -0
  83. package/dist/model/mark.js +121 -0
  84. package/dist/model/node.d.ts +267 -0
  85. package/dist/model/node.js +434 -0
  86. package/dist/model/replace.d.ts +78 -0
  87. package/dist/model/replace.js +207 -0
  88. package/dist/model/resolvedpos.d.ts +196 -0
  89. package/dist/model/resolvedpos.js +305 -0
  90. package/dist/model/schema.d.ts +740 -0
  91. package/dist/model/schema.js +451 -0
  92. package/dist/model/to_dom.d.ts +169 -0
  93. package/dist/model/to_dom.js +238 -0
  94. package/dist/model.d.ts +12 -0
  95. package/dist/model.js +12 -0
  96. package/dist/placeholder.d.ts +53 -0
  97. package/dist/placeholder.js +79 -0
  98. package/dist/reactive/observer.d.ts +54 -0
  99. package/dist/reactive/observer.js +61 -0
  100. package/dist/reactive/selectors.d.ts +22 -0
  101. package/dist/reactive/selectors.js +61 -0
  102. package/dist/reactive/stateref.d.ts +72 -0
  103. package/dist/reactive/stateref.js +71 -0
  104. package/dist/reactive/streams.d.ts +83 -0
  105. package/dist/reactive/streams.js +85 -0
  106. package/dist/reactive.d.ts +16 -0
  107. package/dist/reactive.js +26 -0
  108. package/dist/schema-basic.d.ts +448 -0
  109. package/dist/schema-basic.js +269 -0
  110. package/dist/schema-list/commands.d.ts +66 -0
  111. package/dist/schema-list/commands.js +203 -0
  112. package/dist/schema-list.d.ts +92 -0
  113. package/dist/schema-list.js +100 -0
  114. package/dist/state/errors.d.ts +39 -0
  115. package/dist/state/errors.js +32 -0
  116. package/dist/state/plugin.d.ts +232 -0
  117. package/dist/state/plugin.js +82 -0
  118. package/dist/state/selection.d.ts +297 -0
  119. package/dist/state/selection.js +486 -0
  120. package/dist/state/state.d.ts +212 -0
  121. package/dist/state/state.js +489 -0
  122. package/dist/state/transaction.d.ts +145 -0
  123. package/dist/state/transaction.js +195 -0
  124. package/dist/state.d.ts +6 -0
  125. package/dist/state.js +6 -0
  126. package/dist/test-builder.d.ts +3582 -0
  127. package/dist/test-builder.js +239 -0
  128. package/dist/transform/attr_step.d.ts +60 -0
  129. package/dist/transform/attr_step.js +105 -0
  130. package/dist/transform/errors.d.ts +50 -0
  131. package/dist/transform/errors.js +35 -0
  132. package/dist/transform/map.d.ts +182 -0
  133. package/dist/transform/map.js +280 -0
  134. package/dist/transform/mark.js +98 -0
  135. package/dist/transform/mark_set_step.js +69 -0
  136. package/dist/transform/mark_step.d.ts +113 -0
  137. package/dist/transform/mark_step.js +225 -0
  138. package/dist/transform/replace.d.ts +18 -0
  139. package/dist/transform/replace.js +381 -0
  140. package/dist/transform/replace_step.d.ts +109 -0
  141. package/dist/transform/replace_step.js +175 -0
  142. package/dist/transform/step.d.ts +157 -0
  143. package/dist/transform/step.js +168 -0
  144. package/dist/transform/structure.d.ts +89 -0
  145. package/dist/transform/structure.js +350 -0
  146. package/dist/transform/transform.d.ts +248 -0
  147. package/dist/transform/transform.js +373 -0
  148. package/dist/transform.d.ts +10 -0
  149. package/dist/transform.js +10 -0
  150. package/dist/view/browser.js +39 -0
  151. package/dist/view/capturekeys.js +282 -0
  152. package/dist/view/clipboard.d.ts +8 -0
  153. package/dist/view/clipboard.js +245 -0
  154. package/dist/view/decoration.d.ts +339 -0
  155. package/dist/view/decoration.js +566 -0
  156. package/dist/view/dom.d.ts +18 -0
  157. package/dist/view/dom.js +140 -0
  158. package/dist/view/domchange.js +295 -0
  159. package/dist/view/domcoords.d.ts +22 -0
  160. package/dist/view/domcoords.js +448 -0
  161. package/dist/view/domobserver.d.ts +47 -0
  162. package/dist/view/domobserver.js +328 -0
  163. package/dist/view/errors.d.ts +18 -0
  164. package/dist/view/errors.js +21 -0
  165. package/dist/view/input.d.ts +58 -0
  166. package/dist/view/input.js +704 -0
  167. package/dist/view/selection.js +198 -0
  168. package/dist/view/view.d.ts +699 -0
  169. package/dist/view/view.js +623 -0
  170. package/dist/view/viewdesc.d.ts +236 -0
  171. package/dist/view/viewdesc.js +1205 -0
  172. package/dist/view-css.d.ts +43 -0
  173. package/dist/view-css.js +124 -0
  174. package/dist/view.d.ts +6 -0
  175. package/dist/view.js +4 -0
  176. package/package.json +200 -4
package/dist/html.d.ts ADDED
@@ -0,0 +1,158 @@
1
+ import { ModelError } from "./model/errors.js";
2
+ import { Slice } from "./model/replace.js";
3
+ import { DOMParser, ParseOptions } from "./model/from_dom.js";
4
+ import { DOMSerializer } from "./model/to_dom.js";
5
+ import { AnySchema } from "./model/schema.js";
6
+ import { Node } from "./model/node.js";
7
+ import { Fragment } from "./model/fragment.js";
8
+ import "./model.js";
9
+ import * as Effect from "effect/Effect";
10
+ import * as Schema from "effect/Schema";
11
+ import * as Context from "effect/Context";
12
+ import * as Layer from "effect/Layer";
13
+ declare const MissingDocumentError_base: Schema.Class<MissingDocumentError, Schema.TaggedStruct<"MissingDocumentError", {
14
+ readonly message: Schema.String;
15
+ }>, import("effect/Cause").YieldableError>;
16
+ /**
17
+ * Raised (as a defect) when no DOM `document` is available: neither one
18
+ * passed in the options nor a global `document`.
19
+ *
20
+ * @since 0.1.0
21
+ * @category errors
22
+ */
23
+ export declare class MissingDocumentError extends MissingDocumentError_base {}
24
+ /**
25
+ * Something that can parse an HTML string into a document, like the
26
+ * browser's `window.DOMParser`.
27
+ *
28
+ * @since 0.1.0
29
+ * @category models
30
+ */
31
+ export interface HTMLStringParser {
32
+ readonly parseFromString: (string: string, type: DOMParserSupportedType) => Document;
33
+ }
34
+ /**
35
+ * Options for `toHTML` and `serialize`.
36
+ *
37
+ * @since 0.1.0
38
+ * @category models
39
+ */
40
+ export interface ToHTMLOptions<Sc extends AnySchema = AnySchema> {
41
+ /** The DOM document used to create nodes. Defaults to the global `document`. */
42
+ readonly document?: Document | undefined;
43
+ /** The serializer to use. Defaults to `DOMSerializer.fromSchema(schema)`. */
44
+ readonly serializer?: DOMSerializer<Sc> | undefined;
45
+ }
46
+ /**
47
+ * Options for `fromHTML`, `sliceFromHTML`, `parse` and `parseSlice`.
48
+ * The model's `ParseOptions` are passed through to the parser.
49
+ *
50
+ * @since 0.1.0
51
+ * @category models
52
+ */
53
+ export interface FromHTMLOptions<Sc extends AnySchema = AnySchema> extends ParseOptions<Sc> {
54
+ /**
55
+ * The DOM document used to create an inert HTML document to parse
56
+ * into. Defaults to the global `document`. Ignored when `htmlParser`
57
+ * is given.
58
+ */
59
+ readonly document?: Document | undefined;
60
+ /** An HTML string parser, such as an instance of the browser's `DOMParser`. */
61
+ readonly htmlParser?: HTMLStringParser | undefined;
62
+ /** The parser to use. Defaults to `DOMParser.fromSchema(schema)`. */
63
+ readonly parser?: DOMParser<Sc> | undefined;
64
+ }
65
+ /**
66
+ * Serialize a node or fragment to an HTML string. When given the top
67
+ * node of its schema (usually `doc`), its content is serialized;
68
+ * other nodes are serialized including their own wrapper element (and
69
+ * marks).
70
+ *
71
+ * Throws a `MissingDocumentError` when no document is available, and a
72
+ * `DOMSpecError` for invalid `toDOM` output specs (both programming
73
+ * errors).
74
+ *
75
+ * @since 0.1.0
76
+ * @category serialization
77
+ */
78
+ export declare const toHTML: <Sc extends AnySchema>(content: Node<Sc, any> | Fragment<Sc, any>, options?: ToHTMLOptions<Sc>) => string;
79
+ /**
80
+ * Like `fromHTML`, but throws a `ModelError` when the content can't be
81
+ * parsed into a valid document.
82
+ *
83
+ * @since 0.1.0
84
+ * @category parsing
85
+ */
86
+ export declare const fromHTMLUnsafe: <Sc extends AnySchema>(schema: Sc, html: string, options?: FromHTMLOptions<Sc>) => Node<Sc>;
87
+ /**
88
+ * Parse an HTML string into a document for the given schema.
89
+ *
90
+ * @since 0.1.0
91
+ * @category parsing
92
+ */
93
+ export declare const fromHTML: <Sc extends AnySchema>(schema: Sc, html: string, options?: FromHTMLOptions<Sc>) => Effect.Effect<Node<Sc>, ModelError>;
94
+ /**
95
+ * Like `sliceFromHTML`, but throws a `ModelError` on failure.
96
+ *
97
+ * @since 0.1.0
98
+ * @category parsing
99
+ */
100
+ export declare const sliceFromHTMLUnsafe: <Sc extends AnySchema>(schema: Sc, html: string, options?: FromHTMLOptions<Sc>) => Slice<Sc>;
101
+ /**
102
+ * Parse an HTML string into a slice that is open at the sides (see
103
+ * `DOMParser.parseSlice`), as for pasted content.
104
+ *
105
+ * @since 0.1.0
106
+ * @category parsing
107
+ */
108
+ export declare const sliceFromHTML: <Sc extends AnySchema>(schema: Sc, html: string, options?: FromHTMLOptions<Sc>) => Effect.Effect<Slice<Sc>, ModelError>;
109
+ declare const HtmlEnvironment_base: Context.ServiceClass<HtmlEnvironment, "effect-richtext/html/HtmlEnvironment", {
110
+ readonly document: Document;
111
+ }>;
112
+ /**
113
+ * A service providing the DOM `document` used to serialize and parse
114
+ * HTML.
115
+ *
116
+ * @since 0.1.0
117
+ * @category services
118
+ */
119
+ export declare class HtmlEnvironment extends HtmlEnvironment_base {
120
+ /**
121
+ * A layer providing the given document.
122
+ *
123
+ * @since 0.1.0
124
+ */
125
+ static readonly layer: (document: Document) => Layer.Layer<HtmlEnvironment>;
126
+ /**
127
+ * A layer reading `globalThis.document` when built. Dies with a
128
+ * `MissingDocumentError` when there is no global document.
129
+ *
130
+ * @since 0.1.0
131
+ */
132
+ static readonly layerGlobal: Layer.Layer<HtmlEnvironment>;
133
+ }
134
+ /**
135
+ * Serialize a node or fragment to an HTML string (see `toHTML`), using
136
+ * the `HtmlEnvironment`'s document.
137
+ *
138
+ * @since 0.1.0
139
+ * @category serialization
140
+ */
141
+ export declare const serialize: <Sc extends AnySchema>(content: Node<Sc, any> | Fragment<Sc, any>, options?: Omit<ToHTMLOptions<Sc>, "document">) => Effect.Effect<string, never, HtmlEnvironment>;
142
+ /**
143
+ * Parse an HTML string into a document (see `fromHTML`), using the
144
+ * `HtmlEnvironment`'s document.
145
+ *
146
+ * @since 0.1.0
147
+ * @category parsing
148
+ */
149
+ export declare const parse: <Sc extends AnySchema>(schema: Sc, html: string, options?: Omit<FromHTMLOptions<Sc>, "document">) => Effect.Effect<Node<Sc>, ModelError, HtmlEnvironment>;
150
+ /**
151
+ * Parse an HTML string into an open slice (see `sliceFromHTML`), using
152
+ * the `HtmlEnvironment`'s document.
153
+ *
154
+ * @since 0.1.0
155
+ * @category parsing
156
+ */
157
+ export declare const parseSlice: <Sc extends AnySchema>(schema: Sc, html: string, options?: Omit<FromHTMLOptions<Sc>, "document">) => Effect.Effect<Slice<Sc>, ModelError, HtmlEnvironment>;
158
+ export {};
package/dist/html.js ADDED
@@ -0,0 +1,164 @@
1
+ import { attempt } from "./internal/attempt.js";
2
+ import { DOMParser } from "./model/from_dom.js";
3
+ import { DOMSerializer } from "./model/to_dom.js";
4
+ import { Fragment } from "./model/fragment.js";
5
+ import { isModelError } from "./model/errors.js";
6
+ import * as Effect from "effect/Effect";
7
+ import * as Option from "effect/Option";
8
+ import * as Schema from "effect/Schema";
9
+ import * as Context from "effect/Context";
10
+ import * as Layer from "effect/Layer";
11
+ // src/html.ts
12
+ /**
13
+ * Small helpers converting between documents and HTML strings, built
14
+ * on the model's `DOMParser` and `DOMSerializer`.
15
+ *
16
+ * The helpers need a DOM implementation. In the browser the global
17
+ * `document` is used; elsewhere (for example in Node with `happy-dom`
18
+ * or `jsdom`), pass a `document` in the options, or use the Effect
19
+ * variants (`serialize`, `parse`, `parseSlice`), which read the
20
+ * document from the `HtmlEnvironment` service.
21
+ *
22
+ * ```ts skip-type-checking
23
+ * const html = toHTML(doc) // "<p>Hello</p>"
24
+ * const doc2 = yield* fromHTML(schema, html)
25
+ * ```
26
+ *
27
+ * @since 0.1.0
28
+ */
29
+ /**
30
+ * Raised (as a defect) when no DOM `document` is available: neither one
31
+ * passed in the options nor a global `document`.
32
+ *
33
+ * @since 0.1.0
34
+ * @category errors
35
+ */
36
+ var MissingDocumentError = class extends Schema.TaggedError()("MissingDocumentError", { message: Schema.String }) {};
37
+ const resolveDocument = (document) => {
38
+ const result = document ?? globalThis.document;
39
+ if (!result) throw new MissingDocumentError({ message: "No DOM document available: pass a `document` option or provide an HtmlEnvironment" });
40
+ return result;
41
+ };
42
+ /**
43
+ * Serialize a node or fragment to an HTML string. When given the top
44
+ * node of its schema (usually `doc`), its content is serialized;
45
+ * other nodes are serialized including their own wrapper element (and
46
+ * marks).
47
+ *
48
+ * Throws a `MissingDocumentError` when no document is available, and a
49
+ * `DOMSpecError` for invalid `toDOM` output specs (both programming
50
+ * errors).
51
+ *
52
+ * @since 0.1.0
53
+ * @category serialization
54
+ */
55
+ const toHTML = (content, options = {}) => {
56
+ const document = resolveDocument(options.document);
57
+ const container = document.createElement("div");
58
+ if (content instanceof Fragment) {
59
+ const first = content.firstChild;
60
+ if (Option.isNone(first)) return "";
61
+ const schema = first.value.type.schema;
62
+ (options.serializer ?? DOMSerializer.fromSchema(schema)).serializeFragment(content, { document }, container);
63
+ } else {
64
+ const schema = content.type.schema;
65
+ const serializer = options.serializer ?? DOMSerializer.fromSchema(schema);
66
+ if (content.type === schema.topNodeType) serializer.serializeFragment(content.content, { document }, container);
67
+ else container.appendChild(serializer.serializeNode(content, { document }));
68
+ }
69
+ return container.innerHTML;
70
+ };
71
+ const parseDOM = (html, options) => {
72
+ if (options.htmlParser) return options.htmlParser.parseFromString(html, "text/html").body;
73
+ const inert = resolveDocument(options.document).implementation.createHTMLDocument("");
74
+ inert.body.innerHTML = html;
75
+ return inert.body;
76
+ };
77
+ /**
78
+ * Like `fromHTML`, but throws a `ModelError` when the content can't be
79
+ * parsed into a valid document.
80
+ *
81
+ * @since 0.1.0
82
+ * @category parsing
83
+ */
84
+ const fromHTMLUnsafe = (schema, html, options = {}) => (options.parser ?? DOMParser.fromSchema(schema)).parseUnsafe(parseDOM(html, options), options);
85
+ /**
86
+ * Parse an HTML string into a document for the given schema.
87
+ *
88
+ * @since 0.1.0
89
+ * @category parsing
90
+ */
91
+ const fromHTML = (schema, html, options = {}) => attempt(() => fromHTMLUnsafe(schema, html, options), isModelError);
92
+ /**
93
+ * Like `sliceFromHTML`, but throws a `ModelError` on failure.
94
+ *
95
+ * @since 0.1.0
96
+ * @category parsing
97
+ */
98
+ const sliceFromHTMLUnsafe = (schema, html, options = {}) => (options.parser ?? DOMParser.fromSchema(schema)).parseSliceUnsafe(parseDOM(html, options), options);
99
+ /**
100
+ * Parse an HTML string into a slice that is open at the sides (see
101
+ * `DOMParser.parseSlice`), as for pasted content.
102
+ *
103
+ * @since 0.1.0
104
+ * @category parsing
105
+ */
106
+ const sliceFromHTML = (schema, html, options = {}) => attempt(() => sliceFromHTMLUnsafe(schema, html, options), isModelError);
107
+ /**
108
+ * A service providing the DOM `document` used to serialize and parse
109
+ * HTML.
110
+ *
111
+ * @since 0.1.0
112
+ * @category services
113
+ */
114
+ var HtmlEnvironment = class HtmlEnvironment extends Context.Service()("effect-richtext/html/HtmlEnvironment") {
115
+ static {
116
+ this.layer = (document) => Layer.succeed(HtmlEnvironment, { document });
117
+ }
118
+ static {
119
+ this.layerGlobal = Layer.effect(HtmlEnvironment, Effect.sync(() => ({ document: resolveDocument(void 0) })));
120
+ }
121
+ };
122
+ /**
123
+ * Serialize a node or fragment to an HTML string (see `toHTML`), using
124
+ * the `HtmlEnvironment`'s document.
125
+ *
126
+ * @since 0.1.0
127
+ * @category serialization
128
+ */
129
+ const serialize = (content, options = {}) => Effect.gen(function* () {
130
+ const { document } = yield* HtmlEnvironment;
131
+ return yield* Effect.sync(() => toHTML(content, {
132
+ ...options,
133
+ document
134
+ }));
135
+ });
136
+ /**
137
+ * Parse an HTML string into a document (see `fromHTML`), using the
138
+ * `HtmlEnvironment`'s document.
139
+ *
140
+ * @since 0.1.0
141
+ * @category parsing
142
+ */
143
+ const parse = (schema, html, options = {}) => Effect.gen(function* () {
144
+ const { document } = yield* HtmlEnvironment;
145
+ return yield* fromHTML(schema, html, {
146
+ ...options,
147
+ document
148
+ });
149
+ });
150
+ /**
151
+ * Parse an HTML string into an open slice (see `sliceFromHTML`), using
152
+ * the `HtmlEnvironment`'s document.
153
+ *
154
+ * @since 0.1.0
155
+ * @category parsing
156
+ */
157
+ const parseSlice = (schema, html, options = {}) => Effect.gen(function* () {
158
+ const { document } = yield* HtmlEnvironment;
159
+ return yield* sliceFromHTML(schema, html, {
160
+ ...options,
161
+ document
162
+ });
163
+ });
164
+ export { HtmlEnvironment, MissingDocumentError, fromHTML, fromHTMLUnsafe, parse, parseSlice, serialize, sliceFromHTML, sliceFromHTMLUnsafe, toHTML };
@@ -0,0 +1,271 @@
1
+ import { AnySchema, NodeAttrsInput, NodeNames, NodeType } from "./model/schema.js";
2
+ import { Node } from "./model/node.js";
3
+ import "./model.js";
4
+ import { Dispatch, Transaction } from "./state/transaction.js";
5
+ import { EditorState } from "./state/state.js";
6
+ import { EditorViewLike, Plugin } from "./state/plugin.js";
7
+ import "./state.js";
8
+ import * as Effect from "effect/Effect";
9
+ import * as Option from "effect/Option";
10
+ /**
11
+ * What an input rule handler may return: a transaction describing the
12
+ * rule's effect, `null`/`undefined` (or `None`) when the input was not
13
+ * handled, an `Option` of a transaction, or an Effect producing such an
14
+ * `Option`.
15
+ *
16
+ * @since 0.1.0
17
+ * @category models
18
+ */
19
+ export type InputRuleResult<Sc extends AnySchema = AnySchema, E = never, R = never> = Transaction<Sc> | null | undefined | Option.Option<Transaction<Sc>> | Effect.Effect<Option.Option<Transaction<Sc>>, E, R>;
20
+ /**
21
+ * An input rule handler. Called with the editor state, the match array
22
+ * produced by `RegExp.exec`, and the start and end of the matched range.
23
+ *
24
+ * @since 0.1.0
25
+ * @category models
26
+ */
27
+ export type InputRuleHandler<Sc extends AnySchema = AnySchema, E = never, R = never> = (state: EditorState<Sc, any, any>, match: RegExpMatchArray, start: number, end: number) => InputRuleResult<Sc, E, R>;
28
+ /**
29
+ * Options for `InputRule`.
30
+ *
31
+ * @since 0.1.0
32
+ * @category models
33
+ */
34
+ export interface InputRuleOptions {
35
+ /**
36
+ * When set to false, `undoInputRule` doesn't work on this rule.
37
+ */
38
+ readonly undoable?: boolean | undefined;
39
+ /**
40
+ * By default, input rules will not apply inside nodes marked as
41
+ * `code`. Set this to true to change that, or to `"only"` to _only_
42
+ * match in such nodes.
43
+ */
44
+ readonly inCode?: boolean | "only" | undefined;
45
+ /**
46
+ * When set to `false`, this rule will not fire inside marks marked as
47
+ * `code`. The default is `true`.
48
+ */
49
+ readonly inCodeMark?: boolean | undefined;
50
+ }
51
+ /**
52
+ * @since 0.1.0
53
+ * @category symbols
54
+ */
55
+ export declare const InputRuleTypeId: unique symbol;
56
+ /**
57
+ * @since 0.1.0
58
+ * @category symbols
59
+ */
60
+ export type InputRuleTypeId = typeof InputRuleTypeId;
61
+ /**
62
+ * Input rules are regular expressions describing a piece of text that,
63
+ * when typed, causes something to happen. This might be changing two
64
+ * dashes into an emdash, wrapping a paragraph starting with `"> "` into
65
+ * a blockquote, or something entirely different.
66
+ *
67
+ * @since 0.1.0
68
+ * @category models
69
+ */
70
+ export declare class InputRule<Sc extends AnySchema = AnySchema, E = never, R = never> {
71
+ /** The regular expression the text before the cursor is matched against. */
72
+ readonly match: RegExp;
73
+ readonly [InputRuleTypeId]: {
74
+ readonly _E: (_: never) => E;
75
+ readonly _R: (_: never) => R;
76
+ };
77
+ /** @internal */
78
+ readonly handler: InputRuleHandler<Sc, E, R>;
79
+ /** @internal */
80
+ readonly undoable: boolean;
81
+ /** Whether the rule applies in code nodes (`"only"`: only there). */
82
+ readonly inCode: boolean | "only";
83
+ /** Whether the rule applies inside code marks. */
84
+ readonly inCodeMark: boolean;
85
+ /**
86
+ * Create an input rule. The rule applies when the user typed something
87
+ * and the text directly in front of the cursor matches `match`, which
88
+ * should end with `$`.
89
+ *
90
+ * The `handler` can be a string, in which case the matched text, or
91
+ * the first matched group in the regexp, is replaced by that string.
92
+ *
93
+ * Or it can be a function, which will be called with the match array
94
+ * produced by `RegExp.exec`, as well as the start and end of the
95
+ * matched range, and which can return a transaction that describes the
96
+ * rule's effect, or `null` to indicate the input was not handled. It
97
+ * may also return an `Option` of a transaction, or an Effect producing
98
+ * one.
99
+ */
100
+ constructor(
101
+ /** The regular expression the text before the cursor is matched against. */
102
+ match: RegExp, handler: string | InputRuleHandler<Sc, E, R>, options?: InputRuleOptions);
103
+ }
104
+ /**
105
+ * The union of the error types of the given input rules.
106
+ *
107
+ * @since 0.1.0
108
+ * @category type-level
109
+ */
110
+ export type InputRuleErrors<Rules extends ReadonlyArray<InputRule<any, any, any>>> = Rules[number] extends (infer X) ? X extends InputRule<any, infer E, any> ? E : never : never;
111
+ /**
112
+ * The union of the requirements of the given input rules.
113
+ *
114
+ * @since 0.1.0
115
+ * @category type-level
116
+ */
117
+ export type InputRuleRequirements<Rules extends ReadonlyArray<InputRule<any, any, any>>> = Rules[number] extends (infer X) ? X extends InputRule<any, any, infer R> ? R : never : never;
118
+ /**
119
+ * The last applied (undoable) input rule, as remembered by the input
120
+ * rules plugin so that `undoInputRule` can revert it.
121
+ *
122
+ * @since 0.1.0
123
+ * @category models
124
+ */
125
+ export interface AppliedInputRule<Sc extends AnySchema = AnySchema> {
126
+ /** The transaction produced by the rule. */
127
+ readonly transform: Transaction<Sc>;
128
+ /** The start of the text input that triggered the rule. */
129
+ readonly from: number;
130
+ /** The end of the text input that triggered the rule. */
131
+ readonly to: number;
132
+ /** The typed text that triggered the rule. */
133
+ readonly text: string;
134
+ }
135
+ /**
136
+ * The state of an input rules plugin: the last applied rule, while it
137
+ * is still undoable (until the selection or document changes).
138
+ *
139
+ * @since 0.1.0
140
+ * @category models
141
+ */
142
+ export type InputRulesState = Option.Option<AppliedInputRule<any>>;
143
+ /**
144
+ * Options for `inputRules`.
145
+ *
146
+ * @since 0.1.0
147
+ * @category models
148
+ */
149
+ export interface InputRulesConfig<Rules extends ReadonlyArray<InputRule<any, any, any>>> {
150
+ readonly rules: Rules;
151
+ }
152
+ /**
153
+ * Create an input rules plugin. When enabled, it will cause text input
154
+ * that matches any of the given rules to trigger the rule's action.
155
+ *
156
+ * Rules are tried in order. Rules whose handler returns an Effect run
157
+ * with the view's context: when such an effect completes synchronously,
158
+ * it behaves exactly like a plain rule. When it is asynchronous, the
159
+ * input is considered handled; when it eventually finds no transaction
160
+ * (or fails), the typed text is inserted, and when it produces a
161
+ * transaction, it is dispatched—both only if the editor state didn't
162
+ * change in the meantime.
163
+ *
164
+ * @since 0.1.0
165
+ * @category constructors
166
+ */
167
+ export declare const inputRules: <const Rules extends ReadonlyArray<InputRule<any, any, any>>>({ rules }: InputRulesConfig<Rules>) => Plugin<InputRulesState, AnySchema, InputRuleErrors<Rules>, InputRuleRequirements<Rules>>;
168
+ /**
169
+ * A command that works with any schema and needs no services.
170
+ *
171
+ * @since 0.1.0
172
+ * @category models
173
+ */
174
+ export type InputRuleCommand = <Sc extends AnySchema>(state: EditorState<Sc, any, any>, dispatch?: Dispatch<Sc>, view?: EditorViewLike) => Effect.Effect<boolean>;
175
+ /**
176
+ * This is a command that will undo an input rule, if applying such a
177
+ * rule was the last thing that the user did.
178
+ *
179
+ * @since 0.1.0
180
+ * @category commands
181
+ */
182
+ export declare const undoInputRule: InputRuleCommand;
183
+ /**
184
+ * Attributes for a rule-built node: fixed, or computed from the match.
185
+ *
186
+ * @since 0.1.0
187
+ * @category models
188
+ */
189
+ export type InputRuleAttrs<Sc extends AnySchema, N extends NodeNames<Sc>> = NodeAttrsInput<Sc, N> | null | ((match: RegExpMatchArray) => NodeAttrsInput<Sc, N> | null);
190
+ /**
191
+ * Build an input rule for automatically wrapping a textblock when a
192
+ * given string is typed. The `regexp` argument is directly passed
193
+ * through to the `InputRule` constructor. You'll probably want the
194
+ * regexp to start with `^`, so that the pattern can only occur at the
195
+ * start of a textblock.
196
+ *
197
+ * `nodeType` is the type of node to wrap in. If it needs attributes,
198
+ * you can either pass them directly, or pass a function that will
199
+ * compute them from the regular expression match.
200
+ *
201
+ * By default, if there's a node with the same type above the newly
202
+ * wrapped node, the rule will try to join those two nodes. You can pass
203
+ * a join predicate, which takes a regular expression match and the node
204
+ * before the wrapped node, and can return a boolean to indicate whether
205
+ * a join should happen.
206
+ *
207
+ * @since 0.1.0
208
+ * @category constructors
209
+ */
210
+ export declare const wrappingInputRule: <Sc extends AnySchema, N extends NodeNames<Sc>>(regexp: RegExp, nodeType: NodeType<Sc, N>, getAttrs?: InputRuleAttrs<Sc, N>, joinPredicate?: (match: RegExpMatchArray, node: Node<Sc>) => boolean) => InputRule<Sc>;
211
+ /**
212
+ * Build an input rule that changes the type of a textblock when the
213
+ * matched text is typed into it. You'll usually want to start your
214
+ * regexp with `^` so that it is only matched at the start of a
215
+ * textblock. The optional `getAttrs` parameter can be used to compute
216
+ * the new node's attributes, and works the same as in the
217
+ * `wrappingInputRule` function.
218
+ *
219
+ * @since 0.1.0
220
+ * @category constructors
221
+ */
222
+ export declare const textblockTypeInputRule: <Sc extends AnySchema, N extends NodeNames<Sc>>(regexp: RegExp, nodeType: NodeType<Sc, N>, getAttrs?: InputRuleAttrs<Sc, N>) => InputRule<Sc>;
223
+ /**
224
+ * Converts double dashes to an emdash.
225
+ *
226
+ * @since 0.1.0
227
+ * @category rules
228
+ */
229
+ export declare const emDash: InputRule;
230
+ /**
231
+ * Converts three dots to an ellipsis character.
232
+ *
233
+ * @since 0.1.0
234
+ * @category rules
235
+ */
236
+ export declare const ellipsis: InputRule;
237
+ /**
238
+ * “Smart” opening double quotes.
239
+ *
240
+ * @since 0.1.0
241
+ * @category rules
242
+ */
243
+ export declare const openDoubleQuote: InputRule;
244
+ /**
245
+ * “Smart” closing double quotes.
246
+ *
247
+ * @since 0.1.0
248
+ * @category rules
249
+ */
250
+ export declare const closeDoubleQuote: InputRule;
251
+ /**
252
+ * “Smart” opening single quotes.
253
+ *
254
+ * @since 0.1.0
255
+ * @category rules
256
+ */
257
+ export declare const openSingleQuote: InputRule;
258
+ /**
259
+ * “Smart” closing single quotes.
260
+ *
261
+ * @since 0.1.0
262
+ * @category rules
263
+ */
264
+ export declare const closeSingleQuote: InputRule;
265
+ /**
266
+ * Smart-quote related input rules.
267
+ *
268
+ * @since 0.1.0
269
+ * @category rules
270
+ */
271
+ export declare const smartQuotes: ReadonlyArray<InputRule>;