@exmg/exm-wysiwyg-editor 1.1.23 → 1.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/anchor/action.js +1 -1
- package/dist/exm-wysiwyg-editor-base.d.ts +32 -4
- package/dist/exm-wysiwyg-editor-base.js +66 -7
- package/dist/exm-wysiwyg-editor-toolbar-base.js +1 -1
- package/dist/utils/html2md.d.ts +1 -0
- package/dist/utils/html2md.js +12 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/md2html.d.ts +1 -0
- package/dist/utils/md2html.js +10 -0
- package/dist/{utils.js → utils/sleep.js} +1 -1
- package/dist/validator/exm-wysiwyg-editor-validator.d.ts +23 -0
- package/dist/validator/exm-wysiwyg-editor-validator.js +39 -0
- package/package.json +7 -3
- /package/dist/{utils.d.ts → utils/sleep.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './dialog/exm-wysiwyg-toolbar-link-dialog.js';
|
|
2
|
-
import { sleep } from '../../utils.js';
|
|
2
|
+
import { sleep } from '../../utils/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Open the dialog and wait until the close or submit button has been pressed
|
|
5
5
|
* @param url The initial url for the input
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/core';
|
|
2
|
+
import { getFormValue } from '@material/web/labs/behaviors/form-associated.js';
|
|
3
|
+
import { WysiwygEditorValidator } from './validator/exm-wysiwyg-editor-validator.js';
|
|
4
|
+
import { createValidator, getValidityAnchor } from '@material/web/labs/behaviors/constraint-validation.js';
|
|
2
5
|
import { ExmgElement } from '@exmg/lit-base';
|
|
3
6
|
import { EditorActions } from './types.js';
|
|
4
7
|
import './exm-wysiwyg-editor-toolbar.js';
|
|
5
8
|
import { WysiwygEditorToolbar } from './exm-wysiwyg-editor-toolbar.js';
|
|
9
|
+
declare const WysiwygBaseClass: import("@material/web/labs/behaviors/mixin.js").MixinReturn<import("@material/web/labs/behaviors/mixin.js").MixinReturn<(abstract new (...args: any[]) => import("@material/web/labs/behaviors/element-internals.js").WithElementInternals) & typeof ExmgElement & import("@material/web/labs/behaviors/form-associated.js").FormAssociatedConstructor, import("@material/web/labs/behaviors/form-associated.js").FormAssociated>, import("@material/web/labs/behaviors/constraint-validation.js").ConstraintValidation>;
|
|
10
|
+
type WysiwygMode = 'md' | 'html';
|
|
6
11
|
/**
|
|
7
12
|
* # Events:
|
|
8
13
|
* - change - where detail is current html value
|
|
@@ -10,13 +15,23 @@ import { WysiwygEditorToolbar } from './exm-wysiwyg-editor-toolbar.js';
|
|
|
10
15
|
* - focus - on editor focus
|
|
11
16
|
*
|
|
12
17
|
* @customElement
|
|
13
|
-
* @element exm-
|
|
18
|
+
* @element exm-wysiwyg-editor
|
|
14
19
|
* @memberof Exmg
|
|
15
20
|
* @extends ExmgElement
|
|
16
|
-
* @summary
|
|
21
|
+
* @summary Wysiwyg editor element
|
|
17
22
|
*/
|
|
18
|
-
export declare class WysiwygEditorElementBase extends
|
|
23
|
+
export declare class WysiwygEditorElementBase extends WysiwygBaseClass {
|
|
24
|
+
/**
|
|
25
|
+
* Input value. Can be either a markdown string or html. Don't forget to set the mode
|
|
26
|
+
*/
|
|
19
27
|
value: string;
|
|
28
|
+
/**
|
|
29
|
+
* The value type of the Editor. Can de either `md` for Markdown, of `html` for HTML.
|
|
30
|
+
* Internally the editor uses html, so when set to markdown, the values will be converted
|
|
31
|
+
*
|
|
32
|
+
* @default html
|
|
33
|
+
*/
|
|
34
|
+
mode: WysiwygMode;
|
|
20
35
|
label: string;
|
|
21
36
|
upload: boolean;
|
|
22
37
|
editorActions: EditorActions[];
|
|
@@ -25,10 +40,22 @@ export declare class WysiwygEditorElementBase extends ExmgElement {
|
|
|
25
40
|
supportingText: string;
|
|
26
41
|
editorElement?: HTMLDivElement;
|
|
27
42
|
toolbar?: WysiwygEditorToolbar;
|
|
43
|
+
/**
|
|
44
|
+
* The actual content used in the editor. This is always the html content of the editor
|
|
45
|
+
*/
|
|
46
|
+
content: string;
|
|
28
47
|
editor?: Editor;
|
|
48
|
+
internalTextarea?: HTMLTextAreaElement;
|
|
29
49
|
reset(): void;
|
|
50
|
+
[getFormValue](): string;
|
|
51
|
+
[createValidator](): WysiwygEditorValidator;
|
|
52
|
+
[getValidityAnchor](): HTMLTextAreaElement;
|
|
53
|
+
formResetCallback(): void;
|
|
54
|
+
formStateRestoreCallback(state: string): void;
|
|
55
|
+
focus(): void;
|
|
56
|
+
disconnectedCallback(): void;
|
|
30
57
|
protected firstUpdated(): void;
|
|
31
|
-
attributeChangedCallback(name: string, _old: string | null, value: string | null): void
|
|
58
|
+
attributeChangedCallback(name: string, _old: string | null, value: string | null): Promise<void>;
|
|
32
59
|
private createExtensionList;
|
|
33
60
|
editorSetup(): void;
|
|
34
61
|
private handleEditorUpdate;
|
|
@@ -37,3 +64,4 @@ export declare class WysiwygEditorElementBase extends ExmgElement {
|
|
|
37
64
|
private handleFocus;
|
|
38
65
|
protected render(): import("lit-html").TemplateResult<1>;
|
|
39
66
|
}
|
|
67
|
+
export {};
|
|
@@ -14,6 +14,10 @@ import Strike from '@tiptap/extension-strike';
|
|
|
14
14
|
import Underline from '@tiptap/extension-underline';
|
|
15
15
|
import Blockquote from '@tiptap/extension-blockquote';
|
|
16
16
|
import Link from '@tiptap/extension-link';
|
|
17
|
+
import { mixinElementInternals } from '@material/web/labs/behaviors/element-internals.js';
|
|
18
|
+
import { getFormValue, mixinFormAssociated } from '@material/web/labs/behaviors/form-associated.js';
|
|
19
|
+
import { WysiwygEditorValidator } from './validator/exm-wysiwyg-editor-validator.js';
|
|
20
|
+
import { createValidator, getValidityAnchor, mixinConstraintValidation, } from '@material/web/labs/behaviors/constraint-validation.js';
|
|
17
21
|
import { query, property, state } from 'lit/decorators.js';
|
|
18
22
|
import { ExmgElement } from '@exmg/lit-base';
|
|
19
23
|
import { classMap } from 'lit/directives/class-map.js';
|
|
@@ -21,6 +25,8 @@ import { EditorActions } from './types.js';
|
|
|
21
25
|
import './exm-wysiwyg-editor-toolbar.js';
|
|
22
26
|
import { linkOptions } from './actions/anchor/options.js';
|
|
23
27
|
import { defaultActionList } from './toolbarActions.js';
|
|
28
|
+
import { md2html, html2md } from './utils/index.js';
|
|
29
|
+
const WysiwygBaseClass = mixinConstraintValidation(mixinFormAssociated(mixinElementInternals(ExmgElement)));
|
|
24
30
|
/**
|
|
25
31
|
* # Events:
|
|
26
32
|
* - change - where detail is current html value
|
|
@@ -28,26 +34,62 @@ import { defaultActionList } from './toolbarActions.js';
|
|
|
28
34
|
* - focus - on editor focus
|
|
29
35
|
*
|
|
30
36
|
* @customElement
|
|
31
|
-
* @element exm-
|
|
37
|
+
* @element exm-wysiwyg-editor
|
|
32
38
|
* @memberof Exmg
|
|
33
39
|
* @extends ExmgElement
|
|
34
|
-
* @summary
|
|
40
|
+
* @summary Wysiwyg editor element
|
|
35
41
|
*/
|
|
36
|
-
export class WysiwygEditorElementBase extends
|
|
42
|
+
export class WysiwygEditorElementBase extends WysiwygBaseClass {
|
|
37
43
|
constructor() {
|
|
38
44
|
super(...arguments);
|
|
45
|
+
/**
|
|
46
|
+
* Input value. Can be either a markdown string or html. Don't forget to set the mode
|
|
47
|
+
*/
|
|
39
48
|
this.value = '';
|
|
49
|
+
/**
|
|
50
|
+
* The value type of the Editor. Can de either `md` for Markdown, of `html` for HTML.
|
|
51
|
+
* Internally the editor uses html, so when set to markdown, the values will be converted
|
|
52
|
+
*
|
|
53
|
+
* @default html
|
|
54
|
+
*/
|
|
55
|
+
this.mode = 'html';
|
|
40
56
|
this.label = '';
|
|
41
57
|
this.upload = false;
|
|
42
58
|
this.editorActions = defaultActionList;
|
|
43
59
|
this.required = false;
|
|
44
60
|
this.disabled = false;
|
|
45
61
|
this.supportingText = '';
|
|
62
|
+
/**
|
|
63
|
+
* The actual content used in the editor. This is always the html content of the editor
|
|
64
|
+
*/
|
|
65
|
+
this.content = '';
|
|
46
66
|
}
|
|
47
67
|
reset() {
|
|
48
68
|
var _a;
|
|
49
69
|
this.value = (_a = this.getAttribute('value')) !== null && _a !== void 0 ? _a : '';
|
|
50
70
|
}
|
|
71
|
+
[getFormValue]() {
|
|
72
|
+
return this.value;
|
|
73
|
+
}
|
|
74
|
+
[createValidator]() {
|
|
75
|
+
return new WysiwygEditorValidator(() => this);
|
|
76
|
+
}
|
|
77
|
+
[getValidityAnchor]() {
|
|
78
|
+
return this.internalTextarea;
|
|
79
|
+
}
|
|
80
|
+
formResetCallback() {
|
|
81
|
+
this.reset();
|
|
82
|
+
}
|
|
83
|
+
formStateRestoreCallback(state) {
|
|
84
|
+
this.value = state;
|
|
85
|
+
}
|
|
86
|
+
focus() {
|
|
87
|
+
var _a;
|
|
88
|
+
(_a = this.editor) === null || _a === void 0 ? void 0 : _a.commands.focus();
|
|
89
|
+
}
|
|
90
|
+
disconnectedCallback() {
|
|
91
|
+
this.removeEventListener('blur', this.handleBlur);
|
|
92
|
+
}
|
|
51
93
|
firstUpdated() {
|
|
52
94
|
this.editorSetup();
|
|
53
95
|
if (this.label && this.required) {
|
|
@@ -55,11 +97,17 @@ export class WysiwygEditorElementBase extends ExmgElement {
|
|
|
55
97
|
this.label += ' *';
|
|
56
98
|
}
|
|
57
99
|
}
|
|
58
|
-
attributeChangedCallback(name, _old, value) {
|
|
100
|
+
async attributeChangedCallback(name, _old, value) {
|
|
59
101
|
var _a, _b;
|
|
60
102
|
this[name] = value;
|
|
61
103
|
if (name === 'value') {
|
|
62
|
-
(
|
|
104
|
+
if (this.mode === 'md') {
|
|
105
|
+
this.content = await md2html(this.value);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.content = this.value;
|
|
109
|
+
}
|
|
110
|
+
(_a = this.editor) === null || _a === void 0 ? void 0 : _a.commands.setContent(this.content);
|
|
63
111
|
}
|
|
64
112
|
if (name === 'disabled') {
|
|
65
113
|
this.disabled = value !== null;
|
|
@@ -139,8 +187,13 @@ export class WysiwygEditorElementBase extends ExmgElement {
|
|
|
139
187
|
onFocus: this.handleFocus.bind(this),
|
|
140
188
|
});
|
|
141
189
|
}
|
|
142
|
-
handleEditorUpdate({ editor }) {
|
|
143
|
-
this.
|
|
190
|
+
async handleEditorUpdate({ editor }) {
|
|
191
|
+
if (this.mode === 'md') {
|
|
192
|
+
this.value = await html2md(editor.getHTML());
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
this.value = editor.getHTML();
|
|
196
|
+
}
|
|
144
197
|
this.fire('change', this.value);
|
|
145
198
|
}
|
|
146
199
|
handleEditorTransaction() {
|
|
@@ -181,6 +234,9 @@ export class WysiwygEditorElementBase extends ExmgElement {
|
|
|
181
234
|
__decorate([
|
|
182
235
|
property({ type: String })
|
|
183
236
|
], WysiwygEditorElementBase.prototype, "value", void 0);
|
|
237
|
+
__decorate([
|
|
238
|
+
property({ type: String })
|
|
239
|
+
], WysiwygEditorElementBase.prototype, "mode", void 0);
|
|
184
240
|
__decorate([
|
|
185
241
|
property({ type: String })
|
|
186
242
|
], WysiwygEditorElementBase.prototype, "label", void 0);
|
|
@@ -205,6 +261,9 @@ __decorate([
|
|
|
205
261
|
__decorate([
|
|
206
262
|
query('exm-wysiwyg-editor-toolbar')
|
|
207
263
|
], WysiwygEditorElementBase.prototype, "toolbar", void 0);
|
|
264
|
+
__decorate([
|
|
265
|
+
state()
|
|
266
|
+
], WysiwygEditorElementBase.prototype, "content", void 0);
|
|
208
267
|
__decorate([
|
|
209
268
|
state()
|
|
210
269
|
], WysiwygEditorElementBase.prototype, "editor", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const html2md: (html: string) => Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import TurndownService from 'turndown';
|
|
2
|
+
import { gfm } from 'turndown-plugin-gfm';
|
|
3
|
+
export const html2md = async (html) => {
|
|
4
|
+
const turndownService = new TurndownService({
|
|
5
|
+
headingStyle: 'atx',
|
|
6
|
+
bulletListMarker: '-',
|
|
7
|
+
});
|
|
8
|
+
turndownService.use(gfm);
|
|
9
|
+
const markdown = turndownService.turndown(html);
|
|
10
|
+
return await markdown;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=html2md.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const md2html: (markdown: string) => Promise<string>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=sleep.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Validator } from '@material/web/labs/behaviors/validators/validator.js';
|
|
7
|
+
export interface WysiwygEditorState {
|
|
8
|
+
/**
|
|
9
|
+
* Whether the checkbox is required.
|
|
10
|
+
*/
|
|
11
|
+
readonly required: boolean;
|
|
12
|
+
readonly value: string;
|
|
13
|
+
readonly internalElement?: HTMLInputElement;
|
|
14
|
+
}
|
|
15
|
+
export declare class WysiwygEditorValidator extends Validator<WysiwygEditorState> {
|
|
16
|
+
private inputElement?;
|
|
17
|
+
protected computeValidity(state: WysiwygEditorState): {
|
|
18
|
+
validity: ValidityState;
|
|
19
|
+
validationMessage: string;
|
|
20
|
+
};
|
|
21
|
+
protected equals(prevState: WysiwygEditorState, state: WysiwygEditorState): boolean;
|
|
22
|
+
protected copy(state: WysiwygEditorState): WysiwygEditorState;
|
|
23
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Validator } from '@material/web/labs/behaviors/validators/validator.js';
|
|
7
|
+
export class WysiwygEditorValidator extends Validator {
|
|
8
|
+
computeValidity(state) {
|
|
9
|
+
var _a;
|
|
10
|
+
if (!this.inputElement) {
|
|
11
|
+
this.inputElement = state.internalElement;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Lazily create the input element if not existing
|
|
15
|
+
*/
|
|
16
|
+
if (!this.inputElement) {
|
|
17
|
+
this.inputElement = document.createElement('input');
|
|
18
|
+
this.inputElement.type = 'text';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Set values to the input element
|
|
22
|
+
*/
|
|
23
|
+
this.inputElement.value = (_a = state.value) !== null && _a !== void 0 ? _a : '';
|
|
24
|
+
this.inputElement.required = state.required;
|
|
25
|
+
return {
|
|
26
|
+
validity: this.inputElement.validity,
|
|
27
|
+
validationMessage: this.inputElement.validationMessage,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
equals(prevState, state) {
|
|
31
|
+
return prevState.value === state.value && prevState.required === state.required;
|
|
32
|
+
}
|
|
33
|
+
copy(state) {
|
|
34
|
+
return {
|
|
35
|
+
...state,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=exm-wysiwyg-editor-validator.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exmg/exm-wysiwyg-editor",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.25",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -47,7 +47,11 @@
|
|
|
47
47
|
"@tiptap/extension-paragraph": "^2.11.7",
|
|
48
48
|
"@tiptap/extension-strike": "^2.11.7",
|
|
49
49
|
"@tiptap/extension-text": "^2.11.7",
|
|
50
|
-
"@tiptap/extension-underline": "^2.11.7"
|
|
50
|
+
"@tiptap/extension-underline": "^2.11.7",
|
|
51
|
+
"@types/turndown": "^5.0.0",
|
|
52
|
+
"marked": "^15.0.0",
|
|
53
|
+
"turndown": "^7.2.0",
|
|
54
|
+
"turndown-plugin-gfm": "^1.0.2"
|
|
51
55
|
},
|
|
52
56
|
"peerDependencies": {
|
|
53
57
|
"@exmg/lit-base": "^3.0.3",
|
|
@@ -63,5 +67,5 @@
|
|
|
63
67
|
"publishConfig": {
|
|
64
68
|
"access": "public"
|
|
65
69
|
},
|
|
66
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "e0e168ccfc3d87bcf73b42fe244bba2dd40fc926"
|
|
67
71
|
}
|
|
File without changes
|