@akilli/editor-src 5.1.5

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 (126) hide show
  1. package/abbreviation/Abbreviation.js +32 -0
  2. package/abbreviation/AbbreviationDialog.js +21 -0
  3. package/audio/Audio.js +47 -0
  4. package/audio/AudioDialog.js +18 -0
  5. package/audio/AudioListener.js +50 -0
  6. package/base/AlignCommand.js +34 -0
  7. package/base/AlignableListener.js +45 -0
  8. package/base/Alignment.js +36 -0
  9. package/base/BarListener.js +95 -0
  10. package/base/Base.js +127 -0
  11. package/base/Command.js +139 -0
  12. package/base/CommandManager.js +60 -0
  13. package/base/ContentFilter.js +109 -0
  14. package/base/DeletableListener.js +36 -0
  15. package/base/DeleteCommand.js +18 -0
  16. package/base/Dialog.js +153 -0
  17. package/base/DialogManager.js +44 -0
  18. package/base/Dispatcher.js +88 -0
  19. package/base/Dom.js +790 -0
  20. package/base/EditableListener.js +82 -0
  21. package/base/Editor.js +448 -0
  22. package/base/Filter.js +35 -0
  23. package/base/FilterManager.js +44 -0
  24. package/base/FocusableListener.js +22 -0
  25. package/base/FocusbarListener.js +99 -0
  26. package/base/FormCreator.js +162 -0
  27. package/base/FormatbarListener.js +32 -0
  28. package/base/Key.js +258 -0
  29. package/base/Listener.js +51 -0
  30. package/base/NavigableListener.js +81 -0
  31. package/base/Plugin.js +176 -0
  32. package/base/PluginManager.js +51 -0
  33. package/base/SlotableListener.js +40 -0
  34. package/base/SortCommand.js +30 -0
  35. package/base/SortableListener.js +135 -0
  36. package/base/Sorting.js +36 -0
  37. package/base/Tag.js +113 -0
  38. package/base/TagGroup.js +183 -0
  39. package/base/TagListener.js +34 -0
  40. package/base/TagManager.js +61 -0
  41. package/base/TagName.js +470 -0
  42. package/base/ToolbarListener.js +11 -0
  43. package/base/util.js +59 -0
  44. package/block/Block.js +51 -0
  45. package/block/BlockDialog.js +11 -0
  46. package/block/BlockElement.js +21 -0
  47. package/block/BlockListener.js +60 -0
  48. package/blockquote/Blockquote.js +43 -0
  49. package/blockquote/BlockquoteFilter.js +22 -0
  50. package/blockquote/BlockquoteListener.js +34 -0
  51. package/bold/Bold.js +30 -0
  52. package/break/Break.js +33 -0
  53. package/break/BreakFilter.js +24 -0
  54. package/build/BuildEditor.js +97 -0
  55. package/build/editor.css +548 -0
  56. package/build/editor.woff2 +0 -0
  57. package/cite/Cite.js +30 -0
  58. package/code/Code.js +30 -0
  59. package/data/Data.js +32 -0
  60. package/data/DataDialog.js +13 -0
  61. package/definition/Definition.js +32 -0
  62. package/definition/DefinitionDialog.js +13 -0
  63. package/deletion/Deletion.js +30 -0
  64. package/details/Details.js +63 -0
  65. package/details/DetailsFilter.js +17 -0
  66. package/details/DetailsListener.js +102 -0
  67. package/division/Division.js +53 -0
  68. package/division/DivisionDialog.js +13 -0
  69. package/emphasis/Emphasis.js +30 -0
  70. package/figure/Figure.js +58 -0
  71. package/figure/FigureFilter.js +14 -0
  72. package/figure/FigureListener.js +23 -0
  73. package/heading/Heading.js +38 -0
  74. package/horizontalrule/HorizontalRule.js +37 -0
  75. package/i18n/I18n.js +26 -0
  76. package/i18n/de.js +167 -0
  77. package/iframe/Iframe.js +49 -0
  78. package/iframe/IframeDialog.js +20 -0
  79. package/iframe/IframeListener.js +48 -0
  80. package/image/Image.js +47 -0
  81. package/image/ImageDialog.js +23 -0
  82. package/image/ImageListener.js +47 -0
  83. package/insertion/Insertion.js +30 -0
  84. package/italic/Italic.js +30 -0
  85. package/keyboard/Keyboard.js +30 -0
  86. package/link/Link.js +34 -0
  87. package/link/LinkDialog.js +14 -0
  88. package/link/LinkListener.js +45 -0
  89. package/list/List.js +40 -0
  90. package/list/ListListener.js +91 -0
  91. package/mark/Mark.js +30 -0
  92. package/orderedlist/OrderedList.js +39 -0
  93. package/package.json +24 -0
  94. package/paragraph/Paragraph.js +42 -0
  95. package/paragraph/ParagraphListener.js +40 -0
  96. package/preformat/Preformat.js +43 -0
  97. package/preformat/PreformatFilter.js +22 -0
  98. package/preformat/PreformatListener.js +34 -0
  99. package/quote/Quote.js +30 -0
  100. package/sample/Sample.js +30 -0
  101. package/section/Section.js +55 -0
  102. package/section/SectionDialog.js +13 -0
  103. package/small/Small.js +30 -0
  104. package/strikethrough/Strikethrough.js +30 -0
  105. package/strong/Strong.js +30 -0
  106. package/subheading/Subheading.js +38 -0
  107. package/subscript/Subscript.js +30 -0
  108. package/superscript/Superscript.js +30 -0
  109. package/table/Table.js +113 -0
  110. package/table/TableCellListener.js +125 -0
  111. package/table/TableColumnAddCommand.js +19 -0
  112. package/table/TableColumnListener.js +34 -0
  113. package/table/TableCommand.js +23 -0
  114. package/table/TableDialog.js +14 -0
  115. package/table/TableFilter.js +35 -0
  116. package/table/TableListener.js +39 -0
  117. package/table/TableRowAddCommand.js +18 -0
  118. package/table/TableRowListener.js +34 -0
  119. package/time/Time.js +32 -0
  120. package/time/TimeDialog.js +13 -0
  121. package/underline/Underline.js +30 -0
  122. package/unorderedlist/UnorderedList.js +39 -0
  123. package/variable/Variable.js +30 -0
  124. package/video/Video.js +47 -0
  125. package/video/VideoDialog.js +20 -0
  126. package/video/VideoListener.js +48 -0
@@ -0,0 +1,125 @@
1
+ import Key from '../base/Key.js';
2
+ import Listener from '../base/Listener.js';
3
+ import TagName from '../base/TagName.js';
4
+
5
+ export default class TableCellListener extends Listener {
6
+ /**
7
+ * @param {Editor} editor
8
+ */
9
+ constructor(editor) {
10
+ super(editor);
11
+ this.editor.root.addEventListener('inserttd', this);
12
+ this.editor.root.addEventListener('insertth', this);
13
+ }
14
+
15
+ /**
16
+ * @param {CustomEvent} event
17
+ * @param {HTMLTableCellElement} event.detail.element
18
+ * @return {void}
19
+ */
20
+ inserttd({ detail: { element } }) {
21
+ element.addEventListener('keydown', this);
22
+ }
23
+
24
+ /**
25
+ * @param {CustomEvent} event
26
+ * @param {HTMLTableCellElement} event.detail.element
27
+ * @return {void}
28
+ */
29
+ insertth({ detail: { element } }) {
30
+ element.addEventListener('keydown', this);
31
+ }
32
+
33
+ /**
34
+ * @param {KeyboardEvent} event
35
+ * @param {HTMLTableCellElement} event.target
36
+ * @return {void}
37
+ */
38
+ keydown(event) {
39
+ const cell = event.target;
40
+ const row = cell.parentElement;
41
+ const table = cell.closest(TagName.TABLE);
42
+
43
+ if (
44
+ cell instanceof HTMLTableCellElement &&
45
+ row instanceof HTMLTableRowElement &&
46
+ table instanceof HTMLTableElement &&
47
+ Key.isEventFor(event, [Key.ARROWLEFT, Key.ARROWRIGHT, Key.ARROWUP, Key.ARROWDOWN]) &&
48
+ this.#enabled(cell, event.key)
49
+ ) {
50
+ const cellIndex = cell.cellIndex;
51
+ const cellLength = row.cells.length;
52
+ const isFirst = cellIndex === 0;
53
+ const isLast = cellIndex === cellLength - 1;
54
+ const isFirstTableRow = row.rowIndex === 0;
55
+ const isLastTableRow = row.rowIndex === table.rows.length - 1;
56
+
57
+ event.preventDefault();
58
+ event.stopPropagation();
59
+
60
+ if (event.key === Key.ARROWLEFT && !isFirst) {
61
+ this.editor.dom.focusEnd(row.cells[cellIndex - 1]);
62
+ } else if (event.key === Key.ARROWLEFT && isFirstTableRow) {
63
+ this.editor.dom.focusEnd(table.rows[table.rows.length - 1].cells[cellLength - 1]);
64
+ } else if (event.key === Key.ARROWLEFT) {
65
+ this.editor.dom.focusEnd(table.rows[row.rowIndex - 1].cells[cellLength - 1]);
66
+ } else if (event.key === Key.ARROWRIGHT && !isLast) {
67
+ row.cells[cellIndex + 1].focus();
68
+ } else if (event.key === Key.ARROWRIGHT && isLastTableRow) {
69
+ table.rows[0].cells[0].focus();
70
+ } else if (event.key === Key.ARROWRIGHT) {
71
+ table.rows[row.rowIndex + 1].cells[0].focus();
72
+ } else if (event.key === Key.ARROWUP && isFirstTableRow) {
73
+ table.rows[table.rows.length - 1].cells[cellIndex].focus();
74
+ } else if (event.key === Key.ARROWUP) {
75
+ table.rows[row.rowIndex - 1].cells[cellIndex].focus();
76
+ } else if (event.key === Key.ARROWDOWN && isLastTableRow) {
77
+ table.rows[0].cells[cellIndex].focus();
78
+ } else if (event.key === Key.ARROWDOWN) {
79
+ table.rows[row.rowIndex + 1].cells[cellIndex].focus();
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Enables or disables navigation for table cell elements
86
+ *
87
+ * @param {HTMLTableCellElement} element
88
+ * @param {string} key
89
+ * @return {boolean}
90
+ */
91
+ #enabled(element, key) {
92
+ if ([Key.ARROWUP, Key.ARROWDOWN].includes(key)) {
93
+ return true;
94
+ }
95
+
96
+ const sel = this.editor.dom.getSelection();
97
+ const anc = sel.anchorNode instanceof HTMLElement ? sel.anchorNode : element;
98
+
99
+ if (!sel.isCollapsed) {
100
+ return false;
101
+ }
102
+
103
+ if (key === Key.ARROWLEFT) {
104
+ let first = element.firstChild;
105
+
106
+ if (first instanceof HTMLElement) {
107
+ first = first.firstChild;
108
+ }
109
+
110
+ return sel.anchorOffset === 0 && [element, first].includes(anc);
111
+ }
112
+
113
+ let last = element.lastChild;
114
+
115
+ if (element.lastChild instanceof HTMLBRElement && element.lastChild.previousSibling) {
116
+ last = element.lastChild.previousSibling;
117
+ }
118
+
119
+ if (last instanceof HTMLElement) {
120
+ last = last.lastChild;
121
+ }
122
+
123
+ return sel.anchorOffset === anc.textContent.length && [element, last].includes(anc);
124
+ }
125
+ }
@@ -0,0 +1,19 @@
1
+ import Command from '../base/Command.js';
2
+ import TagName from '../base/TagName.js';
3
+
4
+ export default class TableColumnAddCommand extends Command {
5
+ /**
6
+ * @param {Editor} editor
7
+ */
8
+ constructor(editor) {
9
+ super(editor, 'tablecolumn-add');
10
+ }
11
+
12
+ /**
13
+ * @return {void}
14
+ */
15
+ execute() {
16
+ const element = this.editor.dom.getActiveElement();
17
+ element?.localName === TagName.COL && this.editor.dom.createTableColumnAfter(element);
18
+ }
19
+ }
@@ -0,0 +1,34 @@
1
+ import Key from '../base/Key.js';
2
+ import Listener from '../base/Listener.js';
3
+
4
+ export default class TableColumnListener extends Listener {
5
+ /**
6
+ * @param {Editor} editor
7
+ */
8
+ constructor(editor) {
9
+ super(editor);
10
+ this.editor.root.addEventListener('insertcol', this);
11
+ }
12
+
13
+ /**
14
+ * @param {CustomEvent} event
15
+ * @param {HTMLTableColElement} event.detail.element
16
+ * @return {void}
17
+ */
18
+ insertcol({ detail: { element } }) {
19
+ element.addEventListener('keydown', this);
20
+ }
21
+
22
+ /**
23
+ * @param {KeyboardEvent} event
24
+ * @param {HTMLTableColElement} event.target
25
+ * @return {void}
26
+ */
27
+ keydown(event) {
28
+ if (Key.isEventFor(event, Key.ENTER)) {
29
+ this.editor.dom.createTableColumnAfter(event.target);
30
+ } else if (Key.isEventFor(event, Key.BACKSPACE)) {
31
+ this.editor.dom.delete(event.target);
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,23 @@
1
+ import Command from '../base/Command.js';
2
+ import Table from './Table.js';
3
+ import TagName from '../base/TagName.js';
4
+
5
+ export default class TableCommand extends Command {
6
+ /**
7
+ * @param {Editor} editor
8
+ */
9
+ constructor(editor) {
10
+ super(editor, Table.name, TagName.TABLE);
11
+ }
12
+
13
+ /**
14
+ * @protected
15
+ * @param {Object.<string, string>} [attributes = {}]
16
+ * @param {string} attributes.rows
17
+ * @param {string} attributes.cols
18
+ * @return {void}
19
+ */
20
+ _insert({ rows, cols } = {}) {
21
+ this.editor.dom.insert(this.editor.dom.createTable(parseInt(rows, 10) || 1, parseInt(cols, 10) || 1));
22
+ }
23
+ }
@@ -0,0 +1,14 @@
1
+ import Dialog from '../base/Dialog.js';
2
+
3
+ export default class TableDialog extends Dialog {
4
+ /**
5
+ * @protected
6
+ * @return {void}
7
+ */
8
+ _prepareForm() {
9
+ this.formCreator
10
+ .addLegend(this._('Table'))
11
+ .addNumberInput('rows', this._('Rows'), { min: '1', required: 'required', value: '1' })
12
+ .addNumberInput('cols', this._('Columns'), { min: '1', required: 'required', value: '1' });
13
+ }
14
+ }
@@ -0,0 +1,35 @@
1
+ import Filter from '../base/Filter.js';
2
+ import Table from './Table.js';
3
+ import TagName from '../base/TagName.js';
4
+
5
+ export default class TableFilter extends Filter {
6
+ /**
7
+ * @param {HTMLElement} element
8
+ * @return {void}
9
+ */
10
+ filter(element) {
11
+ if (
12
+ element instanceof HTMLElement &&
13
+ element.localName === TagName.FIGURE &&
14
+ element.classList.contains(Table.name) &&
15
+ element.querySelector(':scope > ' + TagName.TABLE) &&
16
+ !element.querySelector(':scope > ' + TagName.FIGCAPTION)
17
+ ) {
18
+ this.editor.dom.insertBefore(element.querySelector(':scope > ' + TagName.TABLE), element);
19
+ element.parentElement.removeChild(element);
20
+ } else if (
21
+ element instanceof HTMLTableElement &&
22
+ element.querySelector(`:scope > ${TagName.THEAD}, :scope > ${TagName.TFOOT}`) &&
23
+ !element.querySelector(':scope > ' + TagName.TBODY)
24
+ ) {
25
+ element.parentElement.removeChild(element);
26
+ } else if (element instanceof HTMLTableSectionElement && element.rows.length <= 0) {
27
+ element.parentElement.removeChild(element);
28
+ } else if (
29
+ element instanceof HTMLTableRowElement &&
30
+ !element.querySelector(`:scope > ${TagName.TH}:not(:empty), :scope > ${TagName.TD}:not(:empty)`)
31
+ ) {
32
+ element.parentElement.removeChild(element);
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,39 @@
1
+ import Listener from '../base/Listener.js';
2
+ import Table from './Table.js';
3
+ import TagName from '../base/TagName.js';
4
+
5
+ export default class TableListener extends Listener {
6
+ /**
7
+ * @param {Editor} editor
8
+ */
9
+ constructor(editor) {
10
+ super(editor);
11
+ this.editor.root.addEventListener('inserttable', this);
12
+ }
13
+
14
+ /**
15
+ * @param {CustomEvent} event
16
+ * @param {HTMLTableElement} event.detail.element
17
+ * @return {void}
18
+ */
19
+ inserttable({ detail: { element } }) {
20
+ this.editor.dom.wrap(element, TagName.FIGURE, { attributes: { class: Table.name } });
21
+
22
+ if (element.tBodies.length > 0 && element.tBodies[0].rows[0]) {
23
+ const tbody = element.tBodies[0];
24
+ const cols = tbody.rows[0].cells.length;
25
+
26
+ if (!element.querySelector(':scope > ' + TagName.COLGROUP)) {
27
+ this.editor.dom.insertFirstChild(this.editor.dom.createTableColumnGroup(cols), element);
28
+ }
29
+
30
+ if (!element.tHead) {
31
+ this.editor.dom.insertBefore(this.editor.dom.createTableHeader(1, cols), tbody);
32
+ }
33
+
34
+ if (!element.tFoot) {
35
+ this.editor.dom.insertLastChild(this.editor.dom.createTableFooter(1, cols), element);
36
+ }
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,18 @@
1
+ import Command from '../base/Command.js';
2
+
3
+ export default class TableRowAddCommand extends Command {
4
+ /**
5
+ * @param {Editor} editor
6
+ */
7
+ constructor(editor) {
8
+ super(editor, 'tablerow-add');
9
+ }
10
+
11
+ /**
12
+ * @return {void}
13
+ */
14
+ execute() {
15
+ const element = this.editor.dom.getActiveElement();
16
+ element instanceof HTMLTableRowElement && this.editor.dom.createTableRowAfter(element);
17
+ }
18
+ }
@@ -0,0 +1,34 @@
1
+ import Key from '../base/Key.js';
2
+ import Listener from '../base/Listener.js';
3
+
4
+ export default class TableRowListener extends Listener {
5
+ /**
6
+ * @param {Editor} editor
7
+ */
8
+ constructor(editor) {
9
+ super(editor);
10
+ this.editor.root.addEventListener('inserttr', this);
11
+ }
12
+
13
+ /**
14
+ * @param {CustomEvent} event
15
+ * @param {HTMLTableRowElement} event.detail.element
16
+ * @return {void}
17
+ */
18
+ inserttr({ detail: { element } }) {
19
+ element.addEventListener('keydown', this);
20
+ }
21
+
22
+ /**
23
+ * @param {KeyboardEvent} event
24
+ * @param {HTMLTableRowElement} event.target
25
+ * @return {void}
26
+ */
27
+ keydown(event) {
28
+ if (Key.isEventFor(event, Key.ENTER)) {
29
+ this.editor.dom.createTableRowAfter(event.target);
30
+ } else if (Key.isEventFor(event, Key.BACKSPACE)) {
31
+ this.editor.dom.delete(event.target);
32
+ }
33
+ }
34
+ }
package/time/Time.js ADDED
@@ -0,0 +1,32 @@
1
+ import Base from '../base/Base.js';
2
+ import Key from '../base/Key.js';
3
+ import Plugin from '../base/Plugin.js';
4
+ import TagGroup from '../base/TagGroup.js';
5
+ import TagName from '../base/TagName.js';
6
+ import TimeDialog from './TimeDialog.js';
7
+
8
+ export default class Time extends Plugin {
9
+ /**
10
+ * @type {string}
11
+ */
12
+ static get name() {
13
+ return 'time';
14
+ }
15
+
16
+ /**
17
+ * @type {Plugin[]}
18
+ */
19
+ static get dependencies() {
20
+ return [Base];
21
+ }
22
+
23
+ /**
24
+ * @return {void}
25
+ */
26
+ init() {
27
+ this._tag({ name: TagName.TIME, group: TagGroup.FORMAT, attributes: ['datetime'] });
28
+ this.editor.dialogs.set(new TimeDialog(this.editor, this.constructor.name));
29
+ this._command(TagName.TIME);
30
+ this._formatbar('Time', Key.T);
31
+ }
32
+ }
@@ -0,0 +1,13 @@
1
+ import Dialog from '../base/Dialog.js';
2
+
3
+ export default class TimeDialog extends Dialog {
4
+ /**
5
+ * @protected
6
+ * @return {void}
7
+ */
8
+ _prepareForm() {
9
+ this.formCreator.addLegend(this._('Data')).addTextInput('datetime', this._('Machine-readable Datetime'), {
10
+ placeholder: this._('Insert date/time or leave empty to remove it'),
11
+ });
12
+ }
13
+ }
@@ -0,0 +1,30 @@
1
+ import Base from '../base/Base.js';
2
+ import Key from '../base/Key.js';
3
+ import Plugin from '../base/Plugin.js';
4
+ import TagGroup from '../base/TagGroup.js';
5
+ import TagName from '../base/TagName.js';
6
+
7
+ export default class Underline extends Plugin {
8
+ /**
9
+ * @type {string}
10
+ */
11
+ static get name() {
12
+ return 'underline';
13
+ }
14
+
15
+ /**
16
+ * @type {Plugin[]}
17
+ */
18
+ static get dependencies() {
19
+ return [Base];
20
+ }
21
+
22
+ /**
23
+ * @return {void}
24
+ */
25
+ init() {
26
+ this._tag({ name: TagName.U, group: TagGroup.FORMAT });
27
+ this._command(TagName.U);
28
+ this._formatbar('underline', Key.U);
29
+ }
30
+ }
@@ -0,0 +1,39 @@
1
+ import Base from '../base/Base.js';
2
+ import List from '../list/List.js';
3
+ import Plugin from '../base/Plugin.js';
4
+ import TagGroup from '../base/TagGroup.js';
5
+ import TagName from '../base/TagName.js';
6
+
7
+ export default class UnorderedList extends Plugin {
8
+ /**
9
+ * @type {string}
10
+ */
11
+ static get name() {
12
+ return 'unorderedlist';
13
+ }
14
+
15
+ /**
16
+ * @type {Plugin[]}
17
+ */
18
+ static get dependencies() {
19
+ return [Base, List];
20
+ }
21
+
22
+ /**
23
+ * @return {void}
24
+ */
25
+ init() {
26
+ this._tag({
27
+ name: TagName.UL,
28
+ group: TagGroup.LIST,
29
+ children: [TagGroup.LISTITEM],
30
+ arbitrary: true,
31
+ deletable: true,
32
+ focusable: true,
33
+ navigable: true,
34
+ sortable: true,
35
+ });
36
+ this._command(TagName.UL);
37
+ this._toolbar('Unordered List');
38
+ }
39
+ }
@@ -0,0 +1,30 @@
1
+ import Base from '../base/Base.js';
2
+ import Key from '../base/Key.js';
3
+ import Plugin from '../base/Plugin.js';
4
+ import TagGroup from '../base/TagGroup.js';
5
+ import TagName from '../base/TagName.js';
6
+
7
+ export default class Variable extends Plugin {
8
+ /**
9
+ * @type {string}
10
+ */
11
+ static get name() {
12
+ return 'variable';
13
+ }
14
+
15
+ /**
16
+ * @type {Plugin[]}
17
+ */
18
+ static get dependencies() {
19
+ return [Base];
20
+ }
21
+
22
+ /**
23
+ * @return {void}
24
+ */
25
+ init() {
26
+ this._tag({ name: TagName.VAR, group: TagGroup.FORMAT });
27
+ this._command(TagName.VAR);
28
+ this._formatbar('Variable', Key.V);
29
+ }
30
+ }
package/video/Video.js ADDED
@@ -0,0 +1,47 @@
1
+ import Base from '../base/Base.js';
2
+ import Figure from '../figure/Figure.js';
3
+ import Plugin from '../base/Plugin.js';
4
+ import TagGroup from '../base/TagGroup.js';
5
+ import TagName from '../base/TagName.js';
6
+ import VideoDialog from './VideoDialog.js';
7
+ import VideoListener from './VideoListener.js';
8
+
9
+ export default class Video extends Plugin {
10
+ /**
11
+ * @type {string}
12
+ */
13
+ static get name() {
14
+ return 'video';
15
+ }
16
+
17
+ /**
18
+ * @type {Plugin[]}
19
+ */
20
+ static get dependencies() {
21
+ return [Base, Figure];
22
+ }
23
+
24
+ /**
25
+ * @type {Object.<string, any>}
26
+ */
27
+ static get config() {
28
+ return { browser: undefined };
29
+ }
30
+
31
+ /**
32
+ * @return {void}
33
+ */
34
+ init() {
35
+ this._tag({
36
+ name: TagName.VIDEO,
37
+ group: TagGroup.VIDEO,
38
+ attributes: ['controls', 'height', 'id', 'src', 'width'],
39
+ empty: true,
40
+ navigable: true,
41
+ });
42
+ new VideoListener(this.editor);
43
+ this.editor.dialogs.set(new VideoDialog(this.editor, this.constructor.name, this.editor.config.video.browser));
44
+ this._command(TagName.VIDEO);
45
+ this._toolbar('Video');
46
+ }
47
+ }
@@ -0,0 +1,20 @@
1
+ import Dialog from '../base/Dialog.js';
2
+
3
+ export default class VideoDialog extends Dialog {
4
+ /**
5
+ * @protected
6
+ * @return {void}
7
+ */
8
+ _prepareForm() {
9
+ this.formCreator
10
+ .addLegend(this._('Video'))
11
+ .addTextInput('src', this._('URL'), {
12
+ pattern: '(https?|/).+',
13
+ placeholder: this._('Insert URL to video'),
14
+ required: 'required',
15
+ })
16
+ .addNumberInput('width', this._('Width'))
17
+ .addNumberInput('height', this._('Height'))
18
+ .addTextInput('id', this._('ID'));
19
+ }
20
+ }
@@ -0,0 +1,48 @@
1
+ import Listener from '../base/Listener.js';
2
+ import TagName from '../base/TagName.js';
3
+ import Video from './Video.js';
4
+
5
+ export default class VideoListener extends Listener {
6
+ /**
7
+ * @param {Editor} editor
8
+ */
9
+ constructor(editor) {
10
+ super(editor);
11
+ this.editor.root.addEventListener('sethtml', this);
12
+ this.editor.root.addEventListener('insertvideo', this);
13
+ }
14
+
15
+ /**
16
+ * @param {CustomEvent} event
17
+ * @param {HTMLElement} event.detail.element
18
+ * @return {void}
19
+ */
20
+ sethtml({ detail: { element } }) {
21
+ Array.from(element.getElementsByTagName(TagName.VIDEO)).forEach((item) => this.#init(item));
22
+ }
23
+
24
+ /**
25
+ * @param {CustomEvent} event
26
+ * @param {HTMLVideoElement} event.detail.element
27
+ * @return {void}
28
+ */
29
+ insertvideo({ detail: { element } }) {
30
+ this.#init(element);
31
+ }
32
+
33
+ /**
34
+ * @param {HTMLVideoElement} element
35
+ * @return {void}
36
+ */
37
+ #init(element) {
38
+ const src = element.getAttribute('src');
39
+
40
+ if (!src) {
41
+ element.parentElement.removeChild(element);
42
+ } else {
43
+ element.setAttribute('src', this.editor.url(src));
44
+ element.controls = true;
45
+ this.editor.dom.wrap(element, TagName.FIGURE, { attributes: { class: Video.name } });
46
+ }
47
+ }
48
+ }