@solidev/data 1.0.1 → 1.1.1

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.
package/package.json CHANGED
@@ -1,13 +1,26 @@
1
1
  {
2
2
  "name": "@solidev/data",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "license": "AGPL-3.0-only",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^22",
7
7
  "@angular/core": "^22",
8
+ "@codemirror/commands": "^6",
9
+ "@codemirror/lang-markdown": "^6",
10
+ "@codemirror/language": "^6",
11
+ "@codemirror/state": "^6",
12
+ "@codemirror/view": "^6",
13
+ "@lezer/highlight": "^1",
8
14
  "@ng-bootstrap/ng-bootstrap": "^21",
9
15
  "jwt-decode": "^4",
10
- "ngx-editor": "^19.0.0-beta.1"
16
+ "prosemirror-commands": "^1",
17
+ "prosemirror-history": "^1",
18
+ "prosemirror-inputrules": "^1",
19
+ "prosemirror-keymap": "^1",
20
+ "prosemirror-model": "^1",
21
+ "prosemirror-schema-list": "^1",
22
+ "prosemirror-state": "^1",
23
+ "prosemirror-view": "^1"
11
24
  },
12
25
  "dependencies": {
13
26
  "tslib": "^2.8"
@@ -23,6 +36,10 @@
23
36
  "types": "./types/solidev-data.d.ts",
24
37
  "default": "./fesm2022/solidev-data.mjs"
25
38
  },
39
+ "./mdedit": {
40
+ "types": "./types/solidev-data-mdedit.d.ts",
41
+ "default": "./fesm2022/solidev-data-mdedit.mjs"
42
+ },
26
43
  "./richedit": {
27
44
  "types": "./types/solidev-data-richedit.d.ts",
28
45
  "default": "./fesm2022/solidev-data-richedit.mjs"
@@ -0,0 +1,226 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { DataModel, FieldEditorBase } from '@solidev/data';
3
+ import { StateCommand, EditorState, Compartment, Extension } from '@codemirror/state';
4
+ import { HighlightStyle } from '@codemirror/language';
5
+
6
+ /**
7
+ * Toggle a symmetric inline delimiter — `**` for bold, `*` for italic, `~~` for
8
+ * strikethrough, `` ` `` for code.
9
+ *
10
+ * Wraps the selection, or unwraps it when the delimiters are already there,
11
+ * whether they sit just outside the selection (the usual case after a previous
12
+ * toggle) or inside it (the user selected them along with the text). On an
13
+ * empty selection it inserts the pair and leaves the cursor between the two
14
+ * halves, so typing continues inside the mark.
15
+ */
16
+ declare function toggleInlineMark(delim: string): StateCommand;
17
+ /** Toggle `**bold**` around the selection. */
18
+ declare const toggleBold: StateCommand;
19
+ /** Toggle `*italic*` around the selection. */
20
+ declare const toggleItalic: StateCommand;
21
+ /** Toggle `~~strikethrough~~` around the selection (GFM). */
22
+ declare const toggleStrikethrough: StateCommand;
23
+ /** Toggle `` `code` `` around the selection. */
24
+ declare const toggleInlineCode: StateCommand;
25
+ /**
26
+ * Set the heading level of every selected line, `0` meaning plain paragraph.
27
+ *
28
+ * This sets rather than toggles: picking "Heading 2" twice leaves an `h2`, and
29
+ * the way back to a paragraph is `setHeading(0)` — which is what the toolbar's
30
+ * "Paragraphe" entry does. Returns false when nothing would change, as a
31
+ * CodeMirror command should.
32
+ */
33
+ declare function setHeading(level: number): StateCommand;
34
+ /** Toggle `> ` blockquote markers on the selected lines. */
35
+ declare const toggleQuote: StateCommand;
36
+ /** Toggle `- ` bullets on the selected lines; `*` and `+` bullets count as set. */
37
+ declare const toggleBulletList: StateCommand;
38
+ /** Toggle `1. ` numbering on the selected lines, renumbering from one. */
39
+ declare const toggleOrderedList: StateCommand;
40
+ /**
41
+ * Turn the selection into a link.
42
+ *
43
+ * With text selected it becomes `[text](url)` and the `url` placeholder is left
44
+ * selected, ready to be typed over. With no selection the whole
45
+ * `[text](url)` skeleton is inserted and `text` is selected instead.
46
+ */
47
+ declare const insertLink: StateCommand;
48
+ /** What the toolbar needs to know to render its buttons pressed or not. */
49
+ interface MarkdownActiveState {
50
+ bold: boolean;
51
+ italic: boolean;
52
+ strike: boolean;
53
+ code: boolean;
54
+ quote: boolean;
55
+ bulletList: boolean;
56
+ orderedList: boolean;
57
+ link: boolean;
58
+ /** Heading level under the cursor, `0` outside any heading. */
59
+ heading: number;
60
+ }
61
+ /**
62
+ * Which markdown constructs the cursor currently sits in.
63
+ *
64
+ * Read from the syntax tree rather than by matching the raw text, so nesting
65
+ * and escapes are handled by the parser. Drives `aria-pressed` on the toolbar.
66
+ */
67
+ declare function markdownActive(state: EditorState): MarkdownActiveState;
68
+
69
+ /** A button the `mdedit` toolbar knows how to render. */
70
+ type MdToolbarItem = 'bold' | 'italic' | 'strike' | 'code' | 'quote' | 'bullet_list' | 'ordered_list' | 'link' | 'heading';
71
+ /** Toolbar layout: groups of items, rendered as Bootstrap button groups. */
72
+ type MdToolbar = MdToolbarItem[][];
73
+ /**
74
+ * Named toolbar presets for {@link MdeditComponent}, selectable through its
75
+ * `toolbar` input.
76
+ *
77
+ * - `default`: marks, a heading dropdown, quote and code, lists, links.
78
+ * - `light`: a reduced set — bold, italic, bullets, links.
79
+ * - `none`: empty; the component hides the toolbar entirely for this value.
80
+ *
81
+ * An `MdToolbar` can also be passed directly when neither preset fits.
82
+ */
83
+ declare const MdEditToolbars: Record<string, MdToolbar>;
84
+ /** What a plain toolbar button needs: an icon, a label, a command, a state. */
85
+ interface MdButtonDefinition {
86
+ icon: string;
87
+ label: string;
88
+ command: StateCommand;
89
+ active: Exclude<keyof MarkdownActiveState, 'heading'>;
90
+ }
91
+ /** A resolved toolbar entry, ready for the template to render. */
92
+ type MdToolbarEntry = ({
93
+ kind: 'button';
94
+ } & MdButtonDefinition) | {
95
+ kind: 'heading';
96
+ label: string;
97
+ };
98
+ declare class MdeditComponent<FT, T extends DataModel> extends FieldEditorBase<FT, T> {
99
+ /** Toolbar preset name from {@link MdEditToolbars}, or an explicit toolbar. */
100
+ toolbar: _angular_core.InputSignal<MdToolbar | "none" | "default" | "light">;
101
+ /** Text shown while the document is empty. */
102
+ placeholder: _angular_core.InputSignal<string>;
103
+ /** Markdown constructs under the cursor, driving `aria-pressed`. */
104
+ readonly active: _angular_core.WritableSignal<MarkdownActiveState>;
105
+ /** Heading levels offered by the dropdown. */
106
+ readonly headingLevels: {
107
+ level: number;
108
+ label: string;
109
+ }[];
110
+ /** Toolbar resolved from {@link toolbar}, as entries the template can render. */
111
+ readonly groups: _angular_core.Signal<MdToolbarEntry[][]>;
112
+ private readonly host;
113
+ private readonly destroyRef;
114
+ /** Holds the read-only extensions, so editability can be reconfigured live. */
115
+ private readonly readOnly;
116
+ private view?;
117
+ constructor();
118
+ /**
119
+ * Wire the resolved control to the editor, in both directions.
120
+ *
121
+ * The base picks the control (`[fc]`, `[form]`, or its own) and seeds it;
122
+ * this adds the CodeMirror half.
123
+ */
124
+ ngOnInit(): void;
125
+ /**
126
+ * Run a toolbar command against the editor and hand focus back, so a click
127
+ * on the toolbar does not take the caret out of the document.
128
+ */
129
+ run(command: StateCommand): void;
130
+ /** Apply the heading level picked in the dropdown to the current line(s). */
131
+ setHeadingLevel(value: string): void;
132
+ /**
133
+ * Build or tear down the CodeMirror view, following the host element.
134
+ *
135
+ * Toggling back to the read-only view removes the host, which would leave a
136
+ * detached view behind and make the next mount a no-op. The control keeps the
137
+ * value across the round trip, so a fresh view is seeded correctly.
138
+ */
139
+ private syncView;
140
+ /** Build the CodeMirror view inside the host element. */
141
+ private mount;
142
+ /**
143
+ * Push a document into the control, unless it is already there.
144
+ *
145
+ * `setValue` emits even when the value is unchanged, so without this guard an
146
+ * external `setValue` would come back through the editor as a second
147
+ * `valueChanges` — and a second {@link changed} emission for one edit.
148
+ */
149
+ private pushToControl;
150
+ /** Push a control value into the document, unless it is already there. */
151
+ private applyValue;
152
+ /** Mirror the control's enabled/disabled status onto the editor. */
153
+ private applyEditable;
154
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MdeditComponent<any, any>, never>;
155
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MdeditComponent<any, any>, "data-mdedit", never, { "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
156
+ }
157
+
158
+ /** Options accepted by {@link markdownSetup}. */
159
+ interface MarkdownSetupOptions {
160
+ /**
161
+ * Compartment the read-only extensions are installed in, so the caller can
162
+ * flip editability later with `compartment.reconfigure(readOnlyExtension(v))`.
163
+ * Create one per editor instance — compartments are not shareable.
164
+ */
165
+ readOnly?: Compartment;
166
+ /** Whether the editor starts read-only. */
167
+ readOnlyInitially?: boolean;
168
+ /** Text shown while the document is empty. */
169
+ placeholder?: string;
170
+ /** Called with the full markdown source after every document change. */
171
+ onChange?: (doc: string) => void;
172
+ /** Called after every state update, for toolbar active-state tracking. */
173
+ onStateChange?: (state: EditorState) => void;
174
+ /** Id of the element labelling the editor, wired as `aria-labelledby`. */
175
+ labelledBy?: string;
176
+ }
177
+ /**
178
+ * The extensions that make an `EditorView` behave as a markdown source editor.
179
+ *
180
+ * Deliberately not CodeMirror's `basicSetup`: this edits prose, so there are no
181
+ * line numbers, no fold gutter and no bracket matching — just markdown parsing,
182
+ * history, wrapping, and the styling from {@link markdownStyling}.
183
+ *
184
+ * The markdown dialect is `markdownLanguage`, i.e. GFM: tables, strikethrough
185
+ * and task lists parse. Fenced code blocks are recognised but their content is
186
+ * not highlighted per-language; that would need `@codemirror/language-data` and
187
+ * its lazily loaded grammars, which is out of scope here.
188
+ */
189
+ declare function markdownSetup(options?: MarkdownSetupOptions): Extension[];
190
+ /**
191
+ * Read-only state for a given editability, meant to be reconfigured into the
192
+ * compartment passed to {@link markdownSetup}.
193
+ *
194
+ * Both facets are needed: `EditorState.readOnly` stops commands from changing
195
+ * the document, `EditorView.editable` takes `contenteditable` off the DOM node
196
+ * so the caret and the browser's own editing affordances go away too.
197
+ */
198
+ declare function readOnlyExtension(readOnly: boolean): Extension;
199
+
200
+ /**
201
+ * Syntax highlighting for the markdown *source*.
202
+ *
203
+ * The point of `mdedit` is that the markup stays on screen: `**bold**` keeps
204
+ * its asterisks, a heading keeps its `#`. What this style does is make the
205
+ * source read like the document it describes — headings get bigger, `**bold**`
206
+ * renders bold, code turns monospace — while the markers themselves
207
+ * ({@link tags.processingInstruction}, {@link tags.meta}) are dimmed so they
208
+ * stay visible but recede.
209
+ *
210
+ * Colours come from Bootstrap CSS variables so the editor follows the host
211
+ * theme, including its dark mode, without shipping a palette of its own.
212
+ */
213
+ declare const markdownHighlightStyle: HighlightStyle;
214
+ /**
215
+ * Editor chrome: a box that matches Bootstrap's `.form-control`, including its
216
+ * focus ring, so an `mdedit` sits in a form without looking foreign.
217
+ */
218
+ declare const markdownTheme: Extension;
219
+ /**
220
+ * The whole visual layer — chrome plus source highlighting — as one extension,
221
+ * which is what {@link markdownSetup} installs.
222
+ */
223
+ declare function markdownStyling(): Extension;
224
+
225
+ export { MdEditToolbars, MdeditComponent, insertLink, markdownActive, markdownHighlightStyle, markdownSetup, markdownStyling, markdownTheme, readOnlyExtension, setHeading, toggleBold, toggleBulletList, toggleInlineCode, toggleInlineMark, toggleItalic, toggleOrderedList, toggleQuote, toggleStrikethrough };
226
+ export type { MarkdownActiveState, MarkdownSetupOptions, MdToolbar, MdToolbarEntry, MdToolbarItem };
@@ -1,8 +1,116 @@
1
1
  import * as i0 from '@angular/core';
2
- import { OnInit, OnDestroy, EventEmitter } from '@angular/core';
3
- import { Toolbar, Editor } from 'ngx-editor';
4
- import { FormControl } from '@angular/forms';
5
- import { DataModel, BaseFieldManager } from '@solidev/data';
2
+ import { OnInit } from '@angular/core';
3
+ import { DataModel, FieldEditorBase } from '@solidev/data';
4
+ import { EditorState, Command } from 'prosemirror-state';
5
+ import { EditorView } from 'prosemirror-view';
6
+ import * as prosemirror_model from 'prosemirror-model';
7
+ import { Schema, Node, MarkType, NodeType, Attrs } from 'prosemirror-model';
8
+
9
+ /** Options accepted by the {@link Editor} constructor. */
10
+ interface EditorOptions {
11
+ /** Initial content, as an HTML string. */
12
+ content?: string;
13
+ /** Whether the document starts editable. */
14
+ editable?: boolean;
15
+ /** Text shown while the document is empty. */
16
+ placeholder?: string;
17
+ /** Id of the element labelling the editor, wired as `aria-labelledby`. */
18
+ labelledBy?: string;
19
+ }
20
+ /**
21
+ * The rich text engine behind `<data-richedit>`.
22
+ *
23
+ * Owns a ProseMirror `EditorView` and everything plugged into it, and speaks
24
+ * HTML at its edges — which is what the field values are. It replaces
25
+ * `ngx-editor`'s class of the same name and keeps the same shape of
26
+ * responsibility, so the Angular components around it stayed thin.
27
+ *
28
+ * The view is created detached: the menu bar and the editor component both
29
+ * receive the `Editor` before there is anywhere to put its DOM, and the editor
30
+ * component adopts {@link dom} when it renders.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const editor = new Editor({ content: '<p>hello</p>' });
35
+ * editor.onChange((html) => console.log(html));
36
+ * document.body.appendChild(editor.dom);
37
+ * ```
38
+ */
39
+ declare class Editor {
40
+ /** The underlying ProseMirror view. */
41
+ readonly view: EditorView;
42
+ private readonly changeListeners;
43
+ private readonly stateListeners;
44
+ /** Serialization of the current document — what {@link html} reports. */
45
+ private _html;
46
+ /**
47
+ * The last string handed in from outside.
48
+ *
49
+ * Parsing normalises (`<b>` becomes `<strong>`, `text-align:center` gains a
50
+ * space), so the loaded string and the serialized one often differ while
51
+ * meaning the same document. Keeping both is what lets {@link setContent}
52
+ * recognise "you are giving me back what you already gave me".
53
+ */
54
+ private _loaded;
55
+ private _editable;
56
+ constructor(options?: EditorOptions);
57
+ /** The editor's DOM node, ready to be placed in the document. */
58
+ get dom(): HTMLElement;
59
+ /** Current editor state, for menu bar queries. */
60
+ get state(): EditorState;
61
+ /** Current content, as an HTML string. */
62
+ get html(): string;
63
+ /** Whether the document accepts edits. */
64
+ get editable(): boolean;
65
+ /**
66
+ * Replace the content.
67
+ *
68
+ * A no-op when the HTML is the one already loaded, which is what keeps a
69
+ * form control writing its own value back from resetting the cursor on every
70
+ * keystroke. The replacement is kept out of the undo history — undoing back
71
+ * past a programmatic load is not something a user ever means.
72
+ */
73
+ setContent(html: string): void;
74
+ /** Enable or disable editing. */
75
+ setEditable(editable: boolean): void;
76
+ /** Run a command against the current state. Returns whether it applied. */
77
+ exec(command: Command): boolean;
78
+ /** Put the caret back in the document. */
79
+ focus(): void;
80
+ /** Listen to content changes. Returns a function that stops listening. */
81
+ onChange(listener: (html: string) => void): () => void;
82
+ /** Listen to state changes, including selection. Returns an unsubscribe. */
83
+ onStateChange(listener: (state: EditorState) => void): () => void;
84
+ /** Tear the view down and drop every listener. */
85
+ destroy(): void;
86
+ }
87
+
88
+ /**
89
+ * Toolbar configuration for `<data-richedit>`.
90
+ *
91
+ * The shape is the one `ngx-editor` used — an array of groups, each group an
92
+ * array of items, an item either a name or a `{heading: [...]}` dropdown — so
93
+ * toolbars written against the old editor keep compiling and keep working.
94
+ */
95
+ /** Heading levels a heading dropdown can offer. */
96
+ type TBHeadingItems = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
97
+ /**
98
+ * Every item name the configuration accepts.
99
+ *
100
+ * The whole `ngx-editor` vocabulary is listed so existing configurations still
101
+ * type-check. Three of them — `image`, `indent` and `outdent` — have no
102
+ * implementation here and are skipped at render time with a warning naming
103
+ * them, rather than silently disappearing.
104
+ */
105
+ type TBItems = 'bold' | 'italic' | 'code' | 'blockquote' | 'underline' | 'strike' | 'ordered_list' | 'bullet_list' | 'link' | 'image' | 'text_color' | 'background_color' | 'align_left' | 'align_center' | 'align_right' | 'align_justify' | 'horizontal_rule' | 'format_clear' | 'indent' | 'outdent' | 'superscript' | 'subscript' | 'undo' | 'redo';
106
+ /** A heading dropdown, listing the levels it offers. */
107
+ interface ToolbarDropdown {
108
+ heading?: TBHeadingItems[];
109
+ }
110
+ /** One entry in a toolbar group. */
111
+ type ToolbarItem = TBItems | ToolbarDropdown;
112
+ /** Groups of items, rendered as Bootstrap button groups. */
113
+ type Toolbar = ToolbarItem[][];
6
114
 
7
115
  /**
8
116
  * Named toolbar presets for {@link RicheditComponent}, selectable through its
@@ -16,80 +124,189 @@ import { DataModel, BaseFieldManager } from '@solidev/data';
16
124
  * A `Toolbar` can also be passed directly to the component when neither preset
17
125
  * fits.
18
126
  */
19
- declare const RichEditToolbars: {
20
- [index: string]: Toolbar;
21
- };
22
- declare class RicheditComponent<FT, T extends DataModel> implements OnInit, OnDestroy {
23
- /** Model instance holding the field. */
24
- model?: T;
25
- /** Name of the rich text field to edit. */
26
- field?: string;
27
- /** Whether {@link toggleEdit} is allowed to enable editing. */
28
- editable: boolean;
29
- /** Whether the editor is currently enabled. Defaults to true. */
30
- edit: boolean;
31
- /**
32
- * Layout, and whether {@link save} persists.
33
- *
34
- * `dd` renders a `<dt>`/`<dd>` block and is the only mode that saves to the
35
- * API; `inline` and `form` render a label plus the editor and leave saving to
36
- * the caller.
37
- */
38
- mode: "dd" | "inline" | "form";
39
- /** Hide label (for inline forms) */
40
- hideLabel: boolean;
41
- /**
42
- * Hide the built-in save button, for callers driving persistence themselves
43
- * from the {@link changed} output.
44
- */
45
- hideButton: boolean;
46
- /**
47
- * Form control backing the editor.
48
- *
49
- * When supplied, the component uses it as-is and skips its own setup — no
50
- * field manager lookup, no seeding from the model, and no {@link changed}
51
- * emissions. When absent, one is created and wired up from `[model]` and
52
- * `[field]`.
53
- */
54
- fc: FormControl<string | null>;
127
+ declare const RichEditToolbars: Record<string, Toolbar>;
128
+ declare class RicheditComponent<FT, T extends DataModel> extends FieldEditorBase<FT, T> implements OnInit {
55
129
  /** Toolbar preset name from {@link RichEditToolbars}, or an explicit toolbar. */
56
- toolbar: "none" | "default" | "light" | Toolbar;
57
- /** Emits the editor's HTML on every change. Only wired for an internal `fc`. */
58
- changed: EventEmitter<string | null>;
59
- /** Field manager for {@link field}; only resolved when `fc` is created here. */
60
- manager?: BaseFieldManager<FT>;
61
- /** Whether the manager declares the field required. */
62
- required: boolean;
63
- /** Underlying ngx-editor instance; destroyed with the component. */
130
+ toolbar: i0.InputSignal<Toolbar | "none" | "default" | "light">;
131
+ /** Underlying editor instance; destroyed with the component. */
64
132
  editor: Editor;
65
133
  /** Unused; kept for backwards compatibility. */
66
134
  html: string;
67
135
  /** Toolbar actually rendered, resolved from {@link toolbar}. */
68
136
  realToolbar: Toolbar;
137
+ private readonly destroyRef;
69
138
  /**
70
- * Create the editor, resolve the toolbar, and unless a `[fc]` was given —
71
- * build a control seeded from the model field, enabled per `[edit]`, and
72
- * relaying changes to {@link changed}.
139
+ * Build the engine and resolve the toolbar, then let the base resolve the
140
+ * control and relay its changes.
73
141
  */
74
142
  ngOnInit(): void;
75
- /** Destroy the ngx-editor instance to release its resources. */
76
- ngOnDestroy(): void;
77
- /**
78
- * Switch between read-only and editing by enabling or disabling the control.
79
- * Forces read-only when `[editable]` is false.
80
- */
81
- toggleEdit(): void;
82
- /**
83
- * Write the editor content back to the model field, and persist it in `dd`
84
- * mode only.
85
- *
86
- * In `inline` / `form` modes the model is updated in memory but no request is
87
- * sent, leaving the save to the surrounding form. Does nothing without both a
88
- * `[model]` and a `[field]`.
89
- */
90
- save(): Promise<void>;
91
143
  static ɵfac: i0.ɵɵFactoryDeclaration<RicheditComponent<any, any>, never>;
92
- static ɵcmp: i0.ɵɵComponentDeclaration<RicheditComponent<any, any>, "data-richedit", never, { "model": { "alias": "model"; "required": false; }; "field": { "alias": "field"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; "edit": { "alias": "edit"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "hideLabel": { "alias": "hideLabel"; "required": false; }; "hideButton": { "alias": "hideButton"; "required": false; }; "fc": { "alias": "fc"; "required": false; }; "toolbar": { "alias": "toolbar"; "required": false; }; }, { "changed": "changed"; }, never, ["*"], true, never>;
144
+ static ɵcmp: i0.ɵɵComponentDeclaration<RicheditComponent<any, any>, "data-richedit", never, { "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
93
145
  }
94
146
 
95
- export { RichEditToolbars, RicheditComponent };
147
+ /** The schema itself — one instance, shared by every editor. */
148
+ declare const schema: Schema<string, string>;
149
+ /**
150
+ * Node types, resolved once and by name.
151
+ *
152
+ * `Schema.nodes` is an index signature, and this project turns on
153
+ * `noPropertyAccessFromIndexSignature`, so every lookup would otherwise need
154
+ * brackets at the call site.
155
+ */
156
+ declare const nodeTypes: {
157
+ doc: prosemirror_model.NodeType;
158
+ paragraph: prosemirror_model.NodeType;
159
+ heading: prosemirror_model.NodeType;
160
+ blockquote: prosemirror_model.NodeType;
161
+ codeBlock: prosemirror_model.NodeType;
162
+ bulletList: prosemirror_model.NodeType;
163
+ orderedList: prosemirror_model.NodeType;
164
+ listItem: prosemirror_model.NodeType;
165
+ hardBreak: prosemirror_model.NodeType;
166
+ horizontalRule: prosemirror_model.NodeType;
167
+ image: prosemirror_model.NodeType;
168
+ };
169
+ /** Mark types, resolved once and by name. See {@link nodeTypes}. */
170
+ declare const markTypes: {
171
+ strong: prosemirror_model.MarkType;
172
+ em: prosemirror_model.MarkType;
173
+ underline: prosemirror_model.MarkType;
174
+ strike: prosemirror_model.MarkType;
175
+ code: prosemirror_model.MarkType;
176
+ link: prosemirror_model.MarkType;
177
+ textColor: prosemirror_model.MarkType;
178
+ backgroundColor: prosemirror_model.MarkType;
179
+ };
180
+ /** Text alignments an alignable block accepts. */
181
+ type Alignment = 'left' | 'center' | 'right' | 'justify';
182
+
183
+ /**
184
+ * Parse an HTML string into a document node.
185
+ *
186
+ * Anything the schema has no rule for is dropped, which is why the schema keeps
187
+ * parse rules for constructs the toolbar cannot produce.
188
+ */
189
+ declare function fromHTML(html: string, schema?: Schema): Node;
190
+ /**
191
+ * Serialize a document node back to an HTML string.
192
+ *
193
+ * An empty document serializes to `''`, not to the `<p></p>` `ngx-editor`
194
+ * wrote. A field the user cleared should read as empty for the consumer — a
195
+ * paragraph containing nothing is truthy, and every `if (model.description)`
196
+ * built on it was quietly wrong.
197
+ */
198
+ declare function toHTML(doc: Node, schema?: Schema): string;
199
+ /**
200
+ * Whether a document holds nothing but one empty textblock.
201
+ *
202
+ * Drives both the placeholder decoration and {@link toHTML}'s empty case. Note
203
+ * that an empty *heading* counts: the user typed `# ` and nothing else, so
204
+ * there is still no content to store.
205
+ */
206
+ declare function isEmpty(doc: Node): boolean;
207
+
208
+ /**
209
+ * Whether the mark is on the whole selection — or, with the cursor collapsed,
210
+ * whether the next character typed would carry it.
211
+ */
212
+ declare function isMarkActive(state: EditorState, type: MarkType): boolean;
213
+ /**
214
+ * Whether a node of that type (with those attributes, if given) contains or
215
+ * intersects the selection.
216
+ *
217
+ * `nodesBetween` walks down from the document, so this reports ancestors too —
218
+ * which is what makes it work for blockquotes and lists, where the cursor sits
219
+ * in a paragraph nested inside the node being asked about.
220
+ */
221
+ declare function isNodeActive(state: EditorState, type: NodeType, attrs?: Attrs): boolean;
222
+ /** Toggle a mark over the selection. */
223
+ declare function toggleMarkCommand(type: MarkType): Command;
224
+ /** Toggle `<strong>` over the selection. */
225
+ declare const toggleBold: Command;
226
+ /** Toggle `<em>` over the selection. */
227
+ declare const toggleItalic: Command;
228
+ /** Toggle `<u>` over the selection. */
229
+ declare const toggleUnderline: Command;
230
+ /** Toggle `<s>` over the selection. */
231
+ declare const toggleStrike: Command;
232
+ /** Toggle `<code>` over the selection. */
233
+ declare const toggleCode: Command;
234
+ /**
235
+ * Make the selected blocks headings of that level.
236
+ *
237
+ * This is what the menu bar's dropdown uses: picking a level in a list should
238
+ * put you at that level, not toggle you out of it.
239
+ */
240
+ declare function setHeading(level: number): Command;
241
+ /**
242
+ * Switch the selected blocks between a heading of that level and a paragraph.
243
+ *
244
+ * Unlike {@link setHeading}, picking the level already in force turns it back
245
+ * into a paragraph — the behaviour a toggle button wants.
246
+ */
247
+ declare function toggleHeading(level: number): Command;
248
+ /** Turn the selected blocks into paragraphs. */
249
+ declare const setParagraph: Command;
250
+ /** Toggle a code block over the selected blocks. */
251
+ declare const toggleCodeBlock: Command;
252
+ /** Wrap the selection in a blockquote, or lift it back out. */
253
+ declare const toggleBlockquote: Command;
254
+ /** Wrap the selection in a list of that type, or lift it back out. */
255
+ declare function toggleList(type: NodeType): Command;
256
+ /** Toggle a bullet list around the selection. */
257
+ declare const toggleBulletList: Command;
258
+ /** Toggle an ordered list around the selection. */
259
+ declare const toggleOrderedList: Command;
260
+ /**
261
+ * Set the text alignment of every paragraph and heading in the selection.
262
+ *
263
+ * Alignment lives on the block as an attribute and serializes to
264
+ * `style="text-align:…"`, the way `ngx-editor` stored it. `null` clears it.
265
+ */
266
+ declare function setAlign(align: Alignment | null): Command;
267
+ /** The alignment in force on the block holding the cursor, if any. */
268
+ declare function activeAlignment(state: EditorState): Alignment | null;
269
+ /** The heading level in force, or 0 outside a heading. */
270
+ declare function activeHeading(state: EditorState): number;
271
+ /**
272
+ * Apply a colour mark to the selection, replacing any colour already there.
273
+ *
274
+ * With the cursor collapsed the mark is stored instead, so it applies to what
275
+ * the user types next — the same behaviour as bold on an empty selection.
276
+ */
277
+ declare function setColor(type: MarkType, attrs: Attrs): Command;
278
+ /** Drop a colour mark from the selection. */
279
+ declare function removeColor(type: MarkType): Command;
280
+ /** The colour currently carried by the selection, for the colour pickers. */
281
+ declare function activeColor(state: EditorState, type: MarkType, attr: string): string | null;
282
+ /**
283
+ * The span of the link under the cursor, or the selection when it is not
284
+ * collapsed.
285
+ *
286
+ * Walks outwards from the cursor over the sibling text nodes that carry the
287
+ * mark, so "remove link" works with the caret merely inside the link rather
288
+ * than with the whole thing selected.
289
+ */
290
+ declare function linkRange(state: EditorState): {
291
+ from: number;
292
+ to: number;
293
+ } | null;
294
+ /** The href of the link under the cursor, for prefilling the link form. */
295
+ declare function activeLink(state: EditorState): string | null;
296
+ /**
297
+ * Link the selection.
298
+ *
299
+ * Takes the href as an argument rather than prompting, so the command stays
300
+ * free of DOM and the menu bar owns the form. With the caret inside an existing
301
+ * link and nothing selected, that link's whole span is re-linked.
302
+ */
303
+ declare function addLink(href: string, title?: string | null): Command;
304
+ /** Unlink the link under the cursor, or the selection. */
305
+ declare const removeLink: Command;
306
+ /** Insert a horizontal rule at the selection. */
307
+ declare const insertHorizontalRule: Command;
308
+ /** Drop every mark from the selection and put its blocks back to paragraphs. */
309
+ declare const clearFormat: Command;
310
+
311
+ export { Editor, RichEditToolbars, RicheditComponent, activeAlignment, activeColor, activeHeading, activeLink, addLink, clearFormat, fromHTML, insertHorizontalRule, isEmpty, isMarkActive, isNodeActive, linkRange, markTypes, nodeTypes, removeColor, removeLink, schema, setAlign, setColor, setHeading, setParagraph, toHTML, toggleBlockquote, toggleBold, toggleBulletList, toggleCode, toggleCodeBlock, toggleHeading, toggleItalic, toggleList, toggleMarkCommand, toggleOrderedList, toggleStrike, toggleUnderline };
312
+ export type { Alignment, EditorOptions, TBHeadingItems, TBItems, Toolbar, ToolbarDropdown, ToolbarItem };