@monolith-forensics/monolith-ui 1.9.1-dev.0 → 1.9.1-dev.10
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/DropDownMenu/components/MenuItemList.js +32 -12
- package/dist/DropDownMenu/components/StyledInnerItemContainer.js +1 -0
- package/dist/RichTextEditor/Components/BubbleMenu.d.ts +8 -8
- package/dist/RichTextEditor/Components/BubbleMenu.js +198 -93
- package/dist/RichTextEditor/Components/CodeBlockCopyButton.d.ts +9 -0
- package/dist/RichTextEditor/Components/CodeBlockCopyButton.js +45 -0
- package/dist/RichTextEditor/Components/CodeBlockFormatButton.d.ts +10 -0
- package/dist/RichTextEditor/Components/CodeBlockFormatButton.js +60 -0
- package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.d.ts +6 -0
- package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.js +21 -0
- package/dist/RichTextEditor/Components/CodeBlockNodeView.d.ts +3 -0
- package/dist/RichTextEditor/Components/CodeBlockNodeView.js +27 -0
- package/dist/RichTextEditor/Components/CodeBlockWrapButton.d.ts +10 -0
- package/dist/RichTextEditor/Components/CodeBlockWrapButton.js +17 -0
- package/dist/RichTextEditor/Components/LinkEditor.d.ts +8 -0
- package/dist/RichTextEditor/Components/LinkEditor.js +94 -0
- package/dist/RichTextEditor/Enums/Controls.d.ts +5 -1
- package/dist/RichTextEditor/Enums/Controls.js +4 -0
- package/dist/RichTextEditor/Enums/Extensions.d.ts +4 -0
- package/dist/RichTextEditor/Enums/Extensions.js +4 -0
- package/dist/RichTextEditor/Enums/HighlightColors.d.ts +9 -0
- package/dist/RichTextEditor/Enums/HighlightColors.js +10 -0
- package/dist/RichTextEditor/Enums/SlashCommands.d.ts +1 -0
- package/dist/RichTextEditor/Enums/SlashCommands.js +1 -0
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +16 -1
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +10 -2
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +158 -31
- package/dist/RichTextEditor/Plugins/ImageActionsPlugin.js +3 -73
- package/dist/RichTextEditor/Plugins/UploadImagesPlugin.js +1 -0
- package/dist/RichTextEditor/RichTextEditor.d.ts +5 -2
- package/dist/RichTextEditor/RichTextEditor.js +186 -13
- package/dist/RichTextEditor/Toolbar/Control.d.ts +6 -2
- package/dist/RichTextEditor/Toolbar/Control.js +13 -6
- package/dist/RichTextEditor/Toolbar/Controls.d.ts +2 -0
- package/dist/RichTextEditor/Toolbar/Controls.js +14 -0
- package/dist/RichTextEditor/Toolbar/ControlsGroup.js +1 -0
- package/dist/RichTextEditor/Toolbar/Toolbar.js +62 -9
- package/dist/RichTextEditor/Utils/codeBlockUtils.d.ts +20 -0
- package/dist/RichTextEditor/Utils/codeBlockUtils.js +137 -0
- package/dist/RichTextEditor/Utils/codeUtils.d.ts +3 -0
- package/dist/RichTextEditor/Utils/codeUtils.js +12 -0
- package/dist/RichTextEditor/Utils/linkUtils.d.ts +19 -0
- package/dist/RichTextEditor/Utils/linkUtils.js +57 -0
- package/package.json +8 -1
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +0 -7
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +0 -157
|
@@ -66,84 +66,14 @@ const getImageBlob = (src) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
66
66
|
}
|
|
67
67
|
return response.blob();
|
|
68
68
|
});
|
|
69
|
-
const clipboardPngType = "image/png";
|
|
70
|
-
const canWriteClipboardType = (ClipboardItemCtor, type) => {
|
|
71
|
-
if (!type)
|
|
72
|
-
return false;
|
|
73
|
-
if (typeof ClipboardItemCtor.supports === "function") {
|
|
74
|
-
return ClipboardItemCtor.supports(type);
|
|
75
|
-
}
|
|
76
|
-
return type === clipboardPngType;
|
|
77
|
-
};
|
|
78
|
-
const loadImageSource = (src) => new Promise((resolve, reject) => {
|
|
79
|
-
const image = new Image();
|
|
80
|
-
image.crossOrigin = "anonymous";
|
|
81
|
-
image.onload = () => resolve(image);
|
|
82
|
-
image.onerror = () => {
|
|
83
|
-
reject(new Error("Unable to prepare image for clipboard."));
|
|
84
|
-
};
|
|
85
|
-
image.src = src;
|
|
86
|
-
});
|
|
87
|
-
const renderImageSourceToPngBlob = (src) => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
-
const image = yield loadImageSource(src);
|
|
89
|
-
const width = image.naturalWidth || image.width;
|
|
90
|
-
const height = image.naturalHeight || image.height;
|
|
91
|
-
if (!width || !height) {
|
|
92
|
-
throw new Error("Unable to prepare image for clipboard.");
|
|
93
|
-
}
|
|
94
|
-
const canvas = document.createElement("canvas");
|
|
95
|
-
canvas.width = width;
|
|
96
|
-
canvas.height = height;
|
|
97
|
-
const context = canvas.getContext("2d");
|
|
98
|
-
if (!context) {
|
|
99
|
-
throw new Error("Unable to prepare image for clipboard.");
|
|
100
|
-
}
|
|
101
|
-
context.drawImage(image, 0, 0, width, height);
|
|
102
|
-
return new Promise((resolve, reject) => {
|
|
103
|
-
canvas.toBlob((blob) => {
|
|
104
|
-
if (blob) {
|
|
105
|
-
resolve(blob);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
reject(new Error("Unable to prepare image for clipboard."));
|
|
109
|
-
}
|
|
110
|
-
}, clipboardPngType);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
const convertBlobToClipboardPng = (blob, fallbackSrc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
115
|
-
try {
|
|
116
|
-
return yield renderImageSourceToPngBlob(objectUrl);
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
if (!fallbackSrc || fallbackSrc === objectUrl)
|
|
120
|
-
throw error;
|
|
121
|
-
return renderImageSourceToPngBlob(fallbackSrc);
|
|
122
|
-
}
|
|
123
|
-
finally {
|
|
124
|
-
URL.revokeObjectURL(objectUrl);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
const getClipboardImageBlob = (image, ClipboardItemCtor) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
|
-
const src = image.currentSrc || image.src;
|
|
129
|
-
const blob = yield getImageBlob(src);
|
|
130
|
-
const type = blob.type || "";
|
|
131
|
-
if (canWriteClipboardType(ClipboardItemCtor, type)) {
|
|
132
|
-
return { blob, type };
|
|
133
|
-
}
|
|
134
|
-
return {
|
|
135
|
-
blob: yield convertBlobToClipboardPng(blob, src),
|
|
136
|
-
type: clipboardPngType,
|
|
137
|
-
};
|
|
138
|
-
});
|
|
139
69
|
const copyImage = (image) => __awaiter(void 0, void 0, void 0, function* () {
|
|
140
70
|
var _a;
|
|
141
|
-
const ClipboardItemCtor = window
|
|
142
|
-
.ClipboardItem;
|
|
71
|
+
const ClipboardItemCtor = window.ClipboardItem;
|
|
143
72
|
if (!((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.write) || !ClipboardItemCtor) {
|
|
144
73
|
throw new Error("Image copying is not supported by this browser.");
|
|
145
74
|
}
|
|
146
|
-
const
|
|
75
|
+
const blob = yield getImageBlob(image.src);
|
|
76
|
+
const type = blob.type || "image/png";
|
|
147
77
|
yield navigator.clipboard.write([
|
|
148
78
|
new ClipboardItemCtor({
|
|
149
79
|
[type]: blob,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import "highlight.js/styles/github-dark.css";
|
|
1
2
|
import { Editor } from "@tiptap/react";
|
|
2
|
-
import { ExtensionType } from "./Extensions/getTiptapExtensions";
|
|
3
|
+
import { ExtensionPreset, ExtensionType } from "./Extensions/getTiptapExtensions";
|
|
3
4
|
import { HandleImageUrlUpload, HandleImageUpload } from "./Plugins/UploadImagesPlugin";
|
|
4
|
-
import { BubbleMenuOptions } from "./
|
|
5
|
+
import { BubbleMenuOptions } from "./Components/BubbleMenu";
|
|
5
6
|
import { ToolbarOptions } from "./Toolbar/Toolbar";
|
|
6
7
|
type RichTextEditorProps = {
|
|
7
8
|
className?: string;
|
|
8
9
|
editorInstanceRef?: React.RefObject<Editor | null>;
|
|
9
10
|
extensions?: ExtensionType[];
|
|
11
|
+
disabledExtensions?: ExtensionType[];
|
|
12
|
+
extensionPreset?: ExtensionPreset;
|
|
10
13
|
slashCommands?: any[];
|
|
11
14
|
defaultValue?: string;
|
|
12
15
|
value?: string;
|
|
@@ -8,17 +8,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { useEffect, useRef, useState } from "react";
|
|
11
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
12
12
|
import styled from "styled-components";
|
|
13
|
+
import "highlight.js/styles/github-dark.css";
|
|
13
14
|
import { EditorContent, useEditor } from "@tiptap/react";
|
|
15
|
+
import { BubbleMenu as TiptapBubbleMenu, } from "@tiptap/react/menus";
|
|
16
|
+
import { isTextSelection } from "@tiptap/core";
|
|
14
17
|
import { DOMParser as ProseMirrorDOMParser } from "@tiptap/pm/model";
|
|
18
|
+
import { TextSelection } from "@tiptap/pm/state";
|
|
15
19
|
import { Toolbar } from "./Toolbar";
|
|
16
|
-
import getTipTapExtensions from "./Extensions/getTiptapExtensions";
|
|
17
|
-
import { Extensions, SlashCommands } from "./Enums";
|
|
20
|
+
import getTipTapExtensions, { resolveExtensions, } from "./Extensions/getTiptapExtensions";
|
|
21
|
+
import { Controls, Extensions, SlashCommands } from "./Enums";
|
|
18
22
|
import { addImagePlaceholder, removeImagePlaceholder, startImageUpload, } from "./Plugins/UploadImagesPlugin";
|
|
19
23
|
import SaveBadge from "./Components/SaveBadge";
|
|
24
|
+
import BubbleMenuContent from "./Components/BubbleMenu";
|
|
20
25
|
import Fonts from "./Enums/Fonts";
|
|
21
26
|
import RichTextEditorContext from "./Contexts/RichTextEditorContext";
|
|
27
|
+
import { getLinkAttributesAtPosition, getLinkRangeAtPosition, openLink, } from "./Utils/linkUtils";
|
|
22
28
|
const getImageFilesFromClipboard = (clipboardData) => {
|
|
23
29
|
return Array.from(clipboardData.files).filter((file) => file.type.includes("image/"));
|
|
24
30
|
};
|
|
@@ -317,6 +323,78 @@ const StyledContent = styled.div `
|
|
|
317
323
|
margin: 0;
|
|
318
324
|
line-height: 1.5rem;
|
|
319
325
|
}
|
|
326
|
+
.editor-inline-code,
|
|
327
|
+
:not(pre) > code {
|
|
328
|
+
padding: 0.1rem 0.25rem;
|
|
329
|
+
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
330
|
+
border-radius: 4px;
|
|
331
|
+
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
332
|
+
color: ${({ theme }) => theme.palette.text.secondary};
|
|
333
|
+
font-family:
|
|
334
|
+
ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
335
|
+
"Liberation Mono", "Courier New", monospace;
|
|
336
|
+
font-size: 0.9em;
|
|
337
|
+
box-decoration-break: clone;
|
|
338
|
+
}
|
|
339
|
+
.editor-code-block {
|
|
340
|
+
position: relative;
|
|
341
|
+
margin: 0.5rem 0;
|
|
342
|
+
padding: 0.875rem 1rem;
|
|
343
|
+
overflow-x: auto;
|
|
344
|
+
border: 1px solid #30363d;
|
|
345
|
+
border-radius: 6px;
|
|
346
|
+
background-color: #0d1117;
|
|
347
|
+
color: #c9d1d9;
|
|
348
|
+
font-family:
|
|
349
|
+
ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
350
|
+
"Liberation Mono", "Courier New", monospace;
|
|
351
|
+
font-size: 0.85rem;
|
|
352
|
+
line-height: 1.45rem;
|
|
353
|
+
white-space: pre;
|
|
354
|
+
|
|
355
|
+
&[data-wrap="true"] {
|
|
356
|
+
white-space: pre-wrap;
|
|
357
|
+
word-break: break-word;
|
|
358
|
+
overflow-wrap: anywhere;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
code {
|
|
362
|
+
display: block;
|
|
363
|
+
min-width: max-content;
|
|
364
|
+
padding: 0;
|
|
365
|
+
border: 0;
|
|
366
|
+
background-color: transparent;
|
|
367
|
+
color: inherit;
|
|
368
|
+
font: inherit;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
&[data-wrap="true"] code {
|
|
372
|
+
min-width: 0;
|
|
373
|
+
white-space: inherit;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.editor-code-block-actions {
|
|
377
|
+
display: flex;
|
|
378
|
+
position: absolute;
|
|
379
|
+
top: 0.4rem;
|
|
380
|
+
right: 0.4rem;
|
|
381
|
+
z-index: 1;
|
|
382
|
+
gap: 0.25rem;
|
|
383
|
+
opacity: 0;
|
|
384
|
+
transition: opacity 120ms ease-in-out;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.editor-code-block-action {
|
|
388
|
+
background-color: #161b22;
|
|
389
|
+
color: #c9d1d9;
|
|
390
|
+
border-color: #30363d;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
&:hover .editor-code-block-actions,
|
|
394
|
+
&:focus-within .editor-code-block-actions {
|
|
395
|
+
opacity: 1;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
320
398
|
ul {
|
|
321
399
|
margin: 0;
|
|
322
400
|
}
|
|
@@ -330,8 +408,6 @@ const StyledContent = styled.div `
|
|
|
330
408
|
color: ${({ theme }) => theme.palette.text.primary};
|
|
331
409
|
text-decoration: underline;
|
|
332
410
|
cursor: pointer;
|
|
333
|
-
// Set title attribute
|
|
334
|
-
title: "Click to open link";
|
|
335
411
|
}
|
|
336
412
|
img {
|
|
337
413
|
max-width: 100%;
|
|
@@ -543,16 +619,96 @@ const StyledContent = styled.div `
|
|
|
543
619
|
margin: 0 0.125rem;
|
|
544
620
|
}
|
|
545
621
|
`;
|
|
546
|
-
export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = "", value, readOnly = false, font, showToolbar = true, saving = false, extensions = [], slashCommands = [], bubbleMenuOptions, toolbarOptions, autoFocus, onChange, handleImageUpload, handleImageUrlUpload, style, }) => {
|
|
622
|
+
export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = "", value, readOnly = false, font, showToolbar = true, saving = false, disabledExtensions = [], extensionPreset = "basic", extensions = [], slashCommands = [], bubbleMenuOptions, toolbarOptions, autoFocus, onChange, handleImageUpload, handleImageUrlUpload, style, }) => {
|
|
623
|
+
const resolvedExtensions = useMemo(() => resolveExtensions({
|
|
624
|
+
disabledExtensions,
|
|
625
|
+
extensionPreset,
|
|
626
|
+
extensions,
|
|
627
|
+
}), [disabledExtensions, extensionPreset, extensions]);
|
|
628
|
+
const resolvedExtensionSet = useMemo(() => new Set(resolvedExtensions), [resolvedExtensions]);
|
|
629
|
+
const resolvedSlashCommands = useMemo(() => slashCommands.filter((command) => {
|
|
630
|
+
if (command === SlashCommands.CodeBlock) {
|
|
631
|
+
return resolvedExtensionSet.has(Extensions.CodeBlock);
|
|
632
|
+
}
|
|
633
|
+
return true;
|
|
634
|
+
}), [resolvedExtensionSet, slashCommands]);
|
|
635
|
+
const resolvedToolbarOptions = useMemo(() => {
|
|
636
|
+
if (!(toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.controls))
|
|
637
|
+
return toolbarOptions;
|
|
638
|
+
const controlExtensionMap = {
|
|
639
|
+
[Controls.BOLD]: Extensions.Bold,
|
|
640
|
+
[Controls.ITALIC]: Extensions.Italic,
|
|
641
|
+
[Controls.UNDERLINE]: Extensions.Underline,
|
|
642
|
+
[Controls.STRIKE]: Extensions.Strike,
|
|
643
|
+
[Controls.CODE]: Extensions.Code,
|
|
644
|
+
[Controls.CODE_BLOCK]: Extensions.CodeBlock,
|
|
645
|
+
[Controls.BULLET_LIST]: Extensions.BulletList,
|
|
646
|
+
[Controls.ORDERED_LIST]: Extensions.OrderedList,
|
|
647
|
+
[Controls.COLOR]: Extensions.Color,
|
|
648
|
+
[Controls.HIGHLIGHT]: Extensions.Highlight,
|
|
649
|
+
[Controls.LINK]: Extensions.Link,
|
|
650
|
+
[Controls.TEXT_ALIGN_LEFT]: Extensions.TextAlign,
|
|
651
|
+
[Controls.TEXT_ALIGN_CENTER]: Extensions.TextAlign,
|
|
652
|
+
[Controls.TEXT_ALIGN_RIGHT]: Extensions.TextAlign,
|
|
653
|
+
[Controls.TEXT_ALIGN_JUSTIFIED]: Extensions.TextAlign,
|
|
654
|
+
};
|
|
655
|
+
return Object.assign(Object.assign({}, toolbarOptions), { controls: toolbarOptions.controls.filter((control) => {
|
|
656
|
+
if (typeof control !== "string")
|
|
657
|
+
return true;
|
|
658
|
+
const extension = controlExtensionMap[control];
|
|
659
|
+
return !extension || resolvedExtensionSet.has(extension);
|
|
660
|
+
}) });
|
|
661
|
+
}, [resolvedExtensionSet, toolbarOptions]);
|
|
547
662
|
const isControlled = value !== undefined;
|
|
548
|
-
const hasImageExtension =
|
|
549
|
-
const hasSlashCommandExtension =
|
|
550
|
-
const
|
|
663
|
+
const hasImageExtension = resolvedExtensionSet.has(Extensions.Image);
|
|
664
|
+
const hasSlashCommandExtension = resolvedExtensionSet.has(Extensions.SlashCommand);
|
|
665
|
+
const hasBubbleMenuExtension = resolvedExtensionSet.has(Extensions.BubbleMenu);
|
|
666
|
+
const hasImageSlashCommand = hasSlashCommandExtension &&
|
|
667
|
+
resolvedSlashCommands.includes(SlashCommands.Image);
|
|
551
668
|
const onChangeRef = useRef(onChange);
|
|
669
|
+
const bubbleMenuPortalRef = useRef(null);
|
|
552
670
|
const [fontState, setFontState] = useState(font || Fonts.DEFAULT);
|
|
553
671
|
useEffect(() => {
|
|
554
672
|
onChangeRef.current = onChange;
|
|
555
673
|
}, [onChange]);
|
|
674
|
+
const getBubbleMenuPortalRoot = useCallback(() => {
|
|
675
|
+
if (bubbleMenuPortalRef.current) {
|
|
676
|
+
return bubbleMenuPortalRef.current;
|
|
677
|
+
}
|
|
678
|
+
const portal = document.createElement("div");
|
|
679
|
+
portal.setAttribute("data-monolith-bubble-menu-portal", "");
|
|
680
|
+
document.body.appendChild(portal);
|
|
681
|
+
bubbleMenuPortalRef.current = portal;
|
|
682
|
+
return portal;
|
|
683
|
+
}, []);
|
|
684
|
+
useEffect(() => {
|
|
685
|
+
return () => {
|
|
686
|
+
var _a;
|
|
687
|
+
(_a = bubbleMenuPortalRef.current) === null || _a === void 0 ? void 0 : _a.remove();
|
|
688
|
+
bubbleMenuPortalRef.current = null;
|
|
689
|
+
};
|
|
690
|
+
}, []);
|
|
691
|
+
const shouldShowBubbleMenu = useCallback(({ editor, element, view, state, from, to }) => {
|
|
692
|
+
const { selection } = state;
|
|
693
|
+
const isChildOfMenu = element.contains(document.activeElement);
|
|
694
|
+
const hasEditorFocus = view.hasFocus() || isChildOfMenu;
|
|
695
|
+
const selectedText = state.doc.textBetween(from, to).trim();
|
|
696
|
+
const isEmptyTextBlock = !selectedText && isTextSelection(state.selection);
|
|
697
|
+
if (!hasEditorFocus ||
|
|
698
|
+
selection.empty ||
|
|
699
|
+
isEmptyTextBlock ||
|
|
700
|
+
!editor.isEditable) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
return true;
|
|
704
|
+
}, []);
|
|
705
|
+
const bubbleMenuPositionOptions = useMemo(() => ({
|
|
706
|
+
strategy: "fixed",
|
|
707
|
+
placement: "top",
|
|
708
|
+
offset: 8,
|
|
709
|
+
flip: false,
|
|
710
|
+
shift: { padding: 10 },
|
|
711
|
+
}), []);
|
|
556
712
|
if (hasImageSlashCommand && !hasImageExtension) {
|
|
557
713
|
throw new Error("Extensions.Image is required when using the Image slash command.");
|
|
558
714
|
}
|
|
@@ -566,12 +722,29 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
566
722
|
editable: !readOnly,
|
|
567
723
|
shouldRerenderOnTransaction: true,
|
|
568
724
|
extensions: getTipTapExtensions({
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
725
|
+
disabledExtensions,
|
|
726
|
+
extensions: resolvedExtensions,
|
|
727
|
+
slashCommands: resolvedSlashCommands,
|
|
572
728
|
handleImageUpload,
|
|
573
729
|
}),
|
|
574
730
|
editorProps: {
|
|
731
|
+
handleClick: (view, pos, event) => {
|
|
732
|
+
const linkRange = getLinkRangeAtPosition(view.state, pos);
|
|
733
|
+
const linkAttributes = getLinkAttributesAtPosition(view.state, pos);
|
|
734
|
+
if (!linkRange || !(linkAttributes === null || linkAttributes === void 0 ? void 0 : linkAttributes.href))
|
|
735
|
+
return false;
|
|
736
|
+
const mouseEvent = event;
|
|
737
|
+
mouseEvent.preventDefault();
|
|
738
|
+
mouseEvent.stopPropagation();
|
|
739
|
+
const shouldOpenLink = mouseEvent.metaKey || mouseEvent.ctrlKey || !view.editable;
|
|
740
|
+
if (shouldOpenLink) {
|
|
741
|
+
openLink(linkAttributes.href);
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, linkRange.from, linkRange.to)));
|
|
745
|
+
view.focus();
|
|
746
|
+
return true;
|
|
747
|
+
},
|
|
575
748
|
handlePaste: (view, event) => {
|
|
576
749
|
if (!hasImageExtension || !handleImageUpload)
|
|
577
750
|
return false;
|
|
@@ -632,5 +805,5 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
632
805
|
return (_jsx(StyledContent, { className: className, children: _jsxs(RichTextEditorContext.Provider, { value: {
|
|
633
806
|
font: fontState,
|
|
634
807
|
setFont: setFontState,
|
|
635
|
-
}, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions:
|
|
808
|
+
}, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions: resolvedToolbarOptions })), saving && _jsx(SaveBadge, {}), editor && hasBubbleMenuExtension && (_jsx(TiptapBubbleMenu, { editor: editor, pluginKey: "bubbleMenu", updateDelay: 200, appendTo: getBubbleMenuPortalRoot, shouldShow: shouldShowBubbleMenu, options: bubbleMenuPositionOptions, children: _jsx(BubbleMenuContent, { editor: editor, customMenuItems: bubbleMenuOptions === null || bubbleMenuOptions === void 0 ? void 0 : bubbleMenuOptions.customMenuItems }) })), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": fontState || null, style: style })] }) }));
|
|
636
809
|
};
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { Editor } from "@tiptap/react";
|
|
2
|
+
import { ButtonProps } from "../../Button";
|
|
2
3
|
export type ControlProps = {
|
|
3
4
|
className?: string;
|
|
4
5
|
editor: Editor | null;
|
|
5
6
|
isActive?: any;
|
|
6
|
-
operation
|
|
7
|
+
operation?: {
|
|
7
8
|
name: string;
|
|
8
9
|
attributes?: any;
|
|
9
10
|
};
|
|
11
|
+
onClick?: (editor: Editor | null) => void;
|
|
12
|
+
disabled?: boolean;
|
|
10
13
|
label: string;
|
|
11
14
|
icon: any;
|
|
15
|
+
size?: ButtonProps["size"];
|
|
12
16
|
};
|
|
13
|
-
export declare const Control: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<ControlProps, never>> & string & Omit<({ className, editor, isActive, operation, label, icon: Icon, }: ControlProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
17
|
+
export declare const Control: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<ControlProps, never>> & string & Omit<({ className, editor, isActive, operation, onClick, disabled, label, icon: Icon, size, }: ControlProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
import Labels from "./Labels";
|
|
4
|
-
|
|
4
|
+
import { Button } from "../../Button";
|
|
5
|
+
export const Control = styled(({ className, editor, isActive, operation, onClick, disabled, label, icon: Icon, size = "xs", }) => {
|
|
5
6
|
var _a;
|
|
6
7
|
const _label = Labels[label];
|
|
7
8
|
const active = (isActive === null || isActive === void 0 ? void 0 : isActive.name)
|
|
8
9
|
? (_a = editor === null || editor === void 0 ? void 0 : editor.isActive) === null || _a === void 0 ? void 0 : _a.call(editor, isActive.name, isActive.attributes)
|
|
9
10
|
: false;
|
|
10
|
-
return (_jsx(
|
|
11
|
+
return (_jsx(Button, { className: className + (active ? " active" : ""), "aria-label": _label, "data-active": active, title: _label, disabled: disabled, onClick: () => {
|
|
12
|
+
if (onClick) {
|
|
13
|
+
onClick(editor);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!operation)
|
|
17
|
+
return;
|
|
11
18
|
const focus = editor === null || editor === void 0 ? void 0 : editor.chain().focus();
|
|
12
19
|
focus[operation.name](operation.attributes).run();
|
|
13
|
-
}, children: _jsx(Icon, { size: "16px" }) }));
|
|
20
|
+
}, size: size, children: _jsx(Icon, { size: "16px" }) }));
|
|
14
21
|
}) `
|
|
15
22
|
display: flex;
|
|
16
23
|
justify-content: center;
|
|
17
24
|
align-items: center;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
|
|
26
|
+
padding: 5px;
|
|
27
|
+
|
|
21
28
|
background-color: transparent;
|
|
22
29
|
cursor: pointer;
|
|
23
30
|
color: ${({ theme }) => theme.palette.text.primary};
|
|
@@ -8,6 +8,8 @@ export declare const BoldControl: ({ editor }: ControlProps) => import("react/js
|
|
|
8
8
|
export declare const ItalicControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
9
|
export declare const UnderlineControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
10
|
export declare const StrikeThroughControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare const CodeControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare const CodeBlockControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
13
|
export declare const Heading1Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
14
|
export declare const Heading2Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
15
|
export declare const Heading3Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconH1, IconH2, IconH3, IconH4, IconList, IconListNumbers, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignJustified, IconCornerUpLeft, IconCornerUpRight, } from "@tabler/icons-react";
|
|
3
|
+
import { CodeIcon } from "lucide-react";
|
|
4
|
+
import { SquareCodeIcon } from "lucide-react";
|
|
3
5
|
import { Control } from "./Control";
|
|
6
|
+
import { hasInlineCode, toggleInlineCode } from "../Utils/codeUtils";
|
|
7
|
+
import { hasSyntaxHighlightedCodeBlock, toggleCodeBlock, } from "../Utils/codeBlockUtils";
|
|
4
8
|
export const UndoControl = ({ editor }) => {
|
|
5
9
|
return (_jsx(Control, { editor: editor, label: "undoControlLabel", operation: {
|
|
6
10
|
name: "undo",
|
|
@@ -39,6 +43,16 @@ export const StrikeThroughControl = ({ editor }) => {
|
|
|
39
43
|
name: "toggleStrike",
|
|
40
44
|
}, icon: IconStrikethrough }));
|
|
41
45
|
};
|
|
46
|
+
export const CodeControl = ({ editor }) => {
|
|
47
|
+
return (_jsx(Control, { editor: editor, label: "codeControlLabel", isActive: {
|
|
48
|
+
name: "code",
|
|
49
|
+
}, onClick: toggleInlineCode, disabled: !hasInlineCode(editor), icon: CodeIcon }));
|
|
50
|
+
};
|
|
51
|
+
export const CodeBlockControl = ({ editor }) => {
|
|
52
|
+
return (_jsx(Control, { editor: editor, label: "codeBlockControlLabel", isActive: {
|
|
53
|
+
name: "codeBlock",
|
|
54
|
+
}, onClick: toggleCodeBlock, disabled: !hasSyntaxHighlightedCodeBlock(editor), icon: SquareCodeIcon }));
|
|
55
|
+
};
|
|
42
56
|
export const Heading1Control = ({ editor }) => {
|
|
43
57
|
return (_jsx(Control, { editor: editor, label: "h1ControlLabel", isActive: {
|
|
44
58
|
name: "heading",
|
|
@@ -1,33 +1,42 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import styled, { useTheme } from "styled-components";
|
|
3
3
|
import ControlsGroup from "./ControlsGroup";
|
|
4
|
-
import { UndoControl, RedoControl, BoldControl, ItalicControl, UnderlineControl, StrikeThroughControl, Heading1Control, Heading2Control, Heading3Control, Heading4Control, BulletListControl, OrderedListControl, AlignLeftControl, AlignCenterControl, AlignRightControl, AlignJustifiedControl, } from "./Controls";
|
|
4
|
+
import { UndoControl, RedoControl, BoldControl, ItalicControl, UnderlineControl, StrikeThroughControl, CodeControl, CodeBlockControl, Heading1Control, Heading2Control, Heading3Control, Heading4Control, BulletListControl, OrderedListControl, AlignLeftControl, AlignCenterControl, AlignRightControl, AlignJustifiedControl, } from "./Controls";
|
|
5
5
|
import { Controls } from "../Enums";
|
|
6
6
|
import { DropDownMenu } from "../../DropDownMenu";
|
|
7
7
|
import Fonts from "../Enums/Fonts";
|
|
8
|
-
import { useContext } from "react";
|
|
8
|
+
import { useContext, useState } from "react";
|
|
9
9
|
import RichTextEditorContext from "../Contexts/RichTextEditorContext";
|
|
10
10
|
import { Button } from "../../Button";
|
|
11
|
+
import { Popover } from "../../Popover";
|
|
11
12
|
import TextColors from "../Enums/TextColors";
|
|
12
|
-
import
|
|
13
|
+
import HighlightColors from "../Enums/HighlightColors";
|
|
14
|
+
import LinkEditor from "../Components/LinkEditor";
|
|
15
|
+
import CodeBlockLanguageSelect from "../Components/CodeBlockLanguageSelect";
|
|
16
|
+
import CodeBlockWrapButton from "../Components/CodeBlockWrapButton";
|
|
17
|
+
import CodeBlockFormatButton from "../Components/CodeBlockFormatButton";
|
|
18
|
+
import { hasSyntaxHighlightedCodeBlock } from "../Utils/codeBlockUtils";
|
|
19
|
+
import { HighlighterIcon, LinkIcon, PaletteIcon, SquircleIcon, TypeIcon, } from "lucide-react";
|
|
13
20
|
export const Toolbar = styled(({ className, editor, toolbarOptions }) => {
|
|
14
21
|
var _a;
|
|
15
22
|
const theme = useTheme();
|
|
16
23
|
const { controls } = toolbarOptions || {};
|
|
24
|
+
const [linkPopoverOpen, setLinkPopoverOpen] = useState(false);
|
|
17
25
|
const customItems = controls === null || controls === void 0 ? void 0 : controls.filter((control) => typeof control !== "string" &&
|
|
18
26
|
(control.type === "menu" || control.type === "button"));
|
|
19
27
|
const { font, setFont } = useContext(RichTextEditorContext);
|
|
28
|
+
const showCodeBlockLanguageSelect = (editor === null || editor === void 0 ? void 0 : editor.isActive("codeBlock")) && hasSyntaxHighlightedCodeBlock(editor);
|
|
20
29
|
return (_jsxs("div", { className: className, children: [(_a = customItems === null || customItems === void 0 ? void 0 : customItems.map) === null || _a === void 0 ? void 0 : _a.call(customItems, (item, index) => {
|
|
21
30
|
var _a, _b;
|
|
22
31
|
if (item.type === "button") {
|
|
23
|
-
return (_jsx(Button, Object.assign({}, item.options, { children: (_a = item === null || item === void 0 ? void 0 : item.options) === null || _a === void 0 ? void 0 : _a.label }), index));
|
|
32
|
+
return (_jsx(Button, Object.assign({ size: "xs" }, item.options, { children: (_a = item === null || item === void 0 ? void 0 : item.options) === null || _a === void 0 ? void 0 : _a.label }), index));
|
|
24
33
|
}
|
|
25
34
|
else if (item.type === "menu") {
|
|
26
35
|
return (_jsx(DropDownMenu, Object.assign({ dropDownProps: {
|
|
27
36
|
style: {
|
|
28
37
|
width: 135,
|
|
29
38
|
},
|
|
30
|
-
} }, item.options, { children: (_b = item === null || item === void 0 ? void 0 : item.options) === null || _b === void 0 ? void 0 : _b.label }), index));
|
|
39
|
+
} }, item.options, { size: "xs", children: (_b = item === null || item === void 0 ? void 0 : item.options) === null || _b === void 0 ? void 0 : _b.label }), index));
|
|
31
40
|
}
|
|
32
41
|
}), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.FONT)) && (_jsx(DropDownMenu, { data: Object.values(Fonts).map((font) => ({
|
|
33
42
|
label: font,
|
|
@@ -35,12 +44,13 @@ export const Toolbar = styled(({ className, editor, toolbarOptions }) => {
|
|
|
35
44
|
onClick: () => {
|
|
36
45
|
setFont(font);
|
|
37
46
|
},
|
|
38
|
-
})), size: "
|
|
47
|
+
})), size: "xs", variant: "outlined", dropDownProps: {
|
|
39
48
|
style: {
|
|
40
49
|
width: 135,
|
|
41
50
|
},
|
|
42
51
|
}, buttonProps: {
|
|
43
52
|
title: "Select Font",
|
|
53
|
+
leftSection: _jsx(TypeIcon, { size: 12 }),
|
|
44
54
|
}, children: (font || Fonts.DEFAULT) })), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDO)) && _jsx(UndoControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.REDO)) && _jsx(RedoControl, { editor: editor })] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.COLOR)) && (_jsx(DropDownMenu, { data: [
|
|
45
55
|
{
|
|
46
56
|
label: "Default",
|
|
@@ -66,20 +76,63 @@ export const Toolbar = styled(({ className, editor, toolbarOptions }) => {
|
|
|
66
76
|
? theme.palette.text.primary
|
|
67
77
|
: item.value,
|
|
68
78
|
borderRadius: "3px",
|
|
69
|
-
} }), item.label] })), size: "
|
|
79
|
+
} }), item.label] })), size: "xs", variant: "outlined", buttonProps: {
|
|
70
80
|
title: "Select Color",
|
|
81
|
+
style: { padding: "1px 6px" },
|
|
82
|
+
}, dropDownProps: {
|
|
83
|
+
style: {
|
|
84
|
+
width: 120,
|
|
85
|
+
},
|
|
86
|
+
}, children: _jsx(PaletteIcon, { size: 14 }) })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HIGHLIGHT)) && (_jsx(DropDownMenu, { data: [
|
|
87
|
+
{
|
|
88
|
+
label: "Default",
|
|
89
|
+
value: "default",
|
|
90
|
+
onClick: () => {
|
|
91
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetHighlight().run();
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
...Object.keys(HighlightColors).map((color) => {
|
|
95
|
+
const colorKey = color;
|
|
96
|
+
return {
|
|
97
|
+
label: color,
|
|
98
|
+
value: HighlightColors[colorKey],
|
|
99
|
+
onClick: () => {
|
|
100
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().setHighlight({ color: HighlightColors[colorKey] }).run();
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}),
|
|
104
|
+
], renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
|
|
105
|
+
? theme.palette.text.primary
|
|
106
|
+
: item.value, style: {
|
|
107
|
+
backgroundColor: item.value === "default"
|
|
108
|
+
? "transparent"
|
|
109
|
+
: item.value,
|
|
110
|
+
borderRadius: "3px",
|
|
111
|
+
} }), item.label] })), size: "xs", variant: "outlined", buttonProps: {
|
|
112
|
+
title: "Select Highlight",
|
|
113
|
+
style: { padding: "1px 6px" },
|
|
71
114
|
}, dropDownProps: {
|
|
72
115
|
style: {
|
|
73
116
|
width: 100,
|
|
117
|
+
height: 210,
|
|
74
118
|
},
|
|
75
|
-
}, children:
|
|
119
|
+
}, children: _jsx(HighlighterIcon, { size: 14 }) })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.LINK)) && (_jsxs(Popover, { opened: linkPopoverOpen, onChange: setLinkPopoverOpen, position: "bottom", width: 330, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { size: "xs", variant: "outlined", title: "Link", "aria-label": "Link", selected: linkPopoverOpen || Boolean(editor === null || editor === void 0 ? void 0 : editor.isActive("link")), disabled: !editor, style: { padding: "1px 6px" }, children: _jsx(LinkIcon, { size: 14 }) }) }), _jsx(Popover.Dropdown, { children: editor && (_jsx(LinkEditor, { editor: editor, autoFocus: linkPopoverOpen, onClose: () => setLinkPopoverOpen(false) })) })] })), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BOLD)) && _jsx(BoldControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ITALIC)) && (_jsx(ItalicControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDERLINE)) && (_jsx(UnderlineControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.STRIKE)) && (_jsx(StrikeThroughControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE)) && _jsx(CodeControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE_BLOCK)) && (_jsx(CodeBlockControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE_BLOCK)) &&
|
|
120
|
+
showCodeBlockLanguageSelect && (_jsxs(_Fragment, { children: [_jsx(CodeBlockLanguageSelect, { editor: editor }), _jsx(CodeBlockWrapButton, { editor: editor }), _jsx(CodeBlockFormatButton, { editor: editor })] }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_1)) && (_jsx(Heading1Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_2)) && (_jsx(Heading2Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_3)) && (_jsx(Heading3Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_4)) && (_jsx(Heading4Control, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BULLET_LIST)) && (_jsx(BulletListControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ORDERED_LIST)) && (_jsx(OrderedListControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_LEFT)) && (_jsx(AlignLeftControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_CENTER)) && (_jsx(AlignCenterControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_RIGHT)) && (_jsx(AlignRightControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_JUSTIFIED)) && (_jsx(AlignJustifiedControl, { editor: editor }))] })] }));
|
|
76
121
|
}) `
|
|
77
122
|
display: flex;
|
|
78
123
|
flex-direction: row;
|
|
124
|
+
flex-wrap: wrap;
|
|
79
125
|
justify-content: center;
|
|
80
126
|
align-items: center;
|
|
81
127
|
gap: 5px;
|
|
128
|
+
row-gap: 6px;
|
|
129
|
+
width: 100%;
|
|
82
130
|
margin-bottom: 10px;
|
|
83
131
|
border-radius: 5px 5px 0 0;
|
|
84
132
|
border: 1px solid transparent;
|
|
133
|
+
|
|
134
|
+
> button,
|
|
135
|
+
> .mfui-DropDownMenu {
|
|
136
|
+
flex: 0 0 auto;
|
|
137
|
+
}
|
|
85
138
|
`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/react";
|
|
2
|
+
export type CodeBlockLanguage = {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const DEFAULT_CODE_BLOCK_LANGUAGE = "plaintext";
|
|
7
|
+
export declare const CODE_BLOCK_LANGUAGES: CodeBlockLanguage[];
|
|
8
|
+
export declare const getCodeBlockLanguage: (editor: Editor | null) => string;
|
|
9
|
+
export declare const getCodeBlockLanguageOption: (language?: string) => CodeBlockLanguage;
|
|
10
|
+
export declare const canFormatCodeBlockLanguage: (language?: string) => boolean;
|
|
11
|
+
export declare const formatCodeBlockText: (text: string, language?: string) => Promise<string>;
|
|
12
|
+
export declare const hasSyntaxHighlightedCodeBlock: (editor: Editor | null) => boolean;
|
|
13
|
+
export declare const setCodeBlockLanguage: (editor: Editor | null, language: string) => void;
|
|
14
|
+
export declare const getCodeBlockWrap: (editor: Editor | null) => boolean;
|
|
15
|
+
export declare const toggleCodeBlockWrap: (editor: Editor | null) => void;
|
|
16
|
+
export declare const toggleCodeBlock: (editor: Editor | null) => void;
|
|
17
|
+
export declare const getActiveCodeBlockText: (editor: Editor | null) => string;
|
|
18
|
+
export declare const replaceCodeBlockContent: (editor: Editor, from: number, to: number, text: string) => boolean;
|
|
19
|
+
export declare const formatActiveCodeBlock: (editor: Editor | null) => Promise<void>;
|
|
20
|
+
export declare const copyCodeBlockText: (text: string) => Promise<void>;
|