@doist/typist 1.0.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.
- package/CHANGELOG.md +9 -0
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +123 -0
- package/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/components/typist-editor.d.ts +173 -0
- package/dist/components/typist-editor.d.ts.map +1 -0
- package/dist/components/typist-editor.helper.d.ts +22 -0
- package/dist/components/typist-editor.helper.d.ts.map +1 -0
- package/dist/components/typist-editor.helper.js +26 -0
- package/dist/components/typist-editor.js +160 -0
- package/dist/constants/common.d.ts +10 -0
- package/dist/constants/common.d.ts.map +1 -0
- package/dist/constants/common.js +9 -0
- package/dist/constants/extension-priorities.d.ts +26 -0
- package/dist/constants/extension-priorities.d.ts.map +1 -0
- package/dist/constants/extension-priorities.js +25 -0
- package/dist/constants/regular-expressions.d.ts +6 -0
- package/dist/constants/regular-expressions.d.ts.map +1 -0
- package/dist/constants/regular-expressions.js +5 -0
- package/dist/extensions/core/extra-editor-commands/commands/extend-word-range.d.ts +24 -0
- package/dist/extensions/core/extra-editor-commands/commands/extend-word-range.d.ts.map +1 -0
- package/dist/extensions/core/extra-editor-commands/commands/extend-word-range.js +32 -0
- package/dist/extensions/core/extra-editor-commands/commands/insert-markdown-content.d.ts +28 -0
- package/dist/extensions/core/extra-editor-commands/commands/insert-markdown-content.d.ts.map +1 -0
- package/dist/extensions/core/extra-editor-commands/commands/insert-markdown-content.js +25 -0
- package/dist/extensions/core/extra-editor-commands/extra-editor-commands.d.ts +9 -0
- package/dist/extensions/core/extra-editor-commands/extra-editor-commands.d.ts.map +1 -0
- package/dist/extensions/core/extra-editor-commands/extra-editor-commands.js +18 -0
- package/dist/extensions/core/view-event-handlers.d.ts +33 -0
- package/dist/extensions/core/view-event-handlers.d.ts.map +1 -0
- package/dist/extensions/core/view-event-handlers.js +35 -0
- package/dist/extensions/plain-text/paste-multiline-text.d.ts +10 -0
- package/dist/extensions/plain-text/paste-multiline-text.d.ts.map +1 -0
- package/dist/extensions/plain-text/paste-multiline-text.js +66 -0
- package/dist/extensions/plain-text/plain-text-document.d.ts +17 -0
- package/dist/extensions/plain-text/plain-text-document.d.ts.map +1 -0
- package/dist/extensions/plain-text/plain-text-document.js +17 -0
- package/dist/extensions/plain-text/plain-text-kit.d.ts +42 -0
- package/dist/extensions/plain-text/plain-text-kit.d.ts.map +1 -0
- package/dist/extensions/plain-text/plain-text-kit.js +47 -0
- package/dist/extensions/plain-text/plain-text-paragraph.d.ts +9 -0
- package/dist/extensions/plain-text/plain-text-paragraph.d.ts.map +1 -0
- package/dist/extensions/plain-text/plain-text-paragraph.js +13 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.d.ts +9 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.d.ts.map +1 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.js +89 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-select-wrap.d.ts +9 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-select-wrap.d.ts.map +1 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-select-wrap.js +49 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-url-pasting.d.ts +9 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-url-pasting.d.ts.map +1 -0
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-url-pasting.js +43 -0
- package/dist/extensions/plain-text/smart-markdown-typing/smart-markdown-typing.d.ts +8 -0
- package/dist/extensions/plain-text/smart-markdown-typing/smart-markdown-typing.d.ts.map +1 -0
- package/dist/extensions/plain-text/smart-markdown-typing/smart-markdown-typing.js +17 -0
- package/dist/extensions/rich-text/bold-and-italics.d.ts +8 -0
- package/dist/extensions/rich-text/bold-and-italics.d.ts.map +1 -0
- package/dist/extensions/rich-text/bold-and-italics.js +40 -0
- package/dist/extensions/rich-text/curvenote-codemark.d.ts +11 -0
- package/dist/extensions/rich-text/curvenote-codemark.d.ts.map +1 -0
- package/dist/extensions/rich-text/curvenote-codemark.js +18 -0
- package/dist/extensions/rich-text/paste-emojis.d.ts +9 -0
- package/dist/extensions/rich-text/paste-emojis.d.ts.map +1 -0
- package/dist/extensions/rich-text/paste-emojis.js +28 -0
- package/dist/extensions/rich-text/paste-markdown.d.ts +11 -0
- package/dist/extensions/rich-text/paste-markdown.d.ts.map +1 -0
- package/dist/extensions/rich-text/paste-markdown.js +68 -0
- package/dist/extensions/rich-text/rich-text-document.d.ts +17 -0
- package/dist/extensions/rich-text/rich-text-document.d.ts.map +1 -0
- package/dist/extensions/rich-text/rich-text-document.js +17 -0
- package/dist/extensions/rich-text/rich-text-image.d.ts +80 -0
- package/dist/extensions/rich-text/rich-text-image.d.ts.map +1 -0
- package/dist/extensions/rich-text/rich-text-image.js +109 -0
- package/dist/extensions/rich-text/rich-text-kit.d.ts +129 -0
- package/dist/extensions/rich-text/rich-text-kit.d.ts.map +1 -0
- package/dist/extensions/rich-text/rich-text-kit.js +130 -0
- package/dist/extensions/rich-text/rich-text-link.d.ts +10 -0
- package/dist/extensions/rich-text/rich-text-link.d.ts.map +1 -0
- package/dist/extensions/rich-text/rich-text-link.js +102 -0
- package/dist/extensions/shared/copy-markdown-source.d.ts +20 -0
- package/dist/extensions/shared/copy-markdown-source.d.ts.map +1 -0
- package/dist/extensions/shared/copy-markdown-source.js +35 -0
- package/dist/extensions/shared/paste-singleline-text.d.ts +10 -0
- package/dist/extensions/shared/paste-singleline-text.d.ts.map +1 -0
- package/dist/extensions/shared/paste-singleline-text.js +43 -0
- package/dist/factories/create-suggestion-extension.d.ts +121 -0
- package/dist/factories/create-suggestion-extension.d.ts.map +1 -0
- package/dist/factories/create-suggestion-extension.js +149 -0
- package/dist/helpers/dom.d.ts +8 -0
- package/dist/helpers/dom.d.ts.map +1 -0
- package/dist/helpers/dom.js +9 -0
- package/dist/helpers/schema.d.ts +19 -0
- package/dist/helpers/schema.d.ts.map +1 -0
- package/dist/helpers/schema.js +21 -0
- package/dist/helpers/serializer.d.ts +11 -0
- package/dist/helpers/serializer.d.ts.map +1 -0
- package/dist/helpers/serializer.js +16 -0
- package/dist/hooks/use-editor.d.ts +19 -0
- package/dist/hooks/use-editor.d.ts.map +1 -0
- package/dist/hooks/use-editor.js +46 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/serializers/html/extensions/checkbox.d.ts +8 -0
- package/dist/serializers/html/extensions/checkbox.d.ts.map +1 -0
- package/dist/serializers/html/extensions/checkbox.js +12 -0
- package/dist/serializers/html/extensions/code.d.ts +9 -0
- package/dist/serializers/html/extensions/code.d.ts.map +1 -0
- package/dist/serializers/html/extensions/code.js +20 -0
- package/dist/serializers/html/extensions/html.d.ts +10 -0
- package/dist/serializers/html/extensions/html.d.ts.map +1 -0
- package/dist/serializers/html/extensions/html.js +15 -0
- package/dist/serializers/html/extensions/link.d.ts +11 -0
- package/dist/serializers/html/extensions/link.d.ts.map +1 -0
- package/dist/serializers/html/extensions/link.js +28 -0
- package/dist/serializers/html/extensions/paragraph.d.ts +12 -0
- package/dist/serializers/html/extensions/paragraph.d.ts.map +1 -0
- package/dist/serializers/html/extensions/paragraph.js +51 -0
- package/dist/serializers/html/extensions/task-list.d.ts +9 -0
- package/dist/serializers/html/extensions/task-list.d.ts.map +1 -0
- package/dist/serializers/html/extensions/task-list.js +31 -0
- package/dist/serializers/html/html.d.ts +27 -0
- package/dist/serializers/html/html.d.ts.map +1 -0
- package/dist/serializers/html/html.js +129 -0
- package/dist/serializers/markdown/markdown.d.ts +40 -0
- package/dist/serializers/markdown/markdown.d.ts.map +1 -0
- package/dist/serializers/markdown/markdown.js +126 -0
- package/dist/serializers/markdown/plugins/image.d.ts +12 -0
- package/dist/serializers/markdown/plugins/image.d.ts.map +1 -0
- package/dist/serializers/markdown/plugins/image.js +31 -0
- package/dist/serializers/markdown/plugins/list-item.d.ts +14 -0
- package/dist/serializers/markdown/plugins/list-item.d.ts.map +1 -0
- package/dist/serializers/markdown/plugins/list-item.js +41 -0
- package/dist/serializers/markdown/plugins/paragraph.d.ts +12 -0
- package/dist/serializers/markdown/plugins/paragraph.d.ts.map +1 -0
- package/dist/serializers/markdown/plugins/paragraph.js +18 -0
- package/dist/serializers/markdown/plugins/strikethrough.d.ts +13 -0
- package/dist/serializers/markdown/plugins/strikethrough.d.ts.map +1 -0
- package/dist/serializers/markdown/plugins/strikethrough.js +23 -0
- package/dist/serializers/markdown/plugins/suggestion.d.ts +11 -0
- package/dist/serializers/markdown/plugins/suggestion.d.ts.map +1 -0
- package/dist/serializers/markdown/plugins/suggestion.js +21 -0
- package/dist/serializers/markdown/plugins/task-item.d.ts +14 -0
- package/dist/serializers/markdown/plugins/task-item.d.ts.map +1 -0
- package/dist/serializers/markdown/plugins/task-item.js +39 -0
- package/package.json +146 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Document } from '@tiptap/extension-document';
|
|
2
|
+
/**
|
|
3
|
+
* Custom extension that extends the built-in `Document` extension to define a schema for multiline
|
|
4
|
+
* or singleline rich-text documents (as opposed to the multiple block nodes by default).
|
|
5
|
+
*/
|
|
6
|
+
const RichTextDocument = Document.extend({
|
|
7
|
+
addOptions() {
|
|
8
|
+
return {
|
|
9
|
+
multiline: true,
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
content() {
|
|
13
|
+
// ref: https://tiptap.dev/api/schema#content
|
|
14
|
+
return `block${this.options.multiline ? '+' : ''}`;
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
export { RichTextDocument };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { NodeViewProps } from '@tiptap/react';
|
|
3
|
+
/**
|
|
4
|
+
* The properties that describe `RichTextImage` node attributes.
|
|
5
|
+
*/
|
|
6
|
+
declare type RichTextImageAttributes = {
|
|
7
|
+
/**
|
|
8
|
+
* Additional metadata about an image attachment upload.
|
|
9
|
+
*/
|
|
10
|
+
metadata?: {
|
|
11
|
+
/**
|
|
12
|
+
* A unique ID for the image attachment.
|
|
13
|
+
*/
|
|
14
|
+
attachmentId: string;
|
|
15
|
+
/**
|
|
16
|
+
* Specifies if the image attachment failed to upload.
|
|
17
|
+
*/
|
|
18
|
+
isUploadFailed: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The upload progress for the image attachment.
|
|
21
|
+
*/
|
|
22
|
+
uploadProgress: number;
|
|
23
|
+
};
|
|
24
|
+
} & Pick<HTMLImageElement, 'src'> & Pick<Partial<HTMLImageElement>, 'alt' | 'title'>;
|
|
25
|
+
/**
|
|
26
|
+
* Augment the official `@tiptap/core` module with extra commands, relevant for this extension, so
|
|
27
|
+
* that the compiler knows about them.
|
|
28
|
+
*/
|
|
29
|
+
declare module '@tiptap/core' {
|
|
30
|
+
interface Commands<ReturnType> {
|
|
31
|
+
richTextImage: {
|
|
32
|
+
/**
|
|
33
|
+
* Inserts an image into the editor with the given attributes.
|
|
34
|
+
*/
|
|
35
|
+
insertImage: (attributes: RichTextImageAttributes) => ReturnType;
|
|
36
|
+
/**
|
|
37
|
+
* Updates the attributes for an existing image in the editor.
|
|
38
|
+
*/
|
|
39
|
+
updateImage: (attributes: Partial<RichTextImageAttributes> & Required<Pick<RichTextImageAttributes, 'metadata'>>) => ReturnType;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The options available to customize the `RichTextImage` extension.
|
|
45
|
+
*/
|
|
46
|
+
declare type RichTextImageOptions = {
|
|
47
|
+
/**
|
|
48
|
+
* A list of accepted MIME types for images pasting.
|
|
49
|
+
*/
|
|
50
|
+
acceptedImageMimeTypes: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Renders the image node inline (e.g., <p><img src="spacer.gif"></p>). By default images are on
|
|
53
|
+
* the same level as paragraphs.
|
|
54
|
+
*/
|
|
55
|
+
inline: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Custom HTML attributes that should be added to the rendered HTML tag.
|
|
58
|
+
*/
|
|
59
|
+
HTMLAttributes: Record<string, string>;
|
|
60
|
+
/**
|
|
61
|
+
* A React component to render inside the interactive node view.
|
|
62
|
+
*/
|
|
63
|
+
NodeViewComponent?: React.ComponentType<NodeViewProps>;
|
|
64
|
+
/**
|
|
65
|
+
* The event handler that is fired when an image file is pasted.
|
|
66
|
+
*/
|
|
67
|
+
onImageFilePaste?: (file: File) => void;
|
|
68
|
+
/**
|
|
69
|
+
* The event handler that should be fired when an image node is deleted.
|
|
70
|
+
*/
|
|
71
|
+
onImageNodeDelete?: (attachmentId: string) => void;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Custom extension that extends the built-in `Image` extension to add support for image pasting,
|
|
75
|
+
* and also adds the ability to pass aditional metadata about an image attachment upload.
|
|
76
|
+
*/
|
|
77
|
+
declare const RichTextImage: import("@tiptap/react").Node<RichTextImageOptions, any>;
|
|
78
|
+
export { RichTextImage };
|
|
79
|
+
export type { RichTextImageAttributes, RichTextImageOptions };
|
|
80
|
+
//# sourceMappingURL=rich-text-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich-text-image.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-image.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD;;GAEG;AACH,aAAK,uBAAuB,GAAG;IAC3B;;OAEG;IACH,QAAQ,CAAC,EAAE;QACP;;WAEG;QACH,YAAY,EAAE,MAAM,CAAA;QAEpB;;WAEG;QACH,cAAc,EAAE,OAAO,CAAA;QAEvB;;WAEG;QACH,cAAc,EAAE,MAAM,CAAA;KACzB,CAAA;CACJ,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,GAC7B,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;AAEpD;;;GAGG;AACH,OAAO,QAAQ,cAAc,CAAC;IAC1B,UAAU,QAAQ,CAAC,UAAU;QACzB,aAAa,EAAE;YACX;;eAEG;YACH,WAAW,EAAE,CAAC,UAAU,EAAE,uBAAuB,KAAK,UAAU,CAAA;YAEhE;;eAEG;YACH,WAAW,EAAE,CACT,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAC,KACtD,UAAU,CAAA;SAClB,CAAA;KACJ;CACJ;AAED;;GAEG;AACH,aAAK,oBAAoB,GAAG;IACxB;;OAEG;IACH,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAEhC;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEtC;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAA;IAEtD;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAEvC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;CACrD,CAAA;AAED;;;GAGG;AACH,QAAA,MAAM,aAAa,yDAoHjB,CAAA;AAEF,OAAO,EAAE,aAAa,EAAE,CAAA;AAExB,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,CAAA"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Image } from '@tiptap/extension-image';
|
|
2
|
+
import { ReactNodeViewRenderer } from '@tiptap/react';
|
|
3
|
+
import { Plugin, PluginKey, Selection } from 'prosemirror-state';
|
|
4
|
+
/**
|
|
5
|
+
* Custom extension that extends the built-in `Image` extension to add support for image pasting,
|
|
6
|
+
* and also adds the ability to pass aditional metadata about an image attachment upload.
|
|
7
|
+
*/
|
|
8
|
+
const RichTextImage = Image.extend({
|
|
9
|
+
draggable: true,
|
|
10
|
+
addOptions() {
|
|
11
|
+
return {
|
|
12
|
+
...this.parent?.(),
|
|
13
|
+
acceptedImageMimeTypes: ['image/gif', 'image/jpeg', 'image/jpg', 'image/png'],
|
|
14
|
+
NodeViewComponent: undefined,
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
addAttributes() {
|
|
18
|
+
return {
|
|
19
|
+
...this.parent?.(),
|
|
20
|
+
metadata: {
|
|
21
|
+
default: undefined,
|
|
22
|
+
rendered: false,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
addCommands() {
|
|
27
|
+
const { name: nodeTypeName } = this;
|
|
28
|
+
return {
|
|
29
|
+
...this.parent?.(),
|
|
30
|
+
insertImage(attributes) {
|
|
31
|
+
return ({ editor, commands }) => {
|
|
32
|
+
const selectionAtEnd = Selection.atEnd(editor.state.doc);
|
|
33
|
+
return commands.insertContent([
|
|
34
|
+
{
|
|
35
|
+
type: nodeTypeName,
|
|
36
|
+
attrs: attributes,
|
|
37
|
+
},
|
|
38
|
+
// Insert a blank paragraph after the image when at the end of the document
|
|
39
|
+
...(editor.state.selection.to === selectionAtEnd.to
|
|
40
|
+
? [{ type: 'paragraph' }]
|
|
41
|
+
: []),
|
|
42
|
+
]);
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
updateImage(attributes) {
|
|
46
|
+
return ({ commands }) => {
|
|
47
|
+
return commands.command(({ tr }) => {
|
|
48
|
+
tr.doc.descendants((node, position) => {
|
|
49
|
+
const { metadata } = node.attrs;
|
|
50
|
+
// Update the image attributes to the corresponding node
|
|
51
|
+
if (node.type.name === nodeTypeName &&
|
|
52
|
+
metadata?.attachmentId === attributes.metadata?.attachmentId) {
|
|
53
|
+
tr.setNodeMarkup(position, node.type, {
|
|
54
|
+
...node.attrs,
|
|
55
|
+
...attributes,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return true;
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
addNodeView() {
|
|
66
|
+
const { NodeViewComponent } = this.options;
|
|
67
|
+
// Do not add a node view if component was not specified
|
|
68
|
+
if (!NodeViewComponent) {
|
|
69
|
+
return () => ({});
|
|
70
|
+
}
|
|
71
|
+
// Render the node view with the provided React component
|
|
72
|
+
return ReactNodeViewRenderer(NodeViewComponent, {
|
|
73
|
+
as: 'div',
|
|
74
|
+
className: `Typist-${this.type.name}`,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
addProseMirrorPlugins() {
|
|
78
|
+
const { acceptedImageMimeTypes, onImageFilePaste } = this.options;
|
|
79
|
+
return [
|
|
80
|
+
new Plugin({
|
|
81
|
+
key: new PluginKey(this.name),
|
|
82
|
+
props: {
|
|
83
|
+
handlePaste(_, event) {
|
|
84
|
+
// Do not handle the event if we don't have a callback
|
|
85
|
+
if (!onImageFilePaste) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const pastedFiles = Array.from(event.clipboardData?.files || []);
|
|
89
|
+
// Do not handle the event if no files were pasted
|
|
90
|
+
if (pastedFiles.length === 0) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
let wasPasteHandled = false;
|
|
94
|
+
// Invoke the callback for every pasted file that is an accepted image type
|
|
95
|
+
pastedFiles.forEach((pastedFile) => {
|
|
96
|
+
if (acceptedImageMimeTypes.includes(pastedFile.type)) {
|
|
97
|
+
onImageFilePaste(pastedFile);
|
|
98
|
+
wasPasteHandled = true;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
// Suppress the default handling behaviour if at least one image was handled
|
|
102
|
+
return wasPasteHandled;
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
];
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
export { RichTextImage };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import type { BlockquoteOptions } from '@tiptap/extension-blockquote';
|
|
3
|
+
import type { BoldOptions } from '@tiptap/extension-bold';
|
|
4
|
+
import type { BulletListOptions } from '@tiptap/extension-bullet-list';
|
|
5
|
+
import type { CodeOptions } from '@tiptap/extension-code';
|
|
6
|
+
import type { CodeBlockOptions } from '@tiptap/extension-code-block';
|
|
7
|
+
import type { DropcursorOptions } from '@tiptap/extension-dropcursor';
|
|
8
|
+
import type { HardBreakOptions } from '@tiptap/extension-hard-break';
|
|
9
|
+
import type { HeadingOptions } from '@tiptap/extension-heading';
|
|
10
|
+
import type { HistoryOptions } from '@tiptap/extension-history';
|
|
11
|
+
import type { HorizontalRuleOptions } from '@tiptap/extension-horizontal-rule';
|
|
12
|
+
import type { ItalicOptions } from '@tiptap/extension-italic';
|
|
13
|
+
import type { ListItemOptions } from '@tiptap/extension-list-item';
|
|
14
|
+
import type { OrderedListOptions } from '@tiptap/extension-ordered-list';
|
|
15
|
+
import type { ParagraphOptions } from '@tiptap/extension-paragraph';
|
|
16
|
+
import type { StrikeOptions } from '@tiptap/extension-strike';
|
|
17
|
+
import type { RichTextDocumentOptions } from './rich-text-document';
|
|
18
|
+
import type { RichTextImageOptions } from './rich-text-image';
|
|
19
|
+
import type { RichTextLinkOptions } from './rich-text-link';
|
|
20
|
+
/**
|
|
21
|
+
* The options available to customize the `RichTextKit` extension.
|
|
22
|
+
*/
|
|
23
|
+
declare type RichTextKitOptions = {
|
|
24
|
+
/**
|
|
25
|
+
* Set options for the `Blockquote` extension, or `false` to disable.
|
|
26
|
+
*/
|
|
27
|
+
blockquote: Partial<BlockquoteOptions> | false;
|
|
28
|
+
/**
|
|
29
|
+
* Set options for the `Bold` extension, or `false` to disable.
|
|
30
|
+
*/
|
|
31
|
+
bold: Partial<BoldOptions> | false;
|
|
32
|
+
/**
|
|
33
|
+
* Set options for the `BulletList` extension, or `false` to disable.
|
|
34
|
+
*/
|
|
35
|
+
bulletList: Partial<BulletListOptions> | false;
|
|
36
|
+
/**
|
|
37
|
+
* Set options for the `Code` extension, or `false` to disable.
|
|
38
|
+
*/
|
|
39
|
+
code: Partial<CodeOptions> | false;
|
|
40
|
+
/**
|
|
41
|
+
* Set options for the `CodeBlock` extension, or `false` to disable.
|
|
42
|
+
*/
|
|
43
|
+
codeBlock: Partial<CodeBlockOptions> | false;
|
|
44
|
+
/**
|
|
45
|
+
* Set options for the `Document` extension, or `false` to disable.
|
|
46
|
+
*/
|
|
47
|
+
document: Partial<RichTextDocumentOptions> | false;
|
|
48
|
+
/**
|
|
49
|
+
* Set options for the `Dropcursor` extension, or `false` to disable.
|
|
50
|
+
*/
|
|
51
|
+
dropCursor: Partial<DropcursorOptions> | false;
|
|
52
|
+
/**
|
|
53
|
+
* Set to `false` to disable the `Gapcursor` extension.
|
|
54
|
+
*/
|
|
55
|
+
gapCursor: false;
|
|
56
|
+
/**
|
|
57
|
+
* Set options for the `HardBreak` extension, or `false` to disable.
|
|
58
|
+
*/
|
|
59
|
+
hardBreak: Partial<HardBreakOptions> | false;
|
|
60
|
+
/**
|
|
61
|
+
* Set options for the `Heading` extension, or `false` to disable.
|
|
62
|
+
*/
|
|
63
|
+
heading: Partial<HeadingOptions> | false;
|
|
64
|
+
/**
|
|
65
|
+
* Set options for the `History` extension, or `false` to disable.
|
|
66
|
+
*/
|
|
67
|
+
history: Partial<HistoryOptions> | false;
|
|
68
|
+
/**
|
|
69
|
+
* Set options for the `HorizontalRule` extension, or `false` to disable.
|
|
70
|
+
*/
|
|
71
|
+
horizontalRule: Partial<HorizontalRuleOptions> | false;
|
|
72
|
+
/**
|
|
73
|
+
* Set options for the `Image` extension, or `false` to disable.
|
|
74
|
+
*/
|
|
75
|
+
image: Partial<RichTextImageOptions> | false;
|
|
76
|
+
/**
|
|
77
|
+
* Set options for the `Italic` extension, or `false` to disable.
|
|
78
|
+
*/
|
|
79
|
+
italic: Partial<ItalicOptions> | false;
|
|
80
|
+
/**
|
|
81
|
+
* Set options for the `Link` extension, or `false` to disable.
|
|
82
|
+
*/
|
|
83
|
+
link: Partial<RichTextLinkOptions> | false;
|
|
84
|
+
/**
|
|
85
|
+
* Set options for the `ListItem` extension, or `false` to disable.
|
|
86
|
+
*/
|
|
87
|
+
listItem: Partial<ListItemOptions> | false;
|
|
88
|
+
/**
|
|
89
|
+
* Set options for the `OrderedList` extension, or `false` to disable.
|
|
90
|
+
*/
|
|
91
|
+
orderedList: Partial<OrderedListOptions> | false;
|
|
92
|
+
/**
|
|
93
|
+
* Set options for the `Paragraph` extension, or `false` to disable.
|
|
94
|
+
*/
|
|
95
|
+
paragraph: Partial<ParagraphOptions> | false;
|
|
96
|
+
/**
|
|
97
|
+
* Set to `false` to disable the `PasteEmojis` extension.
|
|
98
|
+
*/
|
|
99
|
+
pasteEmojis: false;
|
|
100
|
+
/**
|
|
101
|
+
* Set to `false` to disable the `PasteMarkdown` extension.
|
|
102
|
+
*/
|
|
103
|
+
pasteMarkdown: false;
|
|
104
|
+
/**
|
|
105
|
+
* Set to `false` to disable the `PasteSinglelineText` extension.
|
|
106
|
+
*/
|
|
107
|
+
pasteSinglelineText: false;
|
|
108
|
+
/**
|
|
109
|
+
* Set options for the `Strike` extension, or `false` to disable.
|
|
110
|
+
*/
|
|
111
|
+
strike: Partial<StrikeOptions> | false;
|
|
112
|
+
/**
|
|
113
|
+
* Set to `false` to disable the `Text` extension.
|
|
114
|
+
*/
|
|
115
|
+
text: false;
|
|
116
|
+
/**
|
|
117
|
+
* Set to `false` to disable the `Typography` extension.
|
|
118
|
+
*/
|
|
119
|
+
typography: false;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* The `RichTextKit` extension is a collection of the minimal required extensions to have a full
|
|
123
|
+
* WYSIWYG text editor working. This extension is based on the official `StarterKit` extension
|
|
124
|
+
* implementation, allowing almost every extension to be customized or disabled.
|
|
125
|
+
*/
|
|
126
|
+
declare const RichTextKit: Extension<RichTextKitOptions, any>;
|
|
127
|
+
export { RichTextKit };
|
|
128
|
+
export type { RichTextKitOptions };
|
|
129
|
+
//# sourceMappingURL=rich-text-kit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich-text-kit.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-kit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import { Blockquote } from '@tiptap/extension-blockquote';
|
|
3
|
+
import { Bold } from '@tiptap/extension-bold';
|
|
4
|
+
import { BulletList } from '@tiptap/extension-bullet-list';
|
|
5
|
+
import { Code } from '@tiptap/extension-code';
|
|
6
|
+
import { CodeBlock } from '@tiptap/extension-code-block';
|
|
7
|
+
import { Dropcursor } from '@tiptap/extension-dropcursor';
|
|
8
|
+
import { Gapcursor } from '@tiptap/extension-gapcursor';
|
|
9
|
+
import { HardBreak } from '@tiptap/extension-hard-break';
|
|
10
|
+
import { Heading } from '@tiptap/extension-heading';
|
|
11
|
+
import { History } from '@tiptap/extension-history';
|
|
12
|
+
import { HorizontalRule } from '@tiptap/extension-horizontal-rule';
|
|
13
|
+
import { Italic } from '@tiptap/extension-italic';
|
|
14
|
+
import { ListItem } from '@tiptap/extension-list-item';
|
|
15
|
+
import { OrderedList } from '@tiptap/extension-ordered-list';
|
|
16
|
+
import { Paragraph } from '@tiptap/extension-paragraph';
|
|
17
|
+
import { Strike } from '@tiptap/extension-strike';
|
|
18
|
+
import { Text } from '@tiptap/extension-text';
|
|
19
|
+
import { Typography } from '@tiptap/extension-typography';
|
|
20
|
+
import { BLOCKQUOTE_EXTENSION_PRIORITY } from '../../constants/extension-priorities';
|
|
21
|
+
import { CopyMarkdownSource } from '../shared/copy-markdown-source';
|
|
22
|
+
import { PasteSinglelineText } from '../shared/paste-singleline-text';
|
|
23
|
+
import { BoldAndItalics } from './bold-and-italics';
|
|
24
|
+
import { CurvenoteCodemark } from './curvenote-codemark';
|
|
25
|
+
import { PasteEmojis } from './paste-emojis';
|
|
26
|
+
import { PasteMarkdown } from './paste-markdown';
|
|
27
|
+
import { RichTextDocument } from './rich-text-document';
|
|
28
|
+
import { RichTextImage } from './rich-text-image';
|
|
29
|
+
import { RichTextLink } from './rich-text-link';
|
|
30
|
+
/**
|
|
31
|
+
* The `RichTextKit` extension is a collection of the minimal required extensions to have a full
|
|
32
|
+
* WYSIWYG text editor working. This extension is based on the official `StarterKit` extension
|
|
33
|
+
* implementation, allowing almost every extension to be customized or disabled.
|
|
34
|
+
*/
|
|
35
|
+
const RichTextKit = Extension.create({
|
|
36
|
+
name: 'richTextKit',
|
|
37
|
+
addExtensions() {
|
|
38
|
+
const extensions = [];
|
|
39
|
+
if (this.options.blockquote !== false) {
|
|
40
|
+
extensions.push(Blockquote.extend({
|
|
41
|
+
priority: BLOCKQUOTE_EXTENSION_PRIORITY,
|
|
42
|
+
}).configure(this.options?.blockquote));
|
|
43
|
+
}
|
|
44
|
+
if (this.options.bold !== false) {
|
|
45
|
+
extensions.push(Bold.configure(this.options?.bold));
|
|
46
|
+
}
|
|
47
|
+
if (this.options.bulletList !== false) {
|
|
48
|
+
extensions.push(BulletList.configure(this.options?.bulletList));
|
|
49
|
+
}
|
|
50
|
+
if (this.options.code !== false) {
|
|
51
|
+
extensions.push(Code.configure(this.options?.code),
|
|
52
|
+
// Enhances the Code extension capabilities with additional features
|
|
53
|
+
CurvenoteCodemark);
|
|
54
|
+
}
|
|
55
|
+
if (this.options.codeBlock !== false) {
|
|
56
|
+
extensions.push(CodeBlock.configure(this.options?.codeBlock));
|
|
57
|
+
}
|
|
58
|
+
if (this.options.document !== false) {
|
|
59
|
+
extensions.push(RichTextDocument.configure(this.options?.document),
|
|
60
|
+
// Supports copying the underlying Markdown source to the clipboard
|
|
61
|
+
CopyMarkdownSource.configure({
|
|
62
|
+
keyboardShortcut: 'Mod-Shift-c',
|
|
63
|
+
}));
|
|
64
|
+
if (this.options?.pasteEmojis !== false) {
|
|
65
|
+
// Supports pasting HTML image emojis as unicode characters
|
|
66
|
+
extensions.push(PasteEmojis);
|
|
67
|
+
}
|
|
68
|
+
if (this.options?.pasteMarkdown !== false) {
|
|
69
|
+
// Supports pasting Markdown content as HTML into the editor
|
|
70
|
+
extensions.push(PasteMarkdown);
|
|
71
|
+
}
|
|
72
|
+
if (this.options?.document?.multiline === false &&
|
|
73
|
+
this.options?.pasteSinglelineText !== false) {
|
|
74
|
+
// Supports pasting multiple lines into a singleline editor, by joining all the
|
|
75
|
+
// pasted lines together
|
|
76
|
+
extensions.push(PasteSinglelineText);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (this.options.dropCursor !== false) {
|
|
80
|
+
extensions.push(Dropcursor.configure(this.options?.dropCursor));
|
|
81
|
+
}
|
|
82
|
+
if (this.options.gapCursor !== false) {
|
|
83
|
+
extensions.push(Gapcursor);
|
|
84
|
+
}
|
|
85
|
+
if (this.options.hardBreak !== false) {
|
|
86
|
+
extensions.push(HardBreak.configure(this.options?.hardBreak));
|
|
87
|
+
}
|
|
88
|
+
if (this.options.heading !== false) {
|
|
89
|
+
extensions.push(Heading.configure(this.options?.heading));
|
|
90
|
+
}
|
|
91
|
+
if (this.options.history !== false) {
|
|
92
|
+
extensions.push(History.configure(this.options?.history));
|
|
93
|
+
}
|
|
94
|
+
if (this.options.horizontalRule !== false) {
|
|
95
|
+
extensions.push(HorizontalRule.configure(this.options?.horizontalRule));
|
|
96
|
+
}
|
|
97
|
+
if (this.options.image !== false) {
|
|
98
|
+
extensions.push(RichTextImage.configure(this.options?.image));
|
|
99
|
+
}
|
|
100
|
+
if (this.options.italic !== false) {
|
|
101
|
+
extensions.push(Italic.configure(this.options?.italic));
|
|
102
|
+
}
|
|
103
|
+
if (this.options.bold !== false && this.options.italic !== false) {
|
|
104
|
+
extensions.push(BoldAndItalics);
|
|
105
|
+
}
|
|
106
|
+
if (this.options.link !== false) {
|
|
107
|
+
extensions.push(RichTextLink.configure(this.options?.link));
|
|
108
|
+
}
|
|
109
|
+
if (this.options.listItem !== false) {
|
|
110
|
+
extensions.push(ListItem.configure(this.options?.listItem));
|
|
111
|
+
}
|
|
112
|
+
if (this.options.orderedList !== false) {
|
|
113
|
+
extensions.push(OrderedList.configure(this.options?.orderedList));
|
|
114
|
+
}
|
|
115
|
+
if (this.options.paragraph !== false) {
|
|
116
|
+
extensions.push(Paragraph.configure(this.options?.paragraph));
|
|
117
|
+
}
|
|
118
|
+
if (this.options.strike !== false) {
|
|
119
|
+
extensions.push(Strike.configure(this.options?.strike));
|
|
120
|
+
}
|
|
121
|
+
if (this.options.text !== false) {
|
|
122
|
+
extensions.push(Text);
|
|
123
|
+
}
|
|
124
|
+
if (this.options.typography !== false) {
|
|
125
|
+
extensions.push(Typography);
|
|
126
|
+
}
|
|
127
|
+
return extensions;
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
export { RichTextKit };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LinkOptions } from '@tiptap/extension-link';
|
|
2
|
+
/**
|
|
3
|
+
* Custom extension that extends the built-in `Link` extension to add additional input/paste rules
|
|
4
|
+
* for converting the Markdown link syntax (i.e. `[Doist](https://doist.com)`) into links, and also
|
|
5
|
+
* adds support for the `title` attribute.
|
|
6
|
+
*/
|
|
7
|
+
declare const RichTextLink: import("@tiptap/core").Mark<LinkOptions, any>;
|
|
8
|
+
export { RichTextLink };
|
|
9
|
+
export type { LinkOptions as RichTextLinkOptions };
|
|
10
|
+
//# sourceMappingURL=rich-text-link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich-text-link.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-link.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AA2DzD;;;;GAIG;AACH,QAAA,MAAM,YAAY,+CA8ChB,CAAA;AAEF,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,YAAY,EAAE,WAAW,IAAI,mBAAmB,EAAE,CAAA"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { InputRule, markInputRule, markPasteRule, PasteRule } from '@tiptap/core';
|
|
2
|
+
import { Link } from '@tiptap/extension-link';
|
|
3
|
+
/**
|
|
4
|
+
* The input regex for Markdown links with title support, and multiple quotation marks (required
|
|
5
|
+
* in case the `Typography` extension is being included).
|
|
6
|
+
*
|
|
7
|
+
* @see https://stephenweiss.dev/regex-markdown-link
|
|
8
|
+
*/
|
|
9
|
+
const inputRegex = /(?:^|\s)\[([^\]]*)?\]\(([A-Za-z0-9:/. -]+)(?:["“](.+)["”])?\)$/;
|
|
10
|
+
/**
|
|
11
|
+
* The paste regex for Markdown links with title support, and multiple quotation marks (required
|
|
12
|
+
* in case the `Typography` extension is being included).
|
|
13
|
+
*
|
|
14
|
+
* @see https://stephenweiss.dev/regex-markdown-link
|
|
15
|
+
*/
|
|
16
|
+
const pasteRegex = /(?:^|\s)\[([^\]]*)?\]\(([A-Za-z0-9:/. -]+)(?:["“](.+)["”])?\)/g;
|
|
17
|
+
/**
|
|
18
|
+
* Input rule built specifically for the `Link` extension, which ignores the auto-linked URL in
|
|
19
|
+
* parentheses (e.g., `(https://doist.dev)`).
|
|
20
|
+
*
|
|
21
|
+
* @see https://github.com/ueberdosis/tiptap/discussions/1865
|
|
22
|
+
*/
|
|
23
|
+
function linkInputRule(config) {
|
|
24
|
+
const defaultMarkInputRule = markInputRule(config);
|
|
25
|
+
return new InputRule({
|
|
26
|
+
find: config.find,
|
|
27
|
+
handler: (props) => {
|
|
28
|
+
const { tr } = props.state;
|
|
29
|
+
defaultMarkInputRule.handler(props);
|
|
30
|
+
tr.setMeta('preventAutolink', true);
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Paste rule built specifically for the `Link` extension, which ignores the auto-linked URL in
|
|
36
|
+
* parentheses (e.g., `(https://doist.dev)`). This extension was inspired from the multiple
|
|
37
|
+
* implementations found in a Tiptap discussion at GitHub.
|
|
38
|
+
*
|
|
39
|
+
* @see https://github.com/ueberdosis/tiptap/discussions/1865
|
|
40
|
+
*/
|
|
41
|
+
function linkPasteRule(config) {
|
|
42
|
+
const defaultMarkInputRule = markPasteRule(config);
|
|
43
|
+
return new PasteRule({
|
|
44
|
+
find: config.find,
|
|
45
|
+
handler: (props) => {
|
|
46
|
+
const { tr } = props.state;
|
|
47
|
+
defaultMarkInputRule.handler(props);
|
|
48
|
+
tr.setMeta('preventAutolink', true);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Custom extension that extends the built-in `Link` extension to add additional input/paste rules
|
|
54
|
+
* for converting the Markdown link syntax (i.e. `[Doist](https://doist.com)`) into links, and also
|
|
55
|
+
* adds support for the `title` attribute.
|
|
56
|
+
*/
|
|
57
|
+
const RichTextLink = Link.extend({
|
|
58
|
+
inclusive: false,
|
|
59
|
+
addAttributes() {
|
|
60
|
+
return {
|
|
61
|
+
...this.parent?.(),
|
|
62
|
+
title: {
|
|
63
|
+
default: null,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
addInputRules() {
|
|
68
|
+
return [
|
|
69
|
+
linkInputRule({
|
|
70
|
+
find: inputRegex,
|
|
71
|
+
type: this.type,
|
|
72
|
+
// We need to use `pop()` to remove the last capture groups from the match to
|
|
73
|
+
// satisfy Tiptap's `markPasteRule` expectation of having the content as the last
|
|
74
|
+
// capture group in the match (this makes the attribute order important)
|
|
75
|
+
getAttributes(match) {
|
|
76
|
+
return {
|
|
77
|
+
title: match.pop()?.trim(),
|
|
78
|
+
href: match.pop()?.trim(),
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
];
|
|
83
|
+
},
|
|
84
|
+
addPasteRules() {
|
|
85
|
+
return [
|
|
86
|
+
linkPasteRule({
|
|
87
|
+
find: pasteRegex,
|
|
88
|
+
type: this.type,
|
|
89
|
+
// We need to use `pop()` to remove the last capture groups from the match to
|
|
90
|
+
// satisfy Tiptap's `markInputRule` expectation of having the content as the last
|
|
91
|
+
// capture group in the match (this makes the attribute order important)
|
|
92
|
+
getAttributes(match) {
|
|
93
|
+
return {
|
|
94
|
+
title: match.pop()?.trim(),
|
|
95
|
+
href: match.pop()?.trim(),
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
];
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
export { RichTextLink };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* The options available to customize the `CopyMarkdownSource` extension.
|
|
4
|
+
*/
|
|
5
|
+
declare type CopyMarkdownSourceOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* The keyboard shortcut to copy the editor underlying Markdown source to the system clipboard
|
|
8
|
+
* (default: `Mod-c`).
|
|
9
|
+
*/
|
|
10
|
+
keyboardShortcut: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The `CopyMarkdownSource` extension adds the ability to copy the editor underlying Markdown
|
|
14
|
+
* source, and write it to the system clipboard. This extension has full support for both the
|
|
15
|
+
* plain-text and rich-text editors, considering that it's powered by the Markdown serializer.
|
|
16
|
+
*/
|
|
17
|
+
declare const CopyMarkdownSource: Extension<CopyMarkdownSourceOptions, any>;
|
|
18
|
+
export { CopyMarkdownSource };
|
|
19
|
+
export type { CopyMarkdownSourceOptions };
|
|
20
|
+
//# sourceMappingURL=copy-markdown-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-markdown-source.d.ts","sourceRoot":"","sources":["../../../src/extensions/shared/copy-markdown-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuB,MAAM,cAAc,CAAA;AAI7D;;GAEG;AACH,aAAK,yBAAyB,GAAG;IAC7B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED;;;;GAIG;AACH,QAAA,MAAM,kBAAkB,2CAkCtB,CAAA;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B,YAAY,EAAE,yBAAyB,EAAE,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Extension, getHTMLFromFragment } from '@tiptap/core';
|
|
2
|
+
import { createMarkdownSerializer } from '../../serializers/markdown/markdown';
|
|
3
|
+
/**
|
|
4
|
+
* The `CopyMarkdownSource` extension adds the ability to copy the editor underlying Markdown
|
|
5
|
+
* source, and write it to the system clipboard. This extension has full support for both the
|
|
6
|
+
* plain-text and rich-text editors, considering that it's powered by the Markdown serializer.
|
|
7
|
+
*/
|
|
8
|
+
const CopyMarkdownSource = Extension.create({
|
|
9
|
+
name: 'copyMarkdownSource',
|
|
10
|
+
addOptions() {
|
|
11
|
+
return {
|
|
12
|
+
keyboardShortcut: 'Mod-c',
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
addKeyboardShortcuts() {
|
|
16
|
+
return {
|
|
17
|
+
[this.options.keyboardShortcut]: ({ editor }) => {
|
|
18
|
+
// Get a fragment of the editor's content based on the selection
|
|
19
|
+
const nodeSelection = editor.state.doc.cut(editor.state.selection.from, editor.state.selection.to);
|
|
20
|
+
// Serialize the selected content HTML to Markdown
|
|
21
|
+
const markdownContent = createMarkdownSerializer(editor.schema).serialize(getHTMLFromFragment(nodeSelection.content, editor.schema));
|
|
22
|
+
// Writes the selected Markdown content to the system clipboard
|
|
23
|
+
navigator?.clipboard
|
|
24
|
+
?.writeText(markdownContent)
|
|
25
|
+
// No need to handle the success of the writeText call
|
|
26
|
+
.then(() => undefined)
|
|
27
|
+
// No need to handle the failure of the writeText call
|
|
28
|
+
.catch(() => undefined);
|
|
29
|
+
// Suppress the default handling behaviour
|
|
30
|
+
return true;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
export { CopyMarkdownSource };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* The `PasteSinglelineText` extension joins all paragraphs into a single fragment when
|
|
4
|
+
* copying-and-pasting text into the editor, adding spaces as block separators. This custom
|
|
5
|
+
* extension is required for an editor configured with `multiline: false`, so that multiline
|
|
6
|
+
* clipboard text is pasted into the singleline editor correctly.
|
|
7
|
+
*/
|
|
8
|
+
declare const PasteSinglelineText: Extension<any, any>;
|
|
9
|
+
export { PasteSinglelineText };
|
|
10
|
+
//# sourceMappingURL=paste-singleline-text.d.ts.map
|