xt-plugin-editor 1.3.2 → 1.5.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,770 +1,942 @@
1
- import * as i0 from '@angular/core';
2
- import { SecurityContext, Pipe, input, inject, viewChild, signal, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { XtSimpleComponent, XtResolverService, updateFormGroupWithValue, XtRenderComponent } from 'xt-components';
4
- import * as i1$1 from '@angular/forms';
5
- import { FormGroup, ReactiveFormsModule, FormsModule } from '@angular/forms';
6
- import { NodeSelection, EditorState } from 'prosemirror-state';
7
- import { EditorView } from 'prosemirror-view';
8
- import { schema, defaultMarkdownSerializer, defaultMarkdownParser } from 'prosemirror-markdown';
9
- import { MenuItem, icons, wrapItem, blockTypeItem, Dropdown, DropdownSubmenu, joinUpItem, liftItem, selectParentNodeItem, undoItem, redoItem, menuBar } from 'prosemirror-menu';
10
- import { joinUp, joinDown, lift, selectParentNode, toggleMark, wrapIn, chainCommands, exitCode, setBlockType, baseKeymap } from 'prosemirror-commands';
11
- import { wrapInList, splitListItem, liftListItem, sinkListItem } from 'prosemirror-schema-list';
12
- import { undo, redo, history } from 'prosemirror-history';
13
- import { undoInputRule, wrappingInputRule, textblockTypeInputRule, smartQuotes, ellipsis, emDash, inputRules } from 'prosemirror-inputrules';
14
- import { keymap } from 'prosemirror-keymap';
15
- import { dropCursor } from 'prosemirror-dropcursor';
16
- import { gapCursor } from 'prosemirror-gapcursor';
17
- import { marked } from 'marked';
18
- import * as i1 from '@angular/platform-browser';
19
- import { Tooltip } from 'primeng/tooltip';
20
- import { Dialog } from 'primeng/dialog';
21
- import { ButtonDirective } from 'primeng/button';
22
-
23
- /// Given a blockquote node type, returns an input rule that turns `"> "`
24
- /// at the start of a textblock into a blockquote.
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, Pipe, SecurityContext, effect, inject, input, signal, viewChild } from "@angular/core";
3
+ import { XtRenderComponent, XtResolverService, XtSimpleComponent, updateFormGroupWithValue } from "xt-components";
4
+ import * as i1 from "@angular/forms";
5
+ import { FormGroup, FormsModule, ReactiveFormsModule } from "@angular/forms";
6
+ import { EditorState, NodeSelection } from "prosemirror-state";
7
+ import { EditorView } from "prosemirror-view";
8
+ import { defaultMarkdownParser, defaultMarkdownSerializer, schema } from "prosemirror-markdown";
9
+ import { Dropdown, DropdownSubmenu, MenuItem, blockTypeItem, icons, joinUpItem, liftItem, menuBar, redoItem, selectParentNodeItem, undoItem, wrapItem } from "prosemirror-menu";
10
+ import { baseKeymap, chainCommands, exitCode, joinDown, joinUp, lift, selectParentNode, setBlockType, toggleMark, wrapIn } from "prosemirror-commands";
11
+ import { liftListItem, sinkListItem, splitListItem, wrapInList } from "prosemirror-schema-list";
12
+ import { history, redo, undo } from "prosemirror-history";
13
+ import { ellipsis, emDash, inputRules, smartQuotes, textblockTypeInputRule, undoInputRule, wrappingInputRule } from "prosemirror-inputrules";
14
+ import { keymap } from "prosemirror-keymap";
15
+ import { dropCursor } from "prosemirror-dropcursor";
16
+ import { gapCursor } from "prosemirror-gapcursor";
17
+ import { marked } from "marked";
18
+ import * as i1$1 from "@angular/platform-browser";
19
+ import { Tooltip } from "@openng/optimus-ui/tooltip";
20
+ import { Dialog } from "@openng/optimus-ui/dialog";
21
+ import { ButtonDirective } from "@openng/optimus-ui/button";
25
22
  const prefix = "ProseMirror-prompt";
26
23
  const mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false;
27
- /// Inspect the given schema looking for marks and nodes from the
28
- /// basic schema, and if found, add key bindings related to them.
29
- /// This will add:
30
- ///
31
- /// * **Mod-b** for toggling [strong](#schema-basic.StrongMark)
32
- /// * **Mod-i** for toggling [emphasis](#schema-basic.EmMark)
33
- /// * **Mod-`** for toggling [code font](#schema-basic.CodeMark)
34
- /// * **Ctrl-Shift-0** for making the current textblock a paragraph
35
- /// * **Ctrl-Shift-1** to **Ctrl-Shift-Digit6** for making the current
36
- /// textblock a heading of the corresponding level
37
- /// * **Ctrl-Shift-Backslash** to make the current textblock a code block
38
- /// * **Ctrl-Shift-8** to wrap the selection in an ordered list
39
- /// * **Ctrl-Shift-9** to wrap the selection in a bullet list
40
- /// * **Ctrl->** to wrap the selection in a block quote
41
- /// * **Enter** to split a non-empty textblock in a list item while at
42
- /// the same time splitting the list item
43
- /// * **Mod-Enter** to insert a hard break
44
- /// * **Mod-_** to insert a horizontal rule
45
- /// * **Backspace** to undo an input rule
46
- /// * **Alt-ArrowUp** to `joinUp`
47
- /// * **Alt-ArrowDown** to `joinDown`
48
- /// * **Mod-BracketLeft** to `lift`
49
- /// * **Escape** to `selectParentNode`
50
- ///
51
- /// You can suppress or map these bindings by passing a `mapKeys`
52
- /// argument, which maps key names (say `"Mod-B"` to either `false`, to
53
- /// remove the binding, or a new key name string.
54
24
  function buildKeymap(schema, mapKeys) {
55
- let keys = {}, type;
56
- function bind(key, cmd) {
57
- if (mapKeys) {
58
- let mapped = mapKeys[key];
59
- if (mapped === false)
60
- return;
61
- if (mapped)
62
- key = mapped;
63
- }
64
- keys[key] = cmd;
65
- }
66
- bind("Mod-z", undo);
67
- bind("Shift-Mod-z", redo);
68
- bind("Backspace", undoInputRule);
69
- if (!mac)
70
- bind("Mod-y", redo);
71
- bind("Alt-ArrowUp", joinUp);
72
- bind("Alt-ArrowDown", joinDown);
73
- bind("Mod-BracketLeft", lift);
74
- bind("Escape", selectParentNode);
75
- if (type = schema.marks["strong"]) {
76
- bind("Mod-b", toggleMark(type));
77
- bind("Mod-B", toggleMark(type));
78
- }
79
- if (type = schema.marks["em"]) {
80
- bind("Mod-i", toggleMark(type));
81
- bind("Mod-I", toggleMark(type));
82
- }
83
- if (type = schema.marks["code"])
84
- bind("Mod-`", toggleMark(type));
85
- if (type = schema.nodes["bullet_list"])
86
- bind("Shift-Ctrl-8", wrapInList(type));
87
- if (type = schema.nodes["ordered_list"])
88
- bind("Shift-Ctrl-9", wrapInList(type));
89
- if (type = schema.nodes["blockquote"])
90
- bind("Ctrl->", wrapIn(type));
91
- if (type = schema.nodes["hard_break"]) {
92
- let br = type, cmd = chainCommands(exitCode, (state, dispatch) => {
93
- if (dispatch)
94
- dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView());
95
- return true;
96
- });
97
- bind("Mod-Enter", cmd);
98
- bind("Shift-Enter", cmd);
99
- if (mac)
100
- bind("Ctrl-Enter", cmd);
101
- }
102
- if (type = schema.nodes["list_item"]) {
103
- bind("Enter", splitListItem(type));
104
- bind("Mod-[", liftListItem(type));
105
- bind("Mod-]", sinkListItem(type));
106
- }
107
- if (type = schema.nodes["paragraph"])
108
- bind("Shift-Ctrl-0", setBlockType(type));
109
- if (type = schema.nodes["code_block"])
110
- bind("Shift-Ctrl-\\", setBlockType(type));
111
- if (type = schema.nodes["heading"])
112
- for (let i = 1; i <= 6; i++)
113
- bind("Shift-Ctrl-" + i, setBlockType(type, { level: i }));
114
- if (type = schema.nodes["horizontal_rule"]) {
115
- let hr = type;
116
- bind("Mod-_", (state, dispatch) => {
117
- if (dispatch)
118
- dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView());
119
- return true;
120
- });
121
- }
122
- return keys;
25
+ let keys = {}, type;
26
+ function bind(key, cmd) {
27
+ if (mapKeys) {
28
+ let mapped = mapKeys[key];
29
+ if (mapped === false) return;
30
+ if (mapped) key = mapped;
31
+ }
32
+ keys[key] = cmd;
33
+ }
34
+ bind("Mod-z", undo);
35
+ bind("Shift-Mod-z", redo);
36
+ bind("Backspace", undoInputRule);
37
+ if (!mac) bind("Mod-y", redo);
38
+ bind("Alt-ArrowUp", joinUp);
39
+ bind("Alt-ArrowDown", joinDown);
40
+ bind("Mod-BracketLeft", lift);
41
+ bind("Escape", selectParentNode);
42
+ if (type = schema.marks["strong"]) {
43
+ bind("Mod-b", toggleMark(type));
44
+ bind("Mod-B", toggleMark(type));
45
+ }
46
+ if (type = schema.marks["em"]) {
47
+ bind("Mod-i", toggleMark(type));
48
+ bind("Mod-I", toggleMark(type));
49
+ }
50
+ if (type = schema.marks["code"]) bind("Mod-`", toggleMark(type));
51
+ if (type = schema.nodes["bullet_list"]) bind("Shift-Ctrl-8", wrapInList(type));
52
+ if (type = schema.nodes["ordered_list"]) bind("Shift-Ctrl-9", wrapInList(type));
53
+ if (type = schema.nodes["blockquote"]) bind("Ctrl->", wrapIn(type));
54
+ if (type = schema.nodes["hard_break"]) {
55
+ let br = type, cmd = chainCommands(exitCode, (state, dispatch) => {
56
+ if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView());
57
+ return true;
58
+ });
59
+ bind("Mod-Enter", cmd);
60
+ bind("Shift-Enter", cmd);
61
+ if (mac) bind("Ctrl-Enter", cmd);
62
+ }
63
+ if (type = schema.nodes["list_item"]) {
64
+ bind("Enter", splitListItem(type));
65
+ bind("Mod-[", liftListItem(type));
66
+ bind("Mod-]", sinkListItem(type));
67
+ }
68
+ if (type = schema.nodes["paragraph"]) bind("Shift-Ctrl-0", setBlockType(type));
69
+ if (type = schema.nodes["code_block"]) bind("Shift-Ctrl-\\", setBlockType(type));
70
+ if (type = schema.nodes["heading"]) for (let i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, setBlockType(type, { level: i }));
71
+ if (type = schema.nodes["horizontal_rule"]) {
72
+ let hr = type;
73
+ bind("Mod-_", (state, dispatch) => {
74
+ if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView());
75
+ return true;
76
+ });
77
+ }
78
+ return keys;
123
79
  }
124
80
  function openPrompt(options) {
125
- let wrapper = document.body.appendChild(document.createElement("div"));
126
- wrapper.className = prefix;
127
- let mouseOutside = (e) => { if (!wrapper.contains(e.target))
128
- close(); };
129
- setTimeout(() => window.addEventListener("mousedown", mouseOutside), 50);
130
- let close = () => {
131
- window.removeEventListener("mousedown", mouseOutside);
132
- if (wrapper.parentNode)
133
- wrapper.parentNode.removeChild(wrapper);
134
- };
135
- let domFields = [];
136
- for (let name in options.fields)
137
- domFields.push(options.fields[name].render());
138
- let submitButton = document.createElement("button");
139
- submitButton.type = "submit";
140
- submitButton.className = prefix + "-submit";
141
- submitButton.textContent = "OK";
142
- let cancelButton = document.createElement("button");
143
- cancelButton.type = "button";
144
- cancelButton.className = prefix + "-cancel";
145
- cancelButton.textContent = "Cancel";
146
- cancelButton.addEventListener("click", close);
147
- let form = wrapper.appendChild(document.createElement("form"));
148
- if (options.title)
149
- form.appendChild(document.createElement("h5")).textContent = options.title;
150
- domFields.forEach(field => {
151
- form.appendChild(document.createElement("div")).appendChild(field);
152
- });
153
- let buttons = form.appendChild(document.createElement("div"));
154
- buttons.className = prefix + "-buttons";
155
- buttons.appendChild(submitButton);
156
- buttons.appendChild(document.createTextNode(" "));
157
- buttons.appendChild(cancelButton);
158
- let box = wrapper.getBoundingClientRect();
159
- wrapper.style.top = ((window.innerHeight - box.height) / 2) + "px";
160
- wrapper.style.left = ((window.innerWidth - box.width) / 2) + "px";
161
- let submit = () => {
162
- let params = getValues(options.fields, domFields);
163
- if (params) {
164
- close();
165
- options.callback(params);
166
- }
167
- };
168
- form.addEventListener("submit", e => {
169
- e.preventDefault();
170
- submit();
171
- });
172
- form.addEventListener("keydown", e => {
173
- if (e.keyCode == 27) {
174
- e.preventDefault();
175
- close();
176
- }
177
- else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) {
178
- e.preventDefault();
179
- submit();
180
- }
181
- else if (e.keyCode == 9) {
182
- window.setTimeout(() => {
183
- if (!wrapper.contains(document.activeElement))
184
- close();
185
- }, 500);
186
- }
187
- });
188
- let input = form.elements[0];
189
- if (input)
190
- input.focus();
81
+ let wrapper = document.body.appendChild(document.createElement("div"));
82
+ wrapper.className = prefix;
83
+ let mouseOutside = (e) => {
84
+ if (!wrapper.contains(e.target)) close();
85
+ };
86
+ setTimeout(() => window.addEventListener("mousedown", mouseOutside), 50);
87
+ let close = () => {
88
+ window.removeEventListener("mousedown", mouseOutside);
89
+ if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);
90
+ };
91
+ let domFields = [];
92
+ for (let name in options.fields) domFields.push(options.fields[name].render());
93
+ let submitButton = document.createElement("button");
94
+ submitButton.type = "submit";
95
+ submitButton.className = prefix + "-submit";
96
+ submitButton.textContent = "OK";
97
+ let cancelButton = document.createElement("button");
98
+ cancelButton.type = "button";
99
+ cancelButton.className = prefix + "-cancel";
100
+ cancelButton.textContent = "Cancel";
101
+ cancelButton.addEventListener("click", close);
102
+ let form = wrapper.appendChild(document.createElement("form"));
103
+ if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title;
104
+ domFields.forEach((field) => {
105
+ form.appendChild(document.createElement("div")).appendChild(field);
106
+ });
107
+ let buttons = form.appendChild(document.createElement("div"));
108
+ buttons.className = prefix + "-buttons";
109
+ buttons.appendChild(submitButton);
110
+ buttons.appendChild(document.createTextNode(" "));
111
+ buttons.appendChild(cancelButton);
112
+ let box = wrapper.getBoundingClientRect();
113
+ wrapper.style.top = (window.innerHeight - box.height) / 2 + "px";
114
+ wrapper.style.left = (window.innerWidth - box.width) / 2 + "px";
115
+ let submit = () => {
116
+ let params = getValues(options.fields, domFields);
117
+ if (params) {
118
+ close();
119
+ options.callback(params);
120
+ }
121
+ };
122
+ form.addEventListener("submit", (e) => {
123
+ e.preventDefault();
124
+ submit();
125
+ });
126
+ form.addEventListener("keydown", (e) => {
127
+ if (e.keyCode == 27) {
128
+ e.preventDefault();
129
+ close();
130
+ } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) {
131
+ e.preventDefault();
132
+ submit();
133
+ } else if (e.keyCode == 9) window.setTimeout(() => {
134
+ if (!wrapper.contains(document.activeElement)) close();
135
+ }, 500);
136
+ });
137
+ let input = form.elements[0];
138
+ if (input) input.focus();
191
139
  }
192
140
  function getValues(fields, domFields) {
193
- let result = Object.create(null), i = 0;
194
- for (let name in fields) {
195
- let field = fields[name], dom = domFields[i++];
196
- let value = field.read(dom), bad = field.validate(value);
197
- if (bad) {
198
- reportInvalid(dom, bad);
199
- return null;
200
- }
201
- result[name] = field.clean(value);
202
- }
203
- return result;
141
+ let result = Object.create(null), i = 0;
142
+ for (let name in fields) {
143
+ let field = fields[name], dom = domFields[i++];
144
+ let value = field.read(dom), bad = field.validate(value);
145
+ if (bad) {
146
+ reportInvalid(dom, bad);
147
+ return null;
148
+ }
149
+ result[name] = field.clean(value);
150
+ }
151
+ return result;
204
152
  }
205
153
  function reportInvalid(dom, message) {
206
- // FIXME this is awful and needs a lot more work
207
- let parent = dom.parentNode;
208
- let msg = parent.appendChild(document.createElement("div"));
209
- msg.style.left = (dom.offsetLeft + dom.offsetWidth + 2) + "px";
210
- msg.style.top = (dom.offsetTop - 5) + "px";
211
- msg.className = "ProseMirror-invalid";
212
- msg.textContent = message;
213
- setTimeout(() => parent.removeChild(msg), 1500);
214
- }
215
- /// The type of field that `openPrompt` expects to be passed to it.
216
- class Field {
217
- /// Create a field with the given options. Options support by all
218
- /// field types are:
219
- constructor(
220
- /// @internal
221
- options) {
222
- this.options = options;
223
- }
224
- /// Read the field's value from its DOM node.
225
- read(dom) { return dom.value; }
226
- /// A field-type-specific validation function.
227
- validateType(value) { return null; }
228
- /// @internal
229
- validate(value) {
230
- if (!value && this.options.required)
231
- return "Required field";
232
- return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null);
233
- }
234
- clean(value) {
235
- return this.options.clean ? this.options.clean(value) : value;
236
- }
237
- }
238
- /// A field class for single-line text fields.
239
- class TextField extends Field {
240
- render() {
241
- let input = document.createElement("input");
242
- input.type = "text";
243
- input.placeholder = this.options.label;
244
- input.value = this.options.value || "";
245
- input.autocomplete = "off";
246
- return input;
247
- }
248
- }
249
- /// A field class for dropdown fields based on a plain `<select>`
250
- /// tag. Expects an option `options`, which should be an array of
251
- /// `{value: string, label: string}` objects, or a function taking a
252
- /// `ProseMirror` instance and returning such an array.
253
- class SelectField extends Field {
254
- render() {
255
- let select = document.createElement("select");
256
- this.options.options.forEach(o => {
257
- let opt = select.appendChild(document.createElement("option"));
258
- opt.value = o.value;
259
- opt.selected = o.value == this.options.value;
260
- opt.label = o.label;
261
- });
262
- return select;
263
- }
154
+ let parent = dom.parentNode;
155
+ let msg = parent.appendChild(document.createElement("div"));
156
+ msg.style.left = dom.offsetLeft + dom.offsetWidth + 2 + "px";
157
+ msg.style.top = dom.offsetTop - 5 + "px";
158
+ msg.className = "ProseMirror-invalid";
159
+ msg.textContent = message;
160
+ setTimeout(() => parent.removeChild(msg), 1500);
264
161
  }
265
- // Helpers to create specific types of items
162
+ var Field = class {
163
+ constructor(options) {
164
+ this.options = options;
165
+ }
166
+ read(dom) {
167
+ return dom.value;
168
+ }
169
+ validateType(value) {
170
+ return null;
171
+ }
172
+ validate(value) {
173
+ if (!value && this.options.required) return "Required field";
174
+ return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null);
175
+ }
176
+ clean(value) {
177
+ return this.options.clean ? this.options.clean(value) : value;
178
+ }
179
+ };
180
+ var TextField = class extends Field {
181
+ render() {
182
+ let input = document.createElement("input");
183
+ input.type = "text";
184
+ input.placeholder = this.options.label;
185
+ input.value = this.options.value || "";
186
+ input.autocomplete = "off";
187
+ return input;
188
+ }
189
+ };
266
190
  function canInsert(state, nodeType) {
267
- let $from = state.selection.$from;
268
- for (let d = $from.depth; d >= 0; d--) {
269
- let index = $from.index(d);
270
- if ($from.node(d).canReplaceWith(index, index, nodeType))
271
- return true;
272
- }
273
- return false;
191
+ let $from = state.selection.$from;
192
+ for (let d = $from.depth; d >= 0; d--) {
193
+ let index = $from.index(d);
194
+ if ($from.node(d).canReplaceWith(index, index, nodeType)) return true;
195
+ }
196
+ return false;
274
197
  }
275
198
  function insertImageItem(nodeType) {
276
- return new MenuItem({
277
- title: "Insert image",
278
- label: "Image",
279
- enable(state) { return canInsert(state, nodeType); },
280
- run(state, _, view) {
281
- let { from, to } = state.selection, attrs = null;
282
- if (state.selection instanceof NodeSelection && state.selection.node.type == nodeType)
283
- attrs = state.selection.node.attrs;
284
- openPrompt({
285
- title: "Insert image",
286
- fields: {
287
- src: new TextField({ label: "Location", required: true, value: attrs && attrs["src"] }),
288
- title: new TextField({ label: "Title", value: attrs && attrs["title"] }),
289
- alt: new TextField({ label: "Description",
290
- value: attrs ? attrs["alt"] : state.doc.textBetween(from, to, " ") })
291
- },
292
- callback(attrs) {
293
- view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs)));
294
- view.focus();
295
- }
296
- });
297
- }
298
- });
199
+ return new MenuItem({
200
+ title: "Insert image",
201
+ label: "Image",
202
+ enable(state) {
203
+ return canInsert(state, nodeType);
204
+ },
205
+ run(state, _, view) {
206
+ let { from, to } = state.selection, attrs = null;
207
+ if (state.selection instanceof NodeSelection && state.selection.node.type == nodeType) attrs = state.selection.node.attrs;
208
+ openPrompt({
209
+ title: "Insert image",
210
+ fields: {
211
+ src: new TextField({
212
+ label: "Location",
213
+ required: true,
214
+ value: attrs && attrs["src"]
215
+ }),
216
+ title: new TextField({
217
+ label: "Title",
218
+ value: attrs && attrs["title"]
219
+ }),
220
+ alt: new TextField({
221
+ label: "Description",
222
+ value: attrs ? attrs["alt"] : state.doc.textBetween(from, to, " ")
223
+ })
224
+ },
225
+ callback(attrs) {
226
+ view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs)));
227
+ view.focus();
228
+ }
229
+ });
230
+ }
231
+ });
299
232
  }
300
233
  function cmdItem(cmd, options) {
301
- let passedOptions = {
302
- label: options.title,
303
- run: cmd
304
- };
305
- for (let prop in options)
306
- passedOptions[prop] = options[prop];
307
- if (!options.enable && !options.select)
308
- passedOptions[options.enable ? "enable" : "select"] = state => cmd(state);
309
- return new MenuItem(passedOptions);
234
+ let passedOptions = {
235
+ label: options.title,
236
+ run: cmd
237
+ };
238
+ for (let prop in options) passedOptions[prop] = options[prop];
239
+ if (!options.enable && !options.select) passedOptions[options.enable ? "enable" : "select"] = (state) => cmd(state);
240
+ return new MenuItem(passedOptions);
310
241
  }
311
242
  function markActive(state, type) {
312
- let { from, $from, to, empty } = state.selection;
313
- if (empty)
314
- return !!type.isInSet(state.storedMarks || $from.marks());
315
- else
316
- return state.doc.rangeHasMark(from, to, type);
243
+ let { from, $from, to, empty } = state.selection;
244
+ if (empty) return !!type.isInSet(state.storedMarks || $from.marks());
245
+ else return state.doc.rangeHasMark(from, to, type);
317
246
  }
318
247
  function markItem(markType, options) {
319
- let passedOptions = {
320
- active(state) { return markActive(state, markType); }
321
- };
322
- for (let prop in options)
323
- passedOptions[prop] = options[prop];
324
- return cmdItem(toggleMark(markType), passedOptions);
248
+ let passedOptions = { active(state) {
249
+ return markActive(state, markType);
250
+ } };
251
+ for (let prop in options) passedOptions[prop] = options[prop];
252
+ return cmdItem(toggleMark(markType), passedOptions);
325
253
  }
326
254
  function linkItem(markType) {
327
- return new MenuItem({
328
- title: "Add or remove link",
329
- icon: icons["link"],
330
- active(state) { return markActive(state, markType); },
331
- enable(state) { return !state.selection.empty; },
332
- run(state, dispatch, view) {
333
- if (markActive(state, markType)) {
334
- toggleMark(markType)(state, dispatch);
335
- return true;
336
- }
337
- openPrompt({
338
- title: "Create a link",
339
- fields: {
340
- href: new TextField({
341
- label: "Link target",
342
- required: true
343
- }),
344
- title: new TextField({ label: "Title" })
345
- },
346
- callback(attrs) {
347
- toggleMark(markType, attrs)(view.state, view.dispatch);
348
- view.focus();
349
- }
350
- });
351
- return true;
352
- }
353
- });
255
+ return new MenuItem({
256
+ title: "Add or remove link",
257
+ icon: icons["link"],
258
+ active(state) {
259
+ return markActive(state, markType);
260
+ },
261
+ enable(state) {
262
+ return !state.selection.empty;
263
+ },
264
+ run(state, dispatch, view) {
265
+ if (markActive(state, markType)) {
266
+ toggleMark(markType)(state, dispatch);
267
+ return true;
268
+ }
269
+ openPrompt({
270
+ title: "Create a link",
271
+ fields: {
272
+ href: new TextField({
273
+ label: "Link target",
274
+ required: true
275
+ }),
276
+ title: new TextField({ label: "Title" })
277
+ },
278
+ callback(attrs) {
279
+ toggleMark(markType, attrs)(view.state, view.dispatch);
280
+ view.focus();
281
+ }
282
+ });
283
+ return true;
284
+ }
285
+ });
354
286
  }
355
287
  function wrapListItem(nodeType, options) {
356
- return cmdItem(wrapInList(nodeType, options.attrs), options);
288
+ return cmdItem(wrapInList(nodeType, options.attrs), options);
357
289
  }
358
- /// Given a schema, look for default mark and node types in it and
359
- /// return an object with relevant menu items relating to those marks.
360
290
  function buildMenuItems(schema, override) {
361
- let r = {};
362
- let mark;
363
- override = override || {};
364
- if (mark = schema.marks["strong"])
365
- r.toggleStrong = override["strong"] || markItem(mark, { title: "Toggle strong style", icon: icons["strong"] });
366
- if (mark = schema.marks["em"])
367
- r.toggleEm = override["em"] || markItem(mark, { title: "Toggle emphasis", icon: icons["em"] });
368
- if (mark = schema.marks["code"])
369
- r.toggleCode = override["code"] || markItem(mark, { title: "Toggle code font", icon: icons["code"] });
370
- if (mark = schema.marks["link"])
371
- r.toggleLink = override["link"] || linkItem(mark);
372
- let node;
373
- if (node = schema.nodes["image"])
374
- r.insertImage = override["image"] || insertImageItem(node);
375
- if (node = schema.nodes["bullet_list"])
376
- r.wrapBulletList = override["bullet_list"] || wrapListItem(node, {
377
- title: "Wrap in bullet list",
378
- icon: icons["bulletList"]
379
- });
380
- if (node = schema.nodes["ordered_list"])
381
- r.wrapOrderedList = override["ordered_list"] || wrapListItem(node, {
382
- title: "Wrap in ordered list",
383
- icon: icons["orderedList"]
384
- });
385
- if (node = schema.nodes["blockquote"])
386
- r.wrapBlockQuote = override["blockquote"] || wrapItem(node, {
387
- title: "Wrap in block quote",
388
- icon: icons["blockquote"]
389
- });
390
- if (node = schema.nodes["paragraph"])
391
- r.makeParagraph = override["paragraph"] || blockTypeItem(node, {
392
- title: "Change to paragraph",
393
- label: "Plain"
394
- });
395
- if (node = schema.nodes["code_block"])
396
- r.makeCodeBlock = override["code_block"] || blockTypeItem(node, {
397
- title: "Change to code block",
398
- label: "Code"
399
- });
400
- if (node = schema.nodes["heading"])
401
- for (let i = 1; i <= 10; i++)
402
- r["makeHead" + i] = override["makeHead" + i] || blockTypeItem(node, {
403
- title: "Change to heading " + i,
404
- label: "Level " + i,
405
- attrs: { level: i }
406
- });
407
- if (node = schema.nodes["horizontal_rule"]) {
408
- let hr = node;
409
- r.insertHorizontalRule = override["horizontal_rule"] || new MenuItem({
410
- title: "Insert horizontal rule",
411
- label: "Horizontal rule",
412
- enable(state) { return canInsert(state, hr); },
413
- run(state, dispatch) { dispatch(state.tr.replaceSelectionWith(hr.create())); }
414
- });
415
- }
416
- let cut = (arr) => arr.filter(x => x);
417
- r.insertMenu = new Dropdown(cut([r.insertImage, r.insertHorizontalRule]), { label: "Insert" });
418
- r.typeMenu = new Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new DropdownSubmenu(cut([
419
- r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6
420
- ]), { label: "Heading" })]), { label: "Type..." });
421
- r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])];
422
- r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, joinUpItem,
423
- liftItem, selectParentNodeItem])];
424
- r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[undoItem, redoItem]], r.blockMenu);
425
- return r;
291
+ let r = {};
292
+ let mark;
293
+ override = override || {};
294
+ if (mark = schema.marks["strong"]) r.toggleStrong = override["strong"] || markItem(mark, {
295
+ title: "Toggle strong style",
296
+ icon: icons["strong"]
297
+ });
298
+ if (mark = schema.marks["em"]) r.toggleEm = override["em"] || markItem(mark, {
299
+ title: "Toggle emphasis",
300
+ icon: icons["em"]
301
+ });
302
+ if (mark = schema.marks["code"]) r.toggleCode = override["code"] || markItem(mark, {
303
+ title: "Toggle code font",
304
+ icon: icons["code"]
305
+ });
306
+ if (mark = schema.marks["link"]) r.toggleLink = override["link"] || linkItem(mark);
307
+ let node;
308
+ if (node = schema.nodes["image"]) r.insertImage = override["image"] || insertImageItem(node);
309
+ if (node = schema.nodes["bullet_list"]) r.wrapBulletList = override["bullet_list"] || wrapListItem(node, {
310
+ title: "Wrap in bullet list",
311
+ icon: icons["bulletList"]
312
+ });
313
+ if (node = schema.nodes["ordered_list"]) r.wrapOrderedList = override["ordered_list"] || wrapListItem(node, {
314
+ title: "Wrap in ordered list",
315
+ icon: icons["orderedList"]
316
+ });
317
+ if (node = schema.nodes["blockquote"]) r.wrapBlockQuote = override["blockquote"] || wrapItem(node, {
318
+ title: "Wrap in block quote",
319
+ icon: icons["blockquote"]
320
+ });
321
+ if (node = schema.nodes["paragraph"]) r.makeParagraph = override["paragraph"] || blockTypeItem(node, {
322
+ title: "Change to paragraph",
323
+ label: "Plain"
324
+ });
325
+ if (node = schema.nodes["code_block"]) r.makeCodeBlock = override["code_block"] || blockTypeItem(node, {
326
+ title: "Change to code block",
327
+ label: "Code"
328
+ });
329
+ if (node = schema.nodes["heading"]) for (let i = 1; i <= 10; i++) r["makeHead" + i] = override["makeHead" + i] || blockTypeItem(node, {
330
+ title: "Change to heading " + i,
331
+ label: "Level " + i,
332
+ attrs: { level: i }
333
+ });
334
+ if (node = schema.nodes["horizontal_rule"]) {
335
+ let hr = node;
336
+ r.insertHorizontalRule = override["horizontal_rule"] || new MenuItem({
337
+ title: "Insert horizontal rule",
338
+ label: "Horizontal rule",
339
+ enable(state) {
340
+ return canInsert(state, hr);
341
+ },
342
+ run(state, dispatch) {
343
+ dispatch(state.tr.replaceSelectionWith(hr.create()));
344
+ }
345
+ });
346
+ }
347
+ let cut = (arr) => arr.filter((x) => x);
348
+ r.insertMenu = new Dropdown(cut([r.insertImage, r.insertHorizontalRule]), { label: "Insert" });
349
+ r.typeMenu = new Dropdown(cut([
350
+ r.makeParagraph,
351
+ r.makeCodeBlock,
352
+ r.makeHead1 && new DropdownSubmenu(cut([
353
+ r.makeHead1,
354
+ r.makeHead2,
355
+ r.makeHead3,
356
+ r.makeHead4,
357
+ r.makeHead5,
358
+ r.makeHead6
359
+ ]), { label: "Heading" })
360
+ ]), { label: "Type..." });
361
+ r.inlineMenu = [cut([
362
+ r.toggleStrong,
363
+ r.toggleEm,
364
+ r.toggleCode,
365
+ r.toggleLink
366
+ ])];
367
+ r.blockMenu = [cut([
368
+ r.wrapBulletList,
369
+ r.wrapOrderedList,
370
+ r.wrapBlockQuote,
371
+ joinUpItem,
372
+ liftItem,
373
+ selectParentNodeItem
374
+ ])];
375
+ r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[undoItem, redoItem]], r.blockMenu);
376
+ return r;
426
377
  }
427
378
  function blockQuoteRule(nodeType) {
428
- return wrappingInputRule(/^\s*>\s$/, nodeType);
379
+ return wrappingInputRule(/^\s*>\s$/, nodeType);
429
380
  }
430
- /// Given a list node type, returns an input rule that turns a number
431
- /// followed by a dot at the start of a textblock into an ordered list.
432
381
  function orderedListRule(nodeType) {
433
- return wrappingInputRule(/^(\d+)\.\s$/, nodeType, match => ({ order: +match[1] }), (match, node) => node.childCount + node.attrs["order"] == +match[1]);
382
+ return wrappingInputRule(/^(\d+)\.\s$/, nodeType, (match) => ({ order: +match[1] }), (match, node) => node.childCount + node.attrs["order"] == +match[1]);
434
383
  }
435
- /// Given a list node type, returns an input rule that turns a bullet
436
- /// (dash, plush, or asterisk) at the start of a textblock into a
437
- /// bullet list.
438
384
  function bulletListRule(nodeType) {
439
- return wrappingInputRule(/^\s*([-+*])\s$/, nodeType);
385
+ return wrappingInputRule(/^\s*([-+*])\s$/, nodeType);
440
386
  }
441
- /// Given a code block node type, returns an input rule that turns a
442
- /// textblock starting with three backticks into a code block.
443
387
  function codeBlockRule(nodeType) {
444
- return textblockTypeInputRule(/^```$/, nodeType);
388
+ return textblockTypeInputRule(/^```$/, nodeType);
445
389
  }
446
- /// Given a node type and a maximum level, creates an input rule that
447
- /// turns up to that number of `#` characters followed by a space at
448
- /// the start of a textblock into a heading whose level corresponds to
449
- /// the number of `#` signs.
450
390
  function headingRule(nodeType, maxLevel) {
451
- return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, match => ({ level: match[1].length }));
391
+ return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, (match) => ({ level: match[1].length }));
452
392
  }
453
- /// A set of input rules for creating the basic block quotes, lists,
454
- /// code blocks, and heading.
455
393
  function buildInputRules(schema) {
456
- let rules = smartQuotes.concat(ellipsis, emDash), type;
457
- if (type = schema.nodes["blockquote"])
458
- rules.push(blockQuoteRule(type));
459
- if (type = schema.nodes["ordered_list"])
460
- rules.push(orderedListRule(type));
461
- if (type = schema.nodes["bullet_list"])
462
- rules.push(bulletListRule(type));
463
- if (type = schema.nodes["code_block"])
464
- rules.push(codeBlockRule(type));
465
- if (type = schema.nodes["heading"])
466
- rules.push(headingRule(type, 6));
467
- return inputRules({ rules });
394
+ let rules = smartQuotes.concat(ellipsis, emDash), type;
395
+ if (type = schema.nodes["blockquote"]) rules.push(blockQuoteRule(type));
396
+ if (type = schema.nodes["ordered_list"]) rules.push(orderedListRule(type));
397
+ if (type = schema.nodes["bullet_list"]) rules.push(bulletListRule(type));
398
+ if (type = schema.nodes["code_block"]) rules.push(codeBlockRule(type));
399
+ if (type = schema.nodes["heading"]) rules.push(headingRule(type, 6));
400
+ return inputRules({ rules });
468
401
  }
469
- /// Create an array of plugins pre-configured for the given schema.
470
- /// The resulting array will include the following plugins:
471
- ///
472
- /// * Input rules for smart quotes and creating the block types in the
473
- /// schema using markdown conventions (say `"> "` to create a
474
- /// blockquote)
475
- ///
476
- /// * A keymap that defines keys to create and manipulate the nodes in the
477
- /// schema
478
- ///
479
- /// * A keymap binding the default keys provided by the
480
- /// prosemirror-commands module
481
- ///
482
- /// * The undo history plugin
483
- ///
484
- /// * The drop cursor plugin
485
- ///
486
- /// * The gap cursor plugin
487
- ///
488
- /// * A custom plugin that adds a `menuContent` prop for the
489
- /// prosemirror-menu wrapper, and a CSS class that enables the
490
- /// additional styling defined in `style/style.css` in this package
491
- ///
492
- /// Probably only useful for quickly setting up a passable
493
- /// editor—you'll need more control over your settings in most
494
- /// real-world situations.
495
402
  function basicSetup(options) {
496
- let plugins = [
497
- buildInputRules(options.schema),
498
- keymap(buildKeymap(options.schema, options.mapKeys)),
499
- keymap(baseKeymap),
500
- dropCursor(),
501
- gapCursor()
502
- ];
503
- if (options.menuBar !== false)
504
- plugins.push(menuBar({ floating: options.floatingMenu !== false,
505
- content: buildMenuItems(options.schema, options.menuContent).fullMenu }));
506
- if (options.history !== false)
507
- plugins.push(history());
508
- return plugins; /*.concat(new Plugin({
509
- props: {
510
- attributes: {class: "ProseMirror-example-setup-style"}
511
- }
512
- }))*/
513
- }
514
-
515
- class MarkdownPipe {
516
- constructor(sanitizer) {
517
- this.sanitizer = sanitizer;
518
- }
519
- transform(value, ...args) {
520
- if (typeof value === 'string') {
521
- const html = marked.parse(value.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/, ""), {
522
- async: false
523
- });
524
- return this.sanitizer.sanitize(SecurityContext.HTML, html);
525
- }
526
- return null;
527
- }
528
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: MarkdownPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
529
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.26", ngImport: i0, type: MarkdownPipe, isStandalone: true, name: "markdown" }); }
530
- }
531
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: MarkdownPipe, decorators: [{
532
- type: Pipe,
533
- args: [{
534
- name: 'markdown',
535
- }]
536
- }], ctorParameters: () => [{ type: i1.DomSanitizer }] });
537
-
538
- class InlineMarkdownPipe {
539
- transform(value, ...args) {
540
- if (typeof value === 'string') {
541
- let text = value;
542
- if (text.length > 100)
543
- text = text.substring(0, 100); // For inline text, we don't want all the text, just the start
544
- text = text.replace(/!\[[^\]]*\]\([^)]*\)/g, ''); // images
545
- text = text.replace(/\[([^\]]*)\]\([^)]*\)/g, '$1'); // links -> visible text
546
- text = text.replace(/^#{1,6}\s*/gm, ''); // headers
547
- text = text.replace(/^\s*[-*+]\s+/gm, ''); // bullet lists
548
- text = text.replace(/^\s*\d+[.)]\s+/gm, ''); // numbered lists
549
- text = text.replace(/^\s*[-*]\s+/gm, ''); // bullets that were bold markers
550
- text = text.replace(/\*\*([^*]*)\*\*/g, '$1'); // bold
551
- text = text.replace(/\*([^*]*)\*/g, '$1'); // italic *
552
- text = text.replace(/(?<!\w)_([^_\n]+)_(?!\w)/g, '$1'); // italic _text_
553
- text = text.replace(/\s*\n\s*/g, ' '); // newlines -> spaces
554
- text = text.replace(/\s{2,}/g, ' ').trim(); // collapse
555
- if (text.length > 57) {
556
- return text.substring(0, 57) + '...';
557
- }
558
- return text;
559
- }
560
- return null;
561
- }
562
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: InlineMarkdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
563
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.26", ngImport: i0, type: InlineMarkdownPipe, isStandalone: true, name: "inlineMarkdown" }); }
403
+ let plugins = [
404
+ buildInputRules(options.schema),
405
+ keymap(buildKeymap(options.schema, options.mapKeys)),
406
+ keymap(baseKeymap),
407
+ dropCursor(),
408
+ gapCursor()
409
+ ];
410
+ if (options.menuBar !== false) plugins.push(menuBar({
411
+ floating: options.floatingMenu !== false,
412
+ content: buildMenuItems(options.schema, options.menuContent).fullMenu
413
+ }));
414
+ if (options.history !== false) plugins.push(history());
415
+ return plugins;
564
416
  }
565
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: InlineMarkdownPipe, decorators: [{
566
- type: Pipe,
567
- args: [{
568
- name: 'inlineMarkdown',
569
- }]
570
- }] });
571
-
572
- class EditorComponent extends XtSimpleComponent {
573
- constructor() {
574
- super();
575
- this.context = input.required(...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
576
- this.resolver = inject(XtResolverService);
577
- this.editor = viewChild('editor', ...(ngDevMode ? [{ debugName: "editor" }] : /* istanbul ignore next */ []));
578
- this.sampleJson = { "type": "doc", "content": [{ "type": "heading", "attrs": { "level": 1 }, "content": [{ "type": "text", "text": "Example Text" }] }, { "type": "paragraph", "content": [{ "type": "text", "text": "s it working ?" }] }] };
579
- this.emptyJson = { "type": "doc", "content": [{ "type": "paragraph" }] };
580
- // Mix the nodes from prosemirror-schema-list into the basic schema to create a schema with list support.
581
- /** mySchema: Schema = new Schema({
582
- nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"),
583
- marks: schema.spec.marks
584
- });*/
585
- // Creates the markdown schema
586
- this.mySchema = schema;
587
- this.view = null;
588
- /**
589
- * Enable dialog box for image or link editing
590
- * @protected
591
- */
592
- this.displayAttrDialog = signal(false, ...(ngDevMode ? [{ debugName: "displayAttrDialog" }] : /* istanbul ignore next */ []));
593
- this.editAttrForm = new FormGroup({});
594
- this.editAttrNodeType = this.mySchema['image'];
595
- this.editAttrValueType = "editorImageType";
596
- const imageType = this.resolver.typeResolver.findType('image');
597
- const linkType = this.resolver.typeResolver.findType('link');
598
- // Register the type with the image type if supported
599
- this.resolver.registerTypes({
600
- editorImageType: {
601
- children: {
602
- src: (imageType == null) ? "string" : "image",
603
- title: "string",
604
- alt: "string"
605
- }
606
- },
607
- editorLinkType: {
608
- children: {
609
- href: (linkType == null) ? "string" : "link",
610
- title: "string"
611
- }
612
- }
613
- });
614
- updateFormGroupWithValue(this.editAttrForm, {}, 'editorImageType', this.resolver.typeResolver);
615
- // Setup the editor once the divs are available
616
- effect(() => {
617
- const editor = this.editor();
618
- if ((editor != null) && (this.view == null)) {
619
- const value = this.context().formControlValue();
620
- const doc = this.toProseMirrorDoc(value);
621
- this.view = new EditorView(editor.nativeElement, {
622
- state: EditorState.create({
623
- doc: doc,
624
- plugins: basicSetup({ schema: this.mySchema, menuContent: {
625
- image: this.imageMenu(this.mySchema.nodes['image'], this),
626
- link: this.linkMenu(this.mySchema.marks['link'], this)
627
- } })
628
- }),
629
- dispatchTransaction: this.handleTransactions.bind(this)
630
- });
631
- }
632
- });
633
- }
634
- ngAfterViewInit() {
635
- /* this.editor.valueChanges.pipe(takeUntil(this.unsubscribe)).subscribe((jsonDoc) => {
636
- this.handleChange(jsonDoc);
637
- });*/
638
- }
639
- imageMenu(imageNodeType, that) {
640
- return new MenuItem({
641
- title: "Insert image",
642
- label: "Image",
643
- enable(state) {
644
- return canInsert(state, imageNodeType);
645
- },
646
- run(state, _, view) {
647
- let { from, to } = state.selection, attrs = {};
648
- if (state.selection instanceof NodeSelection && state.selection.node.type == imageNodeType)
649
- attrs = state.selection.node.attrs || {};
650
- if (attrs.alt == null)
651
- attrs.alt = state.doc.textBetween(from, to, " ");
652
- that.editAttrValueType = "editorImageType";
653
- updateFormGroupWithValue(that.editAttrForm, attrs, that.editAttrValueType, that.resolver.typeResolver);
654
- that.editAttrNodeType = imageNodeType;
655
- that.displayAttrDialog.set(true);
656
- }
657
- });
658
- }
659
- updateAttrsFromForm() {
660
- if (this.view != null) {
661
- if (this.editAttrValueType == "editorImageType") {
662
- this.view.dispatch(this.view.state.tr.replaceSelectionWith((this.mySchema.nodes['image']).createAndFill(this.editAttrForm.value)));
663
- }
664
- else if (this.editAttrValueType == "editorLinkType") {
665
- toggleMark(this.editAttrNodeType, this.editAttrForm.value)(this.view.state, this.view.dispatch);
666
- }
667
- this.view.focus();
668
- }
669
- this.displayAttrDialog.set(false);
670
- }
671
- linkMenu(linkMarkType, that) {
672
- return new MenuItem({
673
- title: "Add or Remove link",
674
- icon: icons["link"],
675
- active(state) { return markActive(state, linkMarkType); },
676
- enable(state) { return !state.selection.empty; },
677
- run(state, _, view) {
678
- let { from, to } = state.selection, attrs = {};
679
- if (markActive(state, linkMarkType)) {
680
- toggleMark(linkMarkType)(state, view.dispatch);
681
- return true;
682
- }
683
- that.editAttrValueType = "editorLinkType";
684
- updateFormGroupWithValue(that.editAttrForm, attrs, that.editAttrValueType, that.resolver.typeResolver);
685
- that.editAttrNodeType = linkMarkType;
686
- that.displayAttrDialog.set(true);
687
- return true;
688
- }
689
- });
690
- }
691
- handleTransactions(tr) {
692
- if (this.view != null) {
693
- const state = this.view.state.apply(tr);
694
- this.view.updateState(state);
695
- if (tr.docChanged) {
696
- const markdown = defaultMarkdownSerializer.serialize(state.doc);
697
- this.context().setFormValue(markdown, true);
698
- }
699
- }
700
- else {
701
- console.error("Editor: View transaction received while no view defined.", tr.doc.toJSON());
702
- }
703
- }
704
- toProseMirrorDoc(value) {
705
- if (value == null) {
706
- return this.mySchema.nodeFromJSON(this.emptyJson);
707
- }
708
- if (typeof value === 'string') {
709
- // This is a markdown text,
710
- return defaultMarkdownParser.parse(value);
711
- }
712
- return this.mySchema.nodeFromJSON(value);
713
- }
714
- textJson(text) {
715
- return { "type": "doc", "content": [{ "type": "paragraph", "content": [{ "type": "text", "text": text }] }] };
716
- }
717
- ;
718
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: EditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
719
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.26", type: EditorComponent, isStandalone: true, selector: "xt-editor-editor", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "editor", first: true, predicate: ["editor"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (isInForm() ) {\n <div class=\"editorContainer\">\n <div #editor [formGroup]=\"formGroup()\">\n </div>\n </div>\n <p-dialog [visible]=\"displayAttrDialog()\" [modal]=\"true\" header=\"Edit\">\n <form [formGroup]=\"editAttrForm\">\n <xt-render [valueType]=\"editAttrValueType\" [formGroup]=\"editAttrForm\" displayMode=\"FULL_EDITABLE\" ></xt-render>\n </form>\n <ng-template #footer>\n <button type=\"button\" pButton severity=\"secondary\" variant=\"outlined\" (click)=\"displayAttrDialog.set(false)\">Cancel</button>\n <button type=\"button\" pButton (click)=\"updateAttrsFromForm()\">Save</button>\n </ng-template>\n </p-dialog>\n} @else {\n @let toDisplay=displayValue();\n @if (toDisplay!=null) {\n @if (context().displayMode=='FULL_VIEW') {\n <div class=\"displayForm\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n } @else {\n <span [pTooltip]=\"fullText\">{{ toDisplay | inlineMarkdown}}</span>\n <ng-template #fullText>\n <div class=\"toolTip\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n </ng-template>\n }\n }\n}\n", styles: [".editorContainer{width:60em;border:white solid thin;padding:5px}.toolTip{white-space:normal}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: XtRenderComponent, selector: "xt-render", inputs: ["componentType", "displayMode", "valueType", "value", "formGroup", "subName", "inputs", "models"], outputs: ["valueChange", "outputs"] }, { kind: "directive", type: ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "pipe", type: MarkdownPipe, name: "markdown" }, { kind: "pipe", type: InlineMarkdownPipe, name: "inlineMarkdown" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
720
- }
721
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: EditorComponent, decorators: [{
722
- type: Component,
723
- args: [{ selector: 'xt-editor-editor', imports: [
724
- ReactiveFormsModule,
725
- FormsModule,
726
- MarkdownPipe, InlineMarkdownPipe, Tooltip, Dialog,
727
- XtRenderComponent, ButtonDirective
728
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isInForm() ) {\n <div class=\"editorContainer\">\n <div #editor [formGroup]=\"formGroup()\">\n </div>\n </div>\n <p-dialog [visible]=\"displayAttrDialog()\" [modal]=\"true\" header=\"Edit\">\n <form [formGroup]=\"editAttrForm\">\n <xt-render [valueType]=\"editAttrValueType\" [formGroup]=\"editAttrForm\" displayMode=\"FULL_EDITABLE\" ></xt-render>\n </form>\n <ng-template #footer>\n <button type=\"button\" pButton severity=\"secondary\" variant=\"outlined\" (click)=\"displayAttrDialog.set(false)\">Cancel</button>\n <button type=\"button\" pButton (click)=\"updateAttrsFromForm()\">Save</button>\n </ng-template>\n </p-dialog>\n} @else {\n @let toDisplay=displayValue();\n @if (toDisplay!=null) {\n @if (context().displayMode=='FULL_VIEW') {\n <div class=\"displayForm\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n } @else {\n <span [pTooltip]=\"fullText\">{{ toDisplay | inlineMarkdown}}</span>\n <ng-template #fullText>\n <div class=\"toolTip\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n </ng-template>\n }\n }\n}\n", styles: [".editorContainer{width:60em;border:white solid thin;padding:5px}.toolTip{white-space:normal}\n"] }]
729
- }], ctorParameters: () => [], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: true }] }], editor: [{ type: i0.ViewChild, args: ['editor', { isSignal: true }] }] } });
730
-
417
+ var MarkdownPipe = class MarkdownPipe {
418
+ constructor(sanitizer) {
419
+ this.sanitizer = sanitizer;
420
+ }
421
+ transform(value, ...args) {
422
+ if (typeof value === "string") {
423
+ const html = marked.parse(value.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/, ""), { async: false });
424
+ return this.sanitizer.sanitize(SecurityContext.HTML, html);
425
+ }
426
+ return null;
427
+ }
428
+ static {
429
+ this.ɵfac = i0.ɵɵngDeclareFactory({
430
+ minVersion: "12.0.0",
431
+ version: "22.2.6",
432
+ ngImport: i0,
433
+ type: MarkdownPipe,
434
+ deps: [{ token: i1$1.DomSanitizer }],
435
+ target: i0.ɵɵFactoryTarget.Pipe
436
+ });
437
+ }
438
+ static {
439
+ this.ɵpipe = i0.ɵɵngDeclarePipe({
440
+ minVersion: "14.0.0",
441
+ version: "22.2.6",
442
+ ngImport: i0,
443
+ type: MarkdownPipe,
444
+ isStandalone: true,
445
+ name: "markdown"
446
+ });
447
+ }
448
+ };
449
+ i0.ɵɵngDeclareClassMetadata({
450
+ minVersion: "12.0.0",
451
+ version: "22.2.6",
452
+ ngImport: i0,
453
+ type: MarkdownPipe,
454
+ decorators: [{
455
+ type: Pipe,
456
+ args: [{ name: "markdown" }]
457
+ }],
458
+ ctorParameters: () => [{ type: i1$1.DomSanitizer }]
459
+ });
460
+ var InlineMarkdownPipe = class InlineMarkdownPipe {
461
+ transform(value, ...args) {
462
+ if (typeof value === "string") {
463
+ let text = value;
464
+ if (text.length > 100) text = text.substring(0, 100);
465
+ text = text.replace(/!\[[^\]]*\]\([^)]*\)/g, "");
466
+ text = text.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
467
+ text = text.replace(/^#{1,6}\s*/gm, "");
468
+ text = text.replace(/^\s*[-*+]\s+/gm, "");
469
+ text = text.replace(/^\s*\d+[.)]\s+/gm, "");
470
+ text = text.replace(/^\s*[-*]\s+/gm, "");
471
+ text = text.replace(/\*\*([^*]*)\*\*/g, "$1");
472
+ text = text.replace(/\*([^*]*)\*/g, "$1");
473
+ text = text.replace(/(?<!\w)_([^_\n]+)_(?!\w)/g, "$1");
474
+ text = text.replace(/\s*\n\s*/g, " ");
475
+ text = text.replace(/\s{2,}/g, " ").trim();
476
+ if (text.length > 57) return text.substring(0, 57) + "...";
477
+ return text;
478
+ }
479
+ return null;
480
+ }
481
+ static {
482
+ this.ɵfac = i0.ɵɵngDeclareFactory({
483
+ minVersion: "12.0.0",
484
+ version: "22.2.6",
485
+ ngImport: i0,
486
+ type: InlineMarkdownPipe,
487
+ deps: [],
488
+ target: i0.ɵɵFactoryTarget.Pipe
489
+ });
490
+ }
491
+ static {
492
+ this.ɵpipe = i0.ɵɵngDeclarePipe({
493
+ minVersion: "14.0.0",
494
+ version: "22.2.6",
495
+ ngImport: i0,
496
+ type: InlineMarkdownPipe,
497
+ isStandalone: true,
498
+ name: "inlineMarkdown"
499
+ });
500
+ }
501
+ };
502
+ i0.ɵɵngDeclareClassMetadata({
503
+ minVersion: "12.0.0",
504
+ version: "22.2.6",
505
+ ngImport: i0,
506
+ type: InlineMarkdownPipe,
507
+ decorators: [{
508
+ type: Pipe,
509
+ args: [{ name: "inlineMarkdown" }]
510
+ }]
511
+ });
512
+ var EditorComponent = class EditorComponent extends XtSimpleComponent {
513
+ constructor() {
514
+ super();
515
+ this.context = input.required(...ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []);
516
+ this.resolver = inject(XtResolverService);
517
+ this.editor = viewChild("editor", ...ngDevMode ? [{ debugName: "editor" }] : /* istanbul ignore next */ []);
518
+ this.sampleJson = {
519
+ "type": "doc",
520
+ "content": [{
521
+ "type": "heading",
522
+ "attrs": { "level": 1 },
523
+ "content": [{
524
+ "type": "text",
525
+ "text": "Example Text"
526
+ }]
527
+ }, {
528
+ "type": "paragraph",
529
+ "content": [{
530
+ "type": "text",
531
+ "text": "s it working ?"
532
+ }]
533
+ }]
534
+ };
535
+ this.emptyJson = {
536
+ "type": "doc",
537
+ "content": [{ "type": "paragraph" }]
538
+ };
539
+ this.mySchema = schema;
540
+ this.view = null;
541
+ this.displayAttrDialog = signal(false, ...ngDevMode ? [{ debugName: "displayAttrDialog" }] : /* istanbul ignore next */ []);
542
+ this.editAttrForm = new FormGroup({});
543
+ this.editAttrNodeType = this.mySchema["image"];
544
+ this.editAttrValueType = "editorImageType";
545
+ const imageType = this.resolver.typeResolver.findType("image");
546
+ const linkType = this.resolver.typeResolver.findType("link");
547
+ this.resolver.registerTypes({
548
+ editorImageType: { children: {
549
+ src: imageType == null ? "string" : "image",
550
+ title: "string",
551
+ alt: "string"
552
+ } },
553
+ editorLinkType: { children: {
554
+ href: linkType == null ? "string" : "link",
555
+ title: "string"
556
+ } }
557
+ });
558
+ updateFormGroupWithValue(this.editAttrForm, {}, "editorImageType", this.resolver.typeResolver);
559
+ effect(() => {
560
+ const editor = this.editor();
561
+ if (editor != null && this.view == null) {
562
+ const value = this.context().formControlValue();
563
+ const doc = this.toProseMirrorDoc(value);
564
+ this.view = new EditorView(editor.nativeElement, {
565
+ state: EditorState.create({
566
+ doc,
567
+ plugins: basicSetup({
568
+ schema: this.mySchema,
569
+ menuContent: {
570
+ image: this.imageMenu(this.mySchema.nodes["image"], this),
571
+ link: this.linkMenu(this.mySchema.marks["link"], this)
572
+ }
573
+ })
574
+ }),
575
+ dispatchTransaction: this.handleTransactions.bind(this)
576
+ });
577
+ }
578
+ });
579
+ }
580
+ ngAfterViewInit() {}
581
+ imageMenu(imageNodeType, that) {
582
+ return new MenuItem({
583
+ title: "Insert image",
584
+ label: "Image",
585
+ enable(state) {
586
+ return canInsert(state, imageNodeType);
587
+ },
588
+ run(state, _, view) {
589
+ let { from, to } = state.selection, attrs = {};
590
+ if (state.selection instanceof NodeSelection && state.selection.node.type == imageNodeType) attrs = state.selection.node.attrs || {};
591
+ if (attrs.alt == null) attrs.alt = state.doc.textBetween(from, to, " ");
592
+ that.editAttrValueType = "editorImageType";
593
+ updateFormGroupWithValue(that.editAttrForm, attrs, that.editAttrValueType, that.resolver.typeResolver);
594
+ that.editAttrNodeType = imageNodeType;
595
+ that.displayAttrDialog.set(true);
596
+ }
597
+ });
598
+ }
599
+ updateAttrsFromForm() {
600
+ if (this.view != null) {
601
+ if (this.editAttrValueType == "editorImageType") this.view.dispatch(this.view.state.tr.replaceSelectionWith(this.mySchema.nodes["image"].createAndFill(this.editAttrForm.value)));
602
+ else if (this.editAttrValueType == "editorLinkType") toggleMark(this.editAttrNodeType, this.editAttrForm.value)(this.view.state, this.view.dispatch);
603
+ this.view.focus();
604
+ }
605
+ this.displayAttrDialog.set(false);
606
+ }
607
+ linkMenu(linkMarkType, that) {
608
+ return new MenuItem({
609
+ title: "Add or Remove link",
610
+ icon: icons["link"],
611
+ active(state) {
612
+ return markActive(state, linkMarkType);
613
+ },
614
+ enable(state) {
615
+ return !state.selection.empty;
616
+ },
617
+ run(state, _, view) {
618
+ let { from, to } = state.selection, attrs = {};
619
+ if (markActive(state, linkMarkType)) {
620
+ toggleMark(linkMarkType)(state, view.dispatch);
621
+ return true;
622
+ }
623
+ that.editAttrValueType = "editorLinkType";
624
+ updateFormGroupWithValue(that.editAttrForm, attrs, that.editAttrValueType, that.resolver.typeResolver);
625
+ that.editAttrNodeType = linkMarkType;
626
+ that.displayAttrDialog.set(true);
627
+ return true;
628
+ }
629
+ });
630
+ }
631
+ handleTransactions(tr) {
632
+ if (this.view != null) {
633
+ const state = this.view.state.apply(tr);
634
+ this.view.updateState(state);
635
+ if (tr.docChanged) {
636
+ const markdown = defaultMarkdownSerializer.serialize(state.doc);
637
+ this.context().setFormValue(markdown, true);
638
+ }
639
+ } else console.error("Editor: View transaction received while no view defined.", tr.doc.toJSON());
640
+ }
641
+ toProseMirrorDoc(value) {
642
+ if (value == null) return this.mySchema.nodeFromJSON(this.emptyJson);
643
+ if (typeof value === "string") return defaultMarkdownParser.parse(value);
644
+ return this.mySchema.nodeFromJSON(value);
645
+ }
646
+ textJson(text) {
647
+ return {
648
+ "type": "doc",
649
+ "content": [{
650
+ "type": "paragraph",
651
+ "content": [{
652
+ "type": "text",
653
+ "text": text
654
+ }]
655
+ }]
656
+ };
657
+ }
658
+ static {
659
+ this.ɵfac = i0.ɵɵngDeclareFactory({
660
+ minVersion: "12.0.0",
661
+ version: "22.2.6",
662
+ ngImport: i0,
663
+ type: EditorComponent,
664
+ deps: [],
665
+ target: i0.ɵɵFactoryTarget.Component
666
+ });
667
+ }
668
+ static {
669
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
670
+ minVersion: "17.0.0",
671
+ version: "22.2.6",
672
+ type: EditorComponent,
673
+ isStandalone: true,
674
+ selector: "xt-editor-editor",
675
+ inputs: { context: {
676
+ classPropertyName: "context",
677
+ publicName: "context",
678
+ isSignal: true,
679
+ isRequired: true,
680
+ transformFunction: null
681
+ } },
682
+ viewQueries: [{
683
+ propertyName: "editor",
684
+ first: true,
685
+ predicate: ["editor"],
686
+ descendants: true,
687
+ isSignal: true
688
+ }],
689
+ usesInheritance: true,
690
+ ngImport: i0,
691
+ template: "@if (isInForm() ) {\n <div class=\"editorContainer\">\n <div #editor [formGroup]=\"formGroup()\">\n </div>\n </div>\n <p-dialog [visible]=\"displayAttrDialog()\" [modal]=\"true\" header=\"Edit\">\n <form [formGroup]=\"editAttrForm\">\n <xt-render [valueType]=\"editAttrValueType\" [formGroup]=\"editAttrForm\" displayMode=\"FULL_EDITABLE\" ></xt-render>\n </form>\n <ng-template #footer>\n <button type=\"button\" pButton severity=\"secondary\" variant=\"outlined\" (click)=\"displayAttrDialog.set(false)\">Cancel</button>\n <button type=\"button\" pButton (click)=\"updateAttrsFromForm()\">Save</button>\n </ng-template>\n </p-dialog>\n} @else {\n @let toDisplay=displayValue();\n @if (toDisplay!=null) {\n @if (context().displayMode=='FULL_VIEW') {\n <div class=\"displayForm\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n } @else {\n <span [pTooltip]=\"fullText\">{{ toDisplay | inlineMarkdown}}</span>\n <ng-template #fullText>\n <div class=\"toolTip\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n </ng-template>\n }\n }\n}\n",
692
+ styles: [".editorContainer{width:60em;border:white solid thin;padding:5px}.toolTip{white-space:normal}\n"],
693
+ dependencies: [
694
+ {
695
+ kind: "ngmodule",
696
+ type: ReactiveFormsModule
697
+ },
698
+ {
699
+ kind: "directive",
700
+ type: i1.ɵNgNoValidate,
701
+ selector: "form:not([ngNoForm]):not([ngNativeValidate])"
702
+ },
703
+ {
704
+ kind: "directive",
705
+ type: i1.NgControlStatusGroup,
706
+ selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"
707
+ },
708
+ {
709
+ kind: "directive",
710
+ type: i1.FormGroupDirective,
711
+ selector: "[formGroup]",
712
+ inputs: ["formGroup"],
713
+ outputs: ["ngSubmit"],
714
+ exportAs: ["ngForm"]
715
+ },
716
+ {
717
+ kind: "ngmodule",
718
+ type: FormsModule
719
+ },
720
+ {
721
+ kind: "directive",
722
+ type: Tooltip,
723
+ selector: "[pTooltip]",
724
+ inputs: [
725
+ "tooltipPosition",
726
+ "tooltipEvent",
727
+ "positionStyle",
728
+ "tooltipStyleClass",
729
+ "tooltipZIndex",
730
+ "escape",
731
+ "showDelay",
732
+ "hideDelay",
733
+ "life",
734
+ "positionTop",
735
+ "positionLeft",
736
+ "autoHide",
737
+ "fitContent",
738
+ "hideOnEscape",
739
+ "showOnEllipsis",
740
+ "pTooltip",
741
+ "tooltipDisabled",
742
+ "tooltipOptions",
743
+ "appendTo",
744
+ "ptTooltip",
745
+ "pTooltipPT",
746
+ "pTooltipUnstyled"
747
+ ]
748
+ },
749
+ {
750
+ kind: "component",
751
+ type: Dialog,
752
+ selector: "p-dialog",
753
+ inputs: [
754
+ "hostName",
755
+ "header",
756
+ "draggable",
757
+ "resizable",
758
+ "contentStyle",
759
+ "contentStyleClass",
760
+ "modal",
761
+ "closeOnEscape",
762
+ "dismissableMask",
763
+ "rtl",
764
+ "closable",
765
+ "breakpoints",
766
+ "styleClass",
767
+ "maskStyleClass",
768
+ "maskStyle",
769
+ "showHeader",
770
+ "blockScroll",
771
+ "autoZIndex",
772
+ "baseZIndex",
773
+ "minX",
774
+ "minY",
775
+ "focusOnShow",
776
+ "maximizable",
777
+ "keepInViewport",
778
+ "focusTrap",
779
+ "transitionOptions",
780
+ "maskMotionOptions",
781
+ "motionOptions",
782
+ "closeIcon",
783
+ "closeAriaLabel",
784
+ "closeTabindex",
785
+ "minimizeIcon",
786
+ "maximizeIcon",
787
+ "closeButtonProps",
788
+ "maximizeButtonProps",
789
+ "visible",
790
+ "style",
791
+ "position",
792
+ "role",
793
+ "ariaLabelledBy",
794
+ "appendTo",
795
+ "content",
796
+ "contentTemplate",
797
+ "footerTemplate",
798
+ "closeIconTemplate",
799
+ "maximizeIconTemplate",
800
+ "minimizeIconTemplate",
801
+ "headlessTemplate"
802
+ ],
803
+ outputs: [
804
+ "onShow",
805
+ "onHide",
806
+ "visibleChange",
807
+ "onResizeInit",
808
+ "onResizeEnd",
809
+ "onDragEnd",
810
+ "onMaximize"
811
+ ]
812
+ },
813
+ {
814
+ kind: "component",
815
+ type: XtRenderComponent,
816
+ selector: "xt-render",
817
+ inputs: [
818
+ "componentType",
819
+ "displayMode",
820
+ "valueType",
821
+ "value",
822
+ "formGroup",
823
+ "subName",
824
+ "inputs",
825
+ "models"
826
+ ],
827
+ outputs: ["valueChange", "outputs"]
828
+ },
829
+ {
830
+ kind: "directive",
831
+ type: ButtonDirective,
832
+ selector: "[pButton]",
833
+ inputs: [
834
+ "ptButtonDirective",
835
+ "pButtonPT",
836
+ "pButtonUnstyled",
837
+ "hostName",
838
+ "text",
839
+ "plain",
840
+ "raised",
841
+ "size",
842
+ "outlined",
843
+ "rounded",
844
+ "iconPos",
845
+ "loadingIcon",
846
+ "fluid",
847
+ "label",
848
+ "icon",
849
+ "loading",
850
+ "buttonProps",
851
+ "severity"
852
+ ]
853
+ },
854
+ {
855
+ kind: "pipe",
856
+ type: MarkdownPipe,
857
+ name: "markdown"
858
+ },
859
+ {
860
+ kind: "pipe",
861
+ type: InlineMarkdownPipe,
862
+ name: "inlineMarkdown"
863
+ }
864
+ ],
865
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
866
+ });
867
+ }
868
+ };
869
+ i0.ɵɵngDeclareClassMetadata({
870
+ minVersion: "12.0.0",
871
+ version: "22.2.6",
872
+ ngImport: i0,
873
+ type: EditorComponent,
874
+ decorators: [{
875
+ type: Component,
876
+ args: [{
877
+ selector: "xt-editor-editor",
878
+ imports: [
879
+ ReactiveFormsModule,
880
+ FormsModule,
881
+ MarkdownPipe,
882
+ InlineMarkdownPipe,
883
+ Tooltip,
884
+ Dialog,
885
+ XtRenderComponent,
886
+ ButtonDirective
887
+ ],
888
+ changeDetection: ChangeDetectionStrategy.OnPush,
889
+ template: "@if (isInForm() ) {\n <div class=\"editorContainer\">\n <div #editor [formGroup]=\"formGroup()\">\n </div>\n </div>\n <p-dialog [visible]=\"displayAttrDialog()\" [modal]=\"true\" header=\"Edit\">\n <form [formGroup]=\"editAttrForm\">\n <xt-render [valueType]=\"editAttrValueType\" [formGroup]=\"editAttrForm\" displayMode=\"FULL_EDITABLE\" ></xt-render>\n </form>\n <ng-template #footer>\n <button type=\"button\" pButton severity=\"secondary\" variant=\"outlined\" (click)=\"displayAttrDialog.set(false)\">Cancel</button>\n <button type=\"button\" pButton (click)=\"updateAttrsFromForm()\">Save</button>\n </ng-template>\n </p-dialog>\n} @else {\n @let toDisplay=displayValue();\n @if (toDisplay!=null) {\n @if (context().displayMode=='FULL_VIEW') {\n <div class=\"displayForm\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n } @else {\n <span [pTooltip]=\"fullText\">{{ toDisplay | inlineMarkdown}}</span>\n <ng-template #fullText>\n <div class=\"toolTip\" [innerHTML]=\"displayValue() | markdown\">\n </div>\n </ng-template>\n }\n }\n}\n",
890
+ styles: [".editorContainer{width:60em;border:white solid thin;padding:5px}.toolTip{white-space:normal}\n"]
891
+ }]
892
+ }],
893
+ ctorParameters: () => [],
894
+ propDecorators: {
895
+ context: [{
896
+ type: i0.Input,
897
+ args: [{
898
+ isSignal: true,
899
+ alias: "context",
900
+ required: true
901
+ }]
902
+ }],
903
+ editor: [{
904
+ type: i0.ViewChild,
905
+ args: ["editor", { isSignal: true }]
906
+ }]
907
+ }
908
+ });
731
909
  function registerEditorPlugin(resolverService) {
732
- const pluginName = "Plugin Editor";
733
- console.info('Registering ' + pluginName);
734
- resolverService.registerPlugin({
735
- name: pluginName,
736
- uriLogo: 'pluginicon.png',
737
- cssUrls: [
738
- 'prosemirror-view/style/prosemirror.css',
739
- 'prosemirror-menu/style/menu.css',
740
- 'prosemirror-gapcursor/style/gapcursor.css'
741
- ],
742
- components: [
743
- {
744
- componentName: 'Editor',
745
- componentClass: EditorComponent,
746
- typesHandled: ['markdown', 'rich-text', 'description'],
747
- }
748
- ],
749
- types: {
750
- 'markdown': 'string',
751
- 'rich-text': 'string',
752
- 'description': 'string'
753
- }
754
- });
755
- return pluginName;
910
+ const pluginName = "Plugin Editor";
911
+ console.info("Registering " + pluginName);
912
+ resolverService.registerPlugin({
913
+ name: pluginName,
914
+ uriLogo: "pluginicon.png",
915
+ cssUrls: [
916
+ "prosemirror-view/style/prosemirror.css",
917
+ "prosemirror-menu/style/menu.css",
918
+ "prosemirror-gapcursor/style/gapcursor.css"
919
+ ],
920
+ components: [{
921
+ componentName: "Editor",
922
+ componentClass: EditorComponent,
923
+ typesHandled: [
924
+ "markdown",
925
+ "rich-text",
926
+ "description"
927
+ ]
928
+ }],
929
+ types: {
930
+ "markdown": "string",
931
+ "rich-text": "string",
932
+ "description": "string"
933
+ }
934
+ });
935
+ return pluginName;
756
936
  }
757
937
  function registerPlugin(resolverService) {
758
- return registerEditorPlugin(resolverService);
938
+ return registerEditorPlugin(resolverService);
759
939
  }
760
-
761
- /*
762
- * Public API Surface of web plugin
763
- */
764
-
765
- /**
766
- * Generated bundle index. Do not edit.
767
- */
768
-
769
940
  export { EditorComponent, MarkdownPipe, registerEditorPlugin, registerPlugin };
770
- //# sourceMappingURL=xt-plugin-editor.mjs.map
941
+
942
+ //# sourceMappingURL=xt-plugin-editor.mjs.map