xt-plugin-editor 1.0.0 → 1.3.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.
Files changed (55) hide show
  1. package/README.md +1 -1
  2. package/fesm2022/xt-plugin-editor.mjs +770 -0
  3. package/fesm2022/xt-plugin-editor.mjs.map +1 -0
  4. package/package.json +37 -64
  5. package/types/xt-plugin-editor.d.ts +88 -0
  6. package/types/xt-plugin-editor.d.ts.map +1 -0
  7. package/.editorconfig +0 -17
  8. package/.postcssrc.json +0 -1
  9. package/.prettierrc +0 -12
  10. package/.rush/temp/chunked-rush-logs/xt-plugin-editor.build.chunks.jsonl +0 -23
  11. package/.rush/temp/chunked-rush-logs/xt-plugin-editor.test.chunks.jsonl +0 -50
  12. package/.rush/temp/shrinkwrap-deps.json +0 -1200
  13. package/CHANGELOG.md +0 -2
  14. package/angular.json +0 -148
  15. package/projects/editor/README.md +0 -13
  16. package/projects/editor/ng-package.json +0 -7
  17. package/projects/editor/package.json +0 -43
  18. package/projects/editor/src/lib/editor/editor.component.css +0 -15
  19. package/projects/editor/src/lib/editor/editor.component.html +0 -29
  20. package/projects/editor/src/lib/editor/editor.component.spec.ts +0 -53
  21. package/projects/editor/src/lib/editor/editor.component.ts +0 -202
  22. package/projects/editor/src/lib/markdown/inline-markdown-pipe.spec.ts +0 -25
  23. package/projects/editor/src/lib/markdown/inline-markdown-pipe.ts +0 -30
  24. package/projects/editor/src/lib/markdown/markdown-pipe.spec.ts +0 -29
  25. package/projects/editor/src/lib/markdown/markdown-pipe.ts +0 -21
  26. package/projects/editor/src/lib/prose-mirror/basic-setup.ts +0 -655
  27. package/projects/editor/src/lib/register.ts +0 -33
  28. package/projects/editor/src/public-api.ts +0 -7
  29. package/projects/editor/tsconfig.lib.json +0 -13
  30. package/projects/editor/tsconfig.lib.prod.json +0 -11
  31. package/projects/editor/tsconfig.spec.json +0 -10
  32. package/projects/editor-plugin/federation.config.js +0 -33
  33. package/projects/editor-plugin/public/favicon.ico +0 -0
  34. package/projects/editor-plugin/src/app/app.component.css +0 -0
  35. package/projects/editor-plugin/src/app/app.component.html +0 -3
  36. package/projects/editor-plugin/src/app/app.component.spec.ts +0 -34
  37. package/projects/editor-plugin/src/app/app.component.ts +0 -23
  38. package/projects/editor-plugin/src/app/app.config.ts +0 -22
  39. package/projects/editor-plugin/src/app/app.routes.ts +0 -6
  40. package/projects/editor-plugin/src/app/editor-test-component/editor-test.component.css +0 -4
  41. package/projects/editor-plugin/src/app/editor-test-component/editor-test.component.html +0 -19
  42. package/projects/editor-plugin/src/app/editor-test-component/editor-test.component.spec.ts +0 -33
  43. package/projects/editor-plugin/src/app/editor-test-component/editor-test.component.ts +0 -67
  44. package/projects/editor-plugin/src/bootstrap.ts +0 -6
  45. package/projects/editor-plugin/src/index.html +0 -13
  46. package/projects/editor-plugin/src/main.ts +0 -6
  47. package/projects/editor-plugin/src/styles.css +0 -14
  48. package/projects/editor-plugin/tsconfig.app.json +0 -11
  49. package/projects/editor-plugin/tsconfig.federation.json +0 -13
  50. package/projects/editor-plugin/tsconfig.spec.json +0 -10
  51. package/rush-logs/xt-plugin-editor.build.error.log +0 -8
  52. package/rush-logs/xt-plugin-editor.build.log +0 -23
  53. package/rush-logs/xt-plugin-editor.test.error.log +0 -1
  54. package/rush-logs/xt-plugin-editor.test.log +0 -50
  55. package/tsconfig.json +0 -33
@@ -1,655 +0,0 @@
1
-
2
-
3
-
4
- /// Given a blockquote node type, returns an input rule that turns `"> "`
5
- /// at the start of a textblock into a blockquote.
6
-
7
- import {
8
- wrapItem, blockTypeItem, Dropdown, DropdownSubmenu, joinUpItem, liftItem,
9
- selectParentNodeItem, undoItem, redoItem, icons, MenuItem, MenuElement, MenuItemSpec, menuBar
10
- } from 'prosemirror-menu';
11
- import {NodeSelection, EditorState, Command} from "prosemirror-state"
12
- import {Schema, NodeType, MarkType} from "prosemirror-model"
13
-
14
- import {Attrs} from "prosemirror-model"
15
-
16
- const prefix = "ProseMirror-prompt"
17
-
18
- import {
19
- wrapIn, setBlockType, chainCommands, toggleMark, exitCode,
20
- joinUp, joinDown, lift, selectParentNode, baseKeymap
21
- } from 'prosemirror-commands';
22
- import {wrapInList, splitListItem, liftListItem, sinkListItem} from "prosemirror-schema-list"
23
- import { undo, redo, history } from 'prosemirror-history';
24
- import {
25
- ellipsis, emDash,
26
- inputRules,
27
- smartQuotes,
28
- textblockTypeInputRule,
29
- undoInputRule,
30
- wrappingInputRule
31
- } from 'prosemirror-inputrules';
32
- import { keymap } from 'prosemirror-keymap';
33
- import { dropCursor } from 'prosemirror-dropcursor';
34
- import { gapCursor } from 'prosemirror-gapcursor';
35
-
36
- const mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false
37
-
38
- /// Inspect the given schema looking for marks and nodes from the
39
- /// basic schema, and if found, add key bindings related to them.
40
- /// This will add:
41
- ///
42
- /// * **Mod-b** for toggling [strong](#schema-basic.StrongMark)
43
- /// * **Mod-i** for toggling [emphasis](#schema-basic.EmMark)
44
- /// * **Mod-`** for toggling [code font](#schema-basic.CodeMark)
45
- /// * **Ctrl-Shift-0** for making the current textblock a paragraph
46
- /// * **Ctrl-Shift-1** to **Ctrl-Shift-Digit6** for making the current
47
- /// textblock a heading of the corresponding level
48
- /// * **Ctrl-Shift-Backslash** to make the current textblock a code block
49
- /// * **Ctrl-Shift-8** to wrap the selection in an ordered list
50
- /// * **Ctrl-Shift-9** to wrap the selection in a bullet list
51
- /// * **Ctrl->** to wrap the selection in a block quote
52
- /// * **Enter** to split a non-empty textblock in a list item while at
53
- /// the same time splitting the list item
54
- /// * **Mod-Enter** to insert a hard break
55
- /// * **Mod-_** to insert a horizontal rule
56
- /// * **Backspace** to undo an input rule
57
- /// * **Alt-ArrowUp** to `joinUp`
58
- /// * **Alt-ArrowDown** to `joinDown`
59
- /// * **Mod-BracketLeft** to `lift`
60
- /// * **Escape** to `selectParentNode`
61
- ///
62
- /// You can suppress or map these bindings by passing a `mapKeys`
63
- /// argument, which maps key names (say `"Mod-B"` to either `false`, to
64
- /// remove the binding, or a new key name string.
65
- export function buildKeymap(schema: Schema, mapKeys?: {[key: string]: false | string}) {
66
- let keys: {[key: string]: Command} = {}, type
67
- function bind(key: string, cmd: Command) {
68
- if (mapKeys) {
69
- let mapped = mapKeys[key]
70
- if (mapped === false) return
71
- if (mapped) key = mapped
72
- }
73
- keys[key] = cmd
74
- }
75
-
76
- bind("Mod-z", undo)
77
- bind("Shift-Mod-z", redo)
78
- bind("Backspace", undoInputRule)
79
- if (!mac) bind("Mod-y", redo)
80
-
81
- bind("Alt-ArrowUp", joinUp)
82
- bind("Alt-ArrowDown", joinDown)
83
- bind("Mod-BracketLeft", lift)
84
- bind("Escape", selectParentNode)
85
-
86
- if (type = schema.marks["strong"]) {
87
- bind("Mod-b", toggleMark(type))
88
- bind("Mod-B", toggleMark(type))
89
- }
90
- if (type = schema.marks["em"]) {
91
- bind("Mod-i", toggleMark(type))
92
- bind("Mod-I", toggleMark(type))
93
- }
94
- if (type = schema.marks["code"])
95
- bind("Mod-`", toggleMark(type))
96
-
97
- if (type = schema.nodes["bullet_list"])
98
- bind("Shift-Ctrl-8", wrapInList(type))
99
- if (type = schema.nodes["ordered_list"])
100
- bind("Shift-Ctrl-9", wrapInList(type))
101
- if (type = schema.nodes["blockquote"])
102
- bind("Ctrl->", wrapIn(type))
103
- if (type = schema.nodes["hard_break"]) {
104
- let br = type as any, cmd = chainCommands(exitCode, (state, dispatch) => {
105
- if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView())
106
- return true
107
- })
108
- bind("Mod-Enter", cmd)
109
- bind("Shift-Enter", cmd)
110
- if (mac) bind("Ctrl-Enter", cmd)
111
- }
112
- if (type = schema.nodes["list_item"]) {
113
- bind("Enter", splitListItem(type))
114
- bind("Mod-[", liftListItem(type))
115
- bind("Mod-]", sinkListItem(type))
116
- }
117
- if (type = schema.nodes["paragraph"])
118
- bind("Shift-Ctrl-0", setBlockType(type))
119
- if (type = schema.nodes["code_block"])
120
- bind("Shift-Ctrl-\\", setBlockType(type))
121
- if (type = schema.nodes["heading"])
122
- for (let i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, setBlockType(type, {level: i}))
123
- if (type = schema.nodes["horizontal_rule"]) {
124
- let hr = type as any
125
- bind("Mod-_", (state, dispatch) => {
126
- if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView())
127
- return true
128
- })
129
- }
130
-
131
- return keys
132
- }
133
-
134
-
135
- export function openPrompt(options: {
136
- title: string,
137
- fields: {[name: string]: Field},
138
- callback: (attrs: Attrs) => void
139
- }) {
140
- let wrapper = document.body.appendChild(document.createElement("div"))
141
- wrapper.className = prefix
142
-
143
- let mouseOutside = (e: MouseEvent) => { if (!wrapper.contains(e.target as HTMLElement)) close() }
144
- setTimeout(() => window.addEventListener("mousedown", mouseOutside), 50)
145
- let close = () => {
146
- window.removeEventListener("mousedown", mouseOutside)
147
- if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper)
148
- }
149
-
150
- let domFields: HTMLElement[] = []
151
- for (let name in options.fields) domFields.push(options.fields[name].render())
152
-
153
- let submitButton = document.createElement("button")
154
- submitButton.type = "submit"
155
- submitButton.className = prefix + "-submit"
156
- submitButton.textContent = "OK"
157
- let cancelButton = document.createElement("button")
158
- cancelButton.type = "button"
159
- cancelButton.className = prefix + "-cancel"
160
- cancelButton.textContent = "Cancel"
161
- cancelButton.addEventListener("click", close)
162
-
163
- let form = wrapper.appendChild(document.createElement("form"))
164
- if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title
165
- domFields.forEach(field => {
166
- form.appendChild(document.createElement("div")).appendChild(field)
167
- })
168
- let buttons = form.appendChild(document.createElement("div"))
169
- buttons.className = prefix + "-buttons"
170
- buttons.appendChild(submitButton)
171
- buttons.appendChild(document.createTextNode(" "))
172
- buttons.appendChild(cancelButton)
173
-
174
- let box = wrapper.getBoundingClientRect()
175
- wrapper.style.top = ((window.innerHeight - box.height) / 2) + "px"
176
- wrapper.style.left = ((window.innerWidth - box.width) / 2) + "px"
177
-
178
- let submit = () => {
179
- let params = getValues(options.fields, domFields)
180
- if (params) {
181
- close()
182
- options.callback(params)
183
- }
184
- }
185
-
186
- form.addEventListener("submit", e => {
187
- e.preventDefault()
188
- submit()
189
- })
190
-
191
- form.addEventListener("keydown", e => {
192
- if (e.keyCode == 27) {
193
- e.preventDefault()
194
- close()
195
- } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) {
196
- e.preventDefault()
197
- submit()
198
- } else if (e.keyCode == 9) {
199
- window.setTimeout(() => {
200
- if (!wrapper.contains(document.activeElement)) close()
201
- }, 500)
202
- }
203
- })
204
-
205
- let input = form.elements[0] as HTMLElement
206
- if (input) input.focus()
207
- }
208
-
209
- function getValues(fields: {[name: string]: Field}, domFields: readonly HTMLElement[]) {
210
- let result = Object.create(null), i = 0
211
- for (let name in fields) {
212
- let field = fields[name], dom = domFields[i++]
213
- let value = field.read(dom), bad = field.validate(value)
214
- if (bad) {
215
- reportInvalid(dom, bad)
216
- return null
217
- }
218
- result[name] = field.clean(value)
219
- }
220
- return result
221
- }
222
-
223
- function reportInvalid(dom: HTMLElement, message: string) {
224
- // FIXME this is awful and needs a lot more work
225
- let parent = dom.parentNode!
226
- let msg = parent.appendChild(document.createElement("div"))
227
- msg.style.left = (dom.offsetLeft + dom.offsetWidth + 2) + "px"
228
- msg.style.top = (dom.offsetTop - 5) + "px"
229
- msg.className = "ProseMirror-invalid"
230
- msg.textContent = message
231
- setTimeout(() => parent.removeChild(msg), 1500)
232
- }
233
-
234
- /// The type of field that `openPrompt` expects to be passed to it.
235
- export abstract class Field {
236
- /// Create a field with the given options. Options support by all
237
- /// field types are:
238
- constructor(
239
- /// @internal
240
- readonly options: {
241
- /// The starting value for the field.
242
- value?: any
243
-
244
- /// The label for the field.
245
- label: string
246
-
247
- /// Whether the field is required.
248
- required?: boolean
249
-
250
- /// A function to validate the given value. Should return an
251
- /// error message if it is not valid.
252
- validate?: (value: any) => string | null
253
-
254
- /// A cleanup function for field values.
255
- clean?: (value: any) => any
256
- }
257
- ) {}
258
-
259
- /// Render the field to the DOM. Should be implemented by all subclasses.
260
- abstract render(): HTMLElement
261
-
262
- /// Read the field's value from its DOM node.
263
- read(dom: HTMLElement) { return (dom as any).value }
264
-
265
- /// A field-type-specific validation function.
266
- validateType(value: any): string | null { return null }
267
-
268
- /// @internal
269
- validate(value: any): string | null {
270
- if (!value && this.options.required)
271
- return "Required field"
272
- return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null)
273
- }
274
-
275
- clean(value: any): any {
276
- return this.options.clean ? this.options.clean(value) : value
277
- }
278
- }
279
-
280
- /// A field class for single-line text fields.
281
- export class TextField extends Field {
282
- render() {
283
- let input = document.createElement("input")
284
- input.type = "text"
285
- input.placeholder = this.options.label
286
- input.value = this.options.value || ""
287
- input.autocomplete = "off"
288
- return input
289
- }
290
- }
291
-
292
-
293
- /// A field class for dropdown fields based on a plain `<select>`
294
- /// tag. Expects an option `options`, which should be an array of
295
- /// `{value: string, label: string}` objects, or a function taking a
296
- /// `ProseMirror` instance and returning such an array.
297
- export class SelectField extends Field {
298
- render() {
299
- let select = document.createElement("select")
300
- ;((this.options as any).options as {value: string, label: string}[]).forEach(o => {
301
- let opt = select.appendChild(document.createElement("option"))
302
- opt.value = o.value
303
- opt.selected = o.value == this.options.value
304
- opt.label = o.label
305
- })
306
- return select
307
- }
308
- }
309
-
310
- // Helpers to create specific types of items
311
-
312
- export function canInsert(state: EditorState, nodeType: NodeType) {
313
- let $from = state.selection.$from
314
- for (let d = $from.depth; d >= 0; d--) {
315
- let index = $from.index(d)
316
- if ($from.node(d).canReplaceWith(index, index, nodeType)) return true
317
- }
318
- return false
319
- }
320
-
321
- function insertImageItem(nodeType: NodeType) {
322
- return new MenuItem({
323
- title: "Insert image",
324
- label: "Image",
325
- enable(state) { return canInsert(state, nodeType) },
326
- run(state, _, view) {
327
- let {from, to} = state.selection, attrs = null
328
- if (state.selection instanceof NodeSelection && state.selection.node.type == nodeType)
329
- attrs = state.selection.node.attrs
330
- openPrompt({
331
- title: "Insert image",
332
- fields: {
333
- src: new TextField({label: "Location", required: true, value: attrs && attrs["src"]}),
334
- title: new TextField({label: "Title", value: attrs && attrs["title"]}),
335
- alt: new TextField({label: "Description",
336
- value: attrs ? attrs["alt"] : state.doc.textBetween(from, to, " ")})
337
- },
338
- callback(attrs) {
339
- view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs)!))
340
- view.focus()
341
- }
342
- })
343
- }
344
- })
345
- }
346
-
347
- function cmdItem(cmd: Command, options: Partial<MenuItemSpec>) {
348
- let passedOptions: MenuItemSpec = {
349
- label: options.title as string | undefined,
350
- run: cmd
351
- }
352
- for (let prop in options) (passedOptions as any)[prop] = (options as any)[prop]
353
- if (!options.enable && !options.select)
354
- passedOptions[options.enable ? "enable" : "select"] = state => cmd(state)
355
-
356
- return new MenuItem(passedOptions)
357
- }
358
-
359
- export function markActive(state: EditorState, type: MarkType) {
360
- let {from, $from, to, empty} = state.selection
361
- if (empty) return !!type.isInSet(state.storedMarks || $from.marks())
362
- else return state.doc.rangeHasMark(from, to, type)
363
- }
364
-
365
- function markItem(markType: MarkType, options: Partial<MenuItemSpec>) {
366
- let passedOptions: Partial<MenuItemSpec> = {
367
- active(state) { return markActive(state, markType) }
368
- }
369
- for (let prop in options) (passedOptions as any)[prop] = (options as any)[prop]
370
- return cmdItem(toggleMark(markType), passedOptions)
371
- }
372
-
373
- function linkItem(markType: MarkType) {
374
- return new MenuItem({
375
- title: "Add or remove link",
376
- icon: icons["link"],
377
- active(state) { return markActive(state, markType) },
378
- enable(state) { return !state.selection.empty },
379
- run(state, dispatch, view) {
380
- if (markActive(state, markType)) {
381
- toggleMark(markType)(state, dispatch)
382
- return true
383
- }
384
- openPrompt({
385
- title: "Create a link",
386
- fields: {
387
- href: new TextField({
388
- label: "Link target",
389
- required: true
390
- }),
391
- title: new TextField({label: "Title"})
392
- },
393
- callback(attrs) {
394
- toggleMark(markType, attrs)(view.state, view.dispatch)
395
- view.focus()
396
- }
397
- })
398
- return true
399
- }
400
- })
401
- }
402
-
403
- function wrapListItem(nodeType: NodeType, options: Partial<MenuItemSpec>) {
404
- return cmdItem(wrapInList(nodeType, (options as any).attrs), options)
405
- }
406
-
407
- type MenuItemResult = {
408
- /// A menu item to toggle the [strong mark](#schema-basic.StrongMark).
409
- toggleStrong?: MenuElement
410
-
411
- /// A menu item to toggle the [emphasis mark](#schema-basic.EmMark).
412
- toggleEm?: MenuElement
413
-
414
- /// A menu item to toggle the [code font mark](#schema-basic.CodeMark).
415
- toggleCode?: MenuElement
416
-
417
- /// A menu item to toggle the [link mark](#schema-basic.LinkMark).
418
- toggleLink?: MenuElement
419
-
420
- /// A menu item to insert an [image](#schema-basic.Image).
421
- insertImage?: MenuElement
422
-
423
- /// A menu item to wrap the selection in a [bullet list](#schema-list.BulletList).
424
- wrapBulletList?: MenuElement
425
-
426
- /// A menu item to wrap the selection in an [ordered list](#schema-list.OrderedList).
427
- wrapOrderedList?: MenuElement
428
-
429
- /// A menu item to wrap the selection in a [block quote](#schema-basic.BlockQuote).
430
- wrapBlockQuote?: MenuElement
431
-
432
- /// A menu item to set the current textblock to be a normal
433
- /// [paragraph](#schema-basic.Paragraph).
434
- makeParagraph?: MenuElement
435
-
436
- /// A menu item to set the current textblock to be a
437
- /// [code block](#schema-basic.CodeBlock).
438
- makeCodeBlock?: MenuElement
439
-
440
- /// Menu items to set the current textblock to be a
441
- /// [heading](#schema-basic.Heading) of level _N_.
442
- makeHead1?: MenuElement
443
- makeHead2?: MenuElement
444
- makeHead3?: MenuElement
445
- makeHead4?: MenuElement
446
- makeHead5?: MenuElement
447
- makeHead6?: MenuElement
448
-
449
- /// A menu item to insert a horizontal rule.
450
- insertHorizontalRule?: MenuElement
451
-
452
- /// A dropdown containing the `insertImage` and
453
- /// `insertHorizontalRule` items.
454
- insertMenu: Dropdown
455
-
456
- /// A dropdown containing the items for making the current
457
- /// textblock a paragraph, code block, or heading.
458
- typeMenu: Dropdown
459
-
460
- /// Array of block-related menu items.
461
- blockMenu: MenuElement[][]
462
-
463
- /// Inline-markup related menu items.
464
- inlineMenu: MenuElement[][]
465
-
466
- /// An array of arrays of menu elements for use as the full menu
467
- /// for, for example the [menu
468
- /// bar](https://code.haverbeke.berlin/prosemirror/prosemirror-menu).
469
- fullMenu: MenuElement[][]
470
- }
471
-
472
- /// Given a schema, look for default mark and node types in it and
473
- /// return an object with relevant menu items relating to those marks.
474
- export function buildMenuItems(schema: Schema, override?:{[itemName:string]:MenuElement}): MenuItemResult {
475
- let r: MenuItemResult = {} as any
476
- let mark: MarkType | undefined;
477
- override=override||{};
478
- if (mark = schema.marks["strong"])
479
- r.toggleStrong = override["strong"]||markItem(mark, {title: "Toggle strong style", icon: icons["strong"]})
480
- if (mark = schema.marks["em"])
481
- r.toggleEm = override["em"]|| markItem(mark, {title: "Toggle emphasis", icon: icons["em"]})
482
- if (mark = schema.marks["code"])
483
- r.toggleCode = override["code"]||markItem(mark, {title: "Toggle code font", icon: icons["code"]})
484
- if (mark = schema.marks["link"])
485
- r.toggleLink = override["link"]||linkItem(mark)
486
-
487
- let node: NodeType | undefined
488
- if (node = schema.nodes["image"])
489
- r.insertImage = override["image"]||insertImageItem(node)
490
- if (node = schema.nodes["bullet_list"])
491
- r.wrapBulletList = override["bullet_list"]||wrapListItem(node, {
492
- title: "Wrap in bullet list",
493
- icon: icons["bulletList"]
494
- })
495
- if (node = schema.nodes["ordered_list"])
496
- r.wrapOrderedList = override["ordered_list"]||wrapListItem(node, {
497
- title: "Wrap in ordered list",
498
- icon: icons["orderedList"]
499
- })
500
- if (node = schema.nodes["blockquote"])
501
- r.wrapBlockQuote = override["blockquote"]||wrapItem(node, {
502
- title: "Wrap in block quote",
503
- icon: icons["blockquote"]
504
- })
505
- if (node = schema.nodes["paragraph"])
506
- r.makeParagraph = override["paragraph"]||blockTypeItem(node, {
507
- title: "Change to paragraph",
508
- label: "Plain"
509
- })
510
- if (node = schema.nodes["code_block"])
511
- r.makeCodeBlock = override["code_block"]||blockTypeItem(node, {
512
- title: "Change to code block",
513
- label: "Code"
514
- })
515
- if (node = schema.nodes["heading"])
516
- for (let i = 1; i <= 10; i++)
517
- (r as any)["makeHead" + i] = override["makeHead"+i]||blockTypeItem(node, {
518
- title: "Change to heading " + i,
519
- label: "Level " + i,
520
- attrs: {level: i}
521
- })
522
- if (node = schema.nodes["horizontal_rule"]) {
523
- let hr = node
524
- r.insertHorizontalRule = override["horizontal_rule"]||new MenuItem({
525
- title: "Insert horizontal rule",
526
- label: "Horizontal rule",
527
- enable(state) { return canInsert(state, hr) },
528
- run(state, dispatch) { dispatch(state.tr.replaceSelectionWith(hr.create())) }
529
- })
530
- }
531
-
532
- let cut = <T>(arr: T[]) => arr.filter(x => x) as NonNullable<T>[]
533
- r.insertMenu = new Dropdown(cut([r.insertImage, r.insertHorizontalRule]), {label: "Insert"})
534
- r.typeMenu = new Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new DropdownSubmenu(cut([
535
- r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6
536
- ]), {label: "Heading"})]), {label: "Type..."})
537
-
538
- r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])]
539
- r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, joinUpItem,
540
- liftItem, selectParentNodeItem])]
541
- r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[undoItem, redoItem]], r.blockMenu)
542
-
543
- return r
544
- }
545
-
546
- export function blockQuoteRule(nodeType: NodeType) {
547
- return wrappingInputRule(/^\s*>\s$/, nodeType)
548
- }
549
-
550
- /// Given a list node type, returns an input rule that turns a number
551
- /// followed by a dot at the start of a textblock into an ordered list.
552
- export function orderedListRule(nodeType: NodeType) {
553
- return wrappingInputRule(/^(\d+)\.\s$/, nodeType, match => ({order: +match[1]}),
554
- (match, node) => node.childCount + node.attrs["order"] == +match[1])
555
- }
556
-
557
- /// Given a list node type, returns an input rule that turns a bullet
558
- /// (dash, plush, or asterisk) at the start of a textblock into a
559
- /// bullet list.
560
- export function bulletListRule(nodeType: NodeType) {
561
- return wrappingInputRule(/^\s*([-+*])\s$/, nodeType)
562
- }
563
-
564
- /// Given a code block node type, returns an input rule that turns a
565
- /// textblock starting with three backticks into a code block.
566
- export function codeBlockRule(nodeType: NodeType) {
567
- return textblockTypeInputRule(/^```$/, nodeType)
568
- }
569
-
570
- /// Given a node type and a maximum level, creates an input rule that
571
- /// turns up to that number of `#` characters followed by a space at
572
- /// the start of a textblock into a heading whose level corresponds to
573
- /// the number of `#` signs.
574
- export function headingRule(nodeType: NodeType, maxLevel: number) {
575
- return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"),
576
- nodeType, match => ({level: match[1].length}))
577
- }
578
-
579
- /// A set of input rules for creating the basic block quotes, lists,
580
- /// code blocks, and heading.
581
- export function buildInputRules(schema: Schema) {
582
- let rules = smartQuotes.concat(ellipsis, emDash), type
583
- if (type = schema.nodes["blockquote"]) rules.push(blockQuoteRule(type))
584
- if (type = schema.nodes["ordered_list"]) rules.push(orderedListRule(type))
585
- if (type = schema.nodes["bullet_list"]) rules.push(bulletListRule(type))
586
- if (type = schema.nodes["code_block"]) rules.push(codeBlockRule(type))
587
- if (type = schema.nodes["heading"]) rules.push(headingRule(type, 6))
588
- return inputRules({rules})
589
- }
590
-
591
- /// Create an array of plugins pre-configured for the given schema.
592
- /// The resulting array will include the following plugins:
593
- ///
594
- /// * Input rules for smart quotes and creating the block types in the
595
- /// schema using markdown conventions (say `"> "` to create a
596
- /// blockquote)
597
- ///
598
- /// * A keymap that defines keys to create and manipulate the nodes in the
599
- /// schema
600
- ///
601
- /// * A keymap binding the default keys provided by the
602
- /// prosemirror-commands module
603
- ///
604
- /// * The undo history plugin
605
- ///
606
- /// * The drop cursor plugin
607
- ///
608
- /// * The gap cursor plugin
609
- ///
610
- /// * A custom plugin that adds a `menuContent` prop for the
611
- /// prosemirror-menu wrapper, and a CSS class that enables the
612
- /// additional styling defined in `style/style.css` in this package
613
- ///
614
- /// Probably only useful for quickly setting up a passable
615
- /// editor—you'll need more control over your settings in most
616
- /// real-world situations.
617
- export function basicSetup(options: {
618
- /// The schema to generate key bindings and menu items for.
619
- schema: Schema
620
-
621
- /// Can be used to [adjust](#example-setup.buildKeymap) the key bindings created.
622
- mapKeys?: {[key: string]: string | false}
623
-
624
- /// Set to false to disable the menu bar.
625
- menuBar?: boolean
626
-
627
- /// Set to false to disable the history plugin.
628
- history?: boolean
629
-
630
- /// Set to false to make the menu bar non-floating.
631
- floatingMenu?: boolean
632
-
633
- /// Can be used to override any menu content.
634
- menuContent?: { [itemName:string]:MenuElement }
635
- }) {
636
- let plugins = [
637
- buildInputRules(options.schema),
638
- keymap(buildKeymap(options.schema, options.mapKeys)),
639
- keymap(baseKeymap),
640
- dropCursor(),
641
- gapCursor()
642
- ]
643
- if (options.menuBar !== false)
644
- plugins.push(menuBar({floating: options.floatingMenu !== false,
645
- content: buildMenuItems(options.schema, options.menuContent).fullMenu}))
646
- if (options.history !== false)
647
- plugins.push(history())
648
-
649
- return plugins;/*.concat(new Plugin({
650
- props: {
651
- attributes: {class: "ProseMirror-example-setup-style"}
652
- }
653
- }))*/
654
- }
655
-
@@ -1,33 +0,0 @@
1
- import { XtResolverService } from 'xt-components';
2
- import { EditorComponent } from './editor/editor.component';
3
-
4
- export function registerEditorPlugin (resolverService:XtResolverService):string {
5
- const pluginName = "Plugin Editor";
6
- console.info ('Registering ' +pluginName);
7
- resolverService.registerPlugin ({
8
- name:pluginName,
9
- uriLogo:'pluginicon.png',
10
- cssUrls: [
11
- 'prosemirror-view/style/prosemirror.css',
12
- 'prosemirror-menu/style/menu.css',
13
- 'prosemirror-gapcursor/style/gapcursor.css'
14
- ],
15
- components: [
16
- {
17
- componentName:'Editor',
18
- componentClass:EditorComponent,
19
- typesHandled: ['markdown','rich-text','description'],
20
- }
21
- ],
22
- types: {
23
- 'markdown':'string',
24
- 'rich-text':'string',
25
- 'description':'string'
26
- }
27
- });
28
- return pluginName;
29
- }
30
-
31
- export function registerPlugin (resolverService:XtResolverService):string {
32
- return registerEditorPlugin(resolverService);
33
- }
@@ -1,7 +0,0 @@
1
- /*
2
- * Public API Surface of web plugin
3
- */
4
-
5
- export * from './lib/editor/editor.component';
6
- export * from './lib/register';
7
- export * from './lib/markdown/markdown-pipe'