mirror of
https://github.com/docmost/docmost.git
synced 2026-06-22 09:01:37 +10:00
feat: package updates (#2300)
* package updates * update tiptap * fix editor crash * fix * update list * fix(theme): size badges to their content * fix mantine avatar color regression
This commit is contained in:
@@ -41,7 +41,7 @@
|
|||||||
"highlightjs-sap-abap": "0.3.0",
|
"highlightjs-sap-abap": "0.3.0",
|
||||||
"i18next": "25.10.1",
|
"i18next": "25.10.1",
|
||||||
"i18next-http-backend": "3.0.6",
|
"i18next-http-backend": "3.0.6",
|
||||||
"jotai": "2.18.1",
|
"jotai": "2.20.1",
|
||||||
"jotai-optics": "0.4.0",
|
"jotai-optics": "0.4.0",
|
||||||
"js-cookie": "3.0.7",
|
"js-cookie": "3.0.7",
|
||||||
"jwt-decode": "4.0.0",
|
"jwt-decode": "4.0.0",
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
"mantine-form-zod-resolver": "1.3.0",
|
"mantine-form-zod-resolver": "1.3.0",
|
||||||
"mermaid": "11.15.0",
|
"mermaid": "11.15.0",
|
||||||
"mitt": "3.0.1",
|
"mitt": "3.0.1",
|
||||||
"posthog-js": "1.372.2",
|
"posthog-js": "1.391.2",
|
||||||
"react": "19.2.7",
|
"react": "19.2.7",
|
||||||
"react-clear-modal": "^2.0.18",
|
"react-clear-modal": "^2.0.18",
|
||||||
"react-dom": "19.2.7",
|
"react-dom": "19.2.7",
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
"react-error-boundary": "6.1.1",
|
"react-error-boundary": "6.1.1",
|
||||||
"react-helmet-async": "3.0.0",
|
"react-helmet-async": "3.0.0",
|
||||||
"react-i18next": "16.5.8",
|
"react-i18next": "16.5.8",
|
||||||
"react-router-dom": "7.13.1",
|
"react-router-dom": "7.18.0",
|
||||||
"semver": "7.7.4",
|
"semver": "7.7.4",
|
||||||
"socket.io-client": "4.8.3",
|
"socket.io-client": "4.8.3",
|
||||||
"zod": "4.3.6"
|
"zod": "4.3.6"
|
||||||
|
|||||||
@@ -54,14 +54,17 @@ export const CustomAvatar = React.forwardRef<
|
|||||||
>(({ avatarUrl, name, type, color, variant, ...props }: CustomAvatarProps, ref) => {
|
>(({ avatarUrl, name, type, color, variant, ...props }: CustomAvatarProps, ref) => {
|
||||||
const avatarLink = getAvatarUrl(avatarUrl, type);
|
const avatarLink = getAvatarUrl(avatarUrl, type);
|
||||||
const isInitials = !color || color === "initials";
|
const isInitials = !color || color === "initials";
|
||||||
const resolvedColor = isInitials ? pickInitialsColor(name ?? "") : color;
|
const pickedColor = isInitials ? pickInitialsColor(name ?? "") : color;
|
||||||
|
const hue = pickedColor.split(".")[0];
|
||||||
const initialsSource = sanitizeInitialsSource(name ?? "");
|
const initialsSource = sanitizeInitialsSource(name ?? "");
|
||||||
|
|
||||||
|
const resolvedColor = variant === "filled" ? pickedColor : hue;
|
||||||
|
|
||||||
const placeholderStyles =
|
const placeholderStyles =
|
||||||
isInitials && variant !== "filled"
|
isInitials && variant !== "filled"
|
||||||
? {
|
? {
|
||||||
placeholder: {
|
placeholder: {
|
||||||
color: `var(--mantine-color-${resolvedColor.split(".")[0]}-9)`,
|
color: `var(--mantine-color-${hue}-9)`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ export default function ChatInput({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSubmit = useCallback(() => {
|
const handleSubmit = useCallback(() => {
|
||||||
if (!editor || isStreaming) return;
|
if (!editor || editor.isDestroyed || isStreaming) return;
|
||||||
const json = editor.getJSON();
|
const json = editor.getJSON();
|
||||||
const text = editorJsonToText(json).trim();
|
const text = editorJsonToText(json).trim();
|
||||||
const readyAttachments = pendingAttachments.filter((a) => !a.uploading);
|
const readyAttachments = pendingAttachments.filter((a) => !a.uploading);
|
||||||
@@ -264,7 +264,7 @@ export default function ChatInput({
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editor && autofocus) {
|
if (editor && !editor.isDestroyed && autofocus) {
|
||||||
editor.commands.focus();
|
editor.commands.focus();
|
||||||
}
|
}
|
||||||
}, [editor]);
|
}, [editor]);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { ResultPreview } from "./result-preview.tsx";
|
|||||||
import classes from "./ai-menu.module.css";
|
import classes from "./ai-menu.module.css";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import { DOMSerializer } from "@tiptap/pm/model";
|
import { DOMSerializer } from "@tiptap/pm/model";
|
||||||
import { copyToClipboard, htmlToMarkdown } from "@docmost/editor-ext";
|
import { copyToClipboard, htmlToMarkdown, isEditorReady } from "@docmost/editor-ext";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
interface EditorAiMenuProps {
|
interface EditorAiMenuProps {
|
||||||
@@ -56,7 +56,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
|||||||
});
|
});
|
||||||
}, [prompt, output, activeCommandSet]);
|
}, [prompt, output, activeCommandSet]);
|
||||||
const updateMenuPlacement = useCallback(() => {
|
const updateMenuPlacement = useCallback(() => {
|
||||||
if (!editor || !showAiMenu) return;
|
if (!isEditorReady(editor) || !showAiMenu) return;
|
||||||
|
|
||||||
const { view } = editor;
|
const { view } = editor;
|
||||||
const { from, to } = editor.state.selection;
|
const { from, to } = editor.state.selection;
|
||||||
@@ -102,7 +102,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
|||||||
);
|
);
|
||||||
const handleGenerate = useCallback(
|
const handleGenerate = useCallback(
|
||||||
(item?: CommandItem) => {
|
(item?: CommandItem) => {
|
||||||
if (!editor || isLoading) return;
|
if (!isEditorReady(editor) || isLoading) return;
|
||||||
|
|
||||||
let command: CommandItem | null = item || null;
|
let command: CommandItem | null = item || null;
|
||||||
|
|
||||||
@@ -165,6 +165,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
|||||||
return setActiveCommandSet("main");
|
return setActiveCommandSet("main");
|
||||||
}
|
}
|
||||||
if (item.id === "result-replace") {
|
if (item.id === "result-replace") {
|
||||||
|
if (!isEditorReady(editor)) return setShowAiMenu(false);
|
||||||
const chain = editor.chain().focus();
|
const chain = editor.chain().focus();
|
||||||
|
|
||||||
if (lastAction.action === AiAction.CONTINUE_WRITING) {
|
if (lastAction.action === AiAction.CONTINUE_WRITING) {
|
||||||
@@ -190,6 +191,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
|||||||
return setShowAiMenu(false);
|
return setShowAiMenu(false);
|
||||||
}
|
}
|
||||||
if (item.id === "result-insert-below") {
|
if (item.id === "result-insert-below") {
|
||||||
|
if (!isEditorReady(editor)) return setShowAiMenu(false);
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
@@ -253,7 +255,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editor) return;
|
if (!isEditorReady(editor)) return;
|
||||||
|
|
||||||
const handleClose = () => setShowAiMenu(false);
|
const handleClose = () => setShowAiMenu(false);
|
||||||
const observer = new ResizeObserver(() => {
|
const observer = new ResizeObserver(() => {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { IconCircleCheck, IconCircleCheckFilled } from "@tabler/icons-react";
|
|||||||
import { useResolveCommentMutation } from "@/ee/comment/queries/comment-query";
|
import { useResolveCommentMutation } from "@/ee/comment/queries/comment-query";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Editor } from "@tiptap/react";
|
import { Editor } from "@tiptap/react";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
|
|
||||||
interface ResolveCommentProps {
|
interface ResolveCommentProps {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
@@ -31,7 +32,7 @@ function ResolveComment({
|
|||||||
resolved: !isResolved,
|
resolved: !isResolved,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (editor) {
|
if (isEditorReady(editor)) {
|
||||||
editor.commands.setCommentResolved(commentId, !isResolved);
|
editor.commands.setCommentResolved(commentId, !isResolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const enterpriseFeatures = [
|
|||||||
"Confluence Import",
|
"Confluence Import",
|
||||||
"PDF & DOCX Import",
|
"PDF & DOCX Import",
|
||||||
"Templates",
|
"Templates",
|
||||||
|
"Personal Spaces"
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function OssDetails() {
|
export default function OssDetails() {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export default function TemplateEditor() {
|
|||||||
|
|
||||||
// Load template data into editor
|
// Load template data into editor
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (existingTemplate && editor) {
|
if (existingTemplate && editor && !editor.isDestroyed) {
|
||||||
loadedRef.current = false;
|
loadedRef.current = false;
|
||||||
setTitle(existingTemplate.title || "");
|
setTitle(existingTemplate.title || "");
|
||||||
setIcon(existingTemplate.icon || null);
|
setIcon(existingTemplate.icon || null);
|
||||||
@@ -383,7 +383,8 @@ export default function TemplateEditor() {
|
|||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
editor?.commands.focus("start");
|
if (editor && !editor.isDestroyed)
|
||||||
|
editor.commands.focus("start");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { currentUserAtom } from "@/features/user/atoms/current-user-atom";
|
|||||||
import { useCreateCommentMutation } from "@/features/comment/queries/comment-query";
|
import { useCreateCommentMutation } from "@/features/comment/queries/comment-query";
|
||||||
import { asideStateAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom";
|
import { asideStateAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom";
|
||||||
import { useEditor } from "@tiptap/react";
|
import { useEditor } from "@tiptap/react";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
|
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
@@ -48,11 +49,14 @@ function CommentDialog({ editor, pageId, readOnly }: CommentDialogProps) {
|
|||||||
setReadOnlyCommentData(null);
|
setReadOnlyCommentData(null);
|
||||||
} else {
|
} else {
|
||||||
setShowCommentPopup(false);
|
setShowCommentPopup(false);
|
||||||
editor.chain().focus().unsetCommentDecoration().run();
|
if (isEditorReady(editor)) {
|
||||||
|
editor.chain().focus().unsetCommentDecoration().run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSelectedText = () => {
|
const getSelectedText = () => {
|
||||||
|
if (!isEditorReady(editor)) return "";
|
||||||
const { from, to } = editor.state.selection;
|
const { from, to } = editor.state.selection;
|
||||||
return editor.state.doc.textBetween(from, to);
|
return editor.state.doc.textBetween(from, to);
|
||||||
};
|
};
|
||||||
@@ -74,24 +78,28 @@ function CommentDialog({ editor, pageId, readOnly }: CommentDialogProps) {
|
|||||||
|
|
||||||
const createdComment =
|
const createdComment =
|
||||||
await createCommentMutation.mutateAsync(commentData);
|
await createCommentMutation.mutateAsync(commentData);
|
||||||
editor
|
if (isEditorReady(editor)) {
|
||||||
.chain()
|
editor
|
||||||
.setComment(createdComment.id)
|
.chain()
|
||||||
.unsetCommentDecoration()
|
.setComment(createdComment.id)
|
||||||
.run();
|
.unsetCommentDecoration()
|
||||||
|
.run();
|
||||||
|
editor.commands.setTextSelection({
|
||||||
|
from: editor.view.state.selection.from,
|
||||||
|
to: editor.view.state.selection.from,
|
||||||
|
});
|
||||||
|
}
|
||||||
setActiveCommentId(createdComment.id);
|
setActiveCommentId(createdComment.id);
|
||||||
|
|
||||||
editor.commands.setTextSelection({ from: editor.view.state.selection.from, to: editor.view.state.selection.from });
|
|
||||||
|
|
||||||
setAsideState({ tab: "comments", isAsideOpen: true });
|
setAsideState({ tab: "comments", isAsideOpen: true });
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const selector = `div[data-comment-id="${createdComment.id}"]`;
|
const selector = `div[data-comment-id="${createdComment.id}"]`;
|
||||||
const commentElement = document.querySelector(selector);
|
const commentElement = document.querySelector(selector);
|
||||||
commentElement?.scrollIntoView({ behavior: "smooth", block: "center" });
|
commentElement?.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||||
|
|
||||||
editor.view.dispatch(
|
if (isEditorReady(editor)) {
|
||||||
editor.state.tr.scrollIntoView()
|
editor.view.dispatch(editor.state.tr.scrollIntoView());
|
||||||
);
|
}
|
||||||
}, 400);
|
}, 400);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -112,22 +112,24 @@ const CommentEditor = forwardRef(
|
|||||||
// websocket on another browser). Skip for editable editors to avoid
|
// websocket on another browser). Skip for editable editors to avoid
|
||||||
// resetting the cursor position on every keystroke.
|
// resetting the cursor position on every keystroke.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editable && commentEditor && defaultContent) {
|
if (!editable && commentEditor && !commentEditor.isDestroyed && defaultContent) {
|
||||||
commentEditor.commands.setContent(defaultContent);
|
commentEditor.commands.setContent(defaultContent);
|
||||||
}
|
}
|
||||||
}, [defaultContent, editable, commentEditor]);
|
}, [defaultContent, editable, commentEditor]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (autofocus) {
|
if (autofocus && commentEditor && !commentEditor.isDestroyed) {
|
||||||
commentEditor?.commands.focus("end");
|
commentEditor.commands.focus("end");
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
}, [commentEditor, autofocus]);
|
}, [commentEditor, autofocus]);
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
clearContent: () => {
|
clearContent: () => {
|
||||||
commentEditor.commands.clearContent();
|
if (commentEditor && !commentEditor.isDestroyed) {
|
||||||
|
commentEditor.commands.clearContent();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useAtom, useAtomValue } from "jotai";
|
|||||||
import { useTimeAgo } from "@/hooks/use-time-ago";
|
import { useTimeAgo } from "@/hooks/use-time-ago";
|
||||||
import CommentEditor from "@/features/comment/components/comment-editor";
|
import CommentEditor from "@/features/comment/components/comment-editor";
|
||||||
import { pageEditorAtom } from "@/features/editor/atoms/editor-atoms";
|
import { pageEditorAtom } from "@/features/editor/atoms/editor-atoms";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
import CommentActions from "@/features/comment/components/comment-actions";
|
import CommentActions from "@/features/comment/components/comment-actions";
|
||||||
import CommentMenu from "@/features/comment/components/comment-menu";
|
import CommentMenu from "@/features/comment/components/comment-menu";
|
||||||
import { useHasFeature } from "@/ee/hooks/use-feature";
|
import { useHasFeature } from "@/ee/hooks/use-feature";
|
||||||
@@ -75,7 +76,9 @@ function CommentListItem({
|
|||||||
async function handleDeleteComment() {
|
async function handleDeleteComment() {
|
||||||
try {
|
try {
|
||||||
await deleteCommentMutation.mutateAsync(comment.id);
|
await deleteCommentMutation.mutateAsync(comment.id);
|
||||||
editor?.commands.unsetComment(comment.id);
|
if (isEditorReady(editor)) {
|
||||||
|
editor.commands.unsetComment(comment.id);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to delete comment:", error);
|
console.error("Failed to delete comment:", error);
|
||||||
}
|
}
|
||||||
@@ -93,7 +96,7 @@ function CommentListItem({
|
|||||||
resolved: !isResolved,
|
resolved: !isResolved,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (editor) {
|
if (isEditorReady(editor)) {
|
||||||
editor.commands.setCommentResolved(comment.id, !isResolved);
|
editor.commands.setCommentResolved(comment.id, !isResolved);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
} from "@/features/comment/atoms/comment-atom";
|
} from "@/features/comment/atoms/comment-atom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { getRelativeSelection, ySyncPluginKey } from "@tiptap/y-tiptap";
|
import { getRelativeSelection, ySyncPluginKey } from "@tiptap/y-tiptap";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
|
|
||||||
type ReadonlyBubbleMenuProps = {
|
type ReadonlyBubbleMenuProps = {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
@@ -29,6 +30,10 @@ export const ReadonlyBubbleMenu: FC<ReadonlyBubbleMenuProps> = ({ editor }) => {
|
|||||||
|
|
||||||
const updateMenuPosition = useCallback(() => {
|
const updateMenuPosition = useCallback(() => {
|
||||||
if (isInteractingRef.current) return;
|
if (isInteractingRef.current) return;
|
||||||
|
if (!isEditorReady(editor)) {
|
||||||
|
setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const pmSelection = editor.state.selection;
|
const pmSelection = editor.state.selection;
|
||||||
if (!(pmSelection instanceof TextSelection) || pmSelection.empty) {
|
if (!(pmSelection instanceof TextSelection) || pmSelection.empty) {
|
||||||
@@ -97,7 +102,7 @@ export const ReadonlyBubbleMenu: FC<ReadonlyBubbleMenuProps> = ({ editor }) => {
|
|||||||
}, [showReadOnlyCommentPopup]);
|
}, [showReadOnlyCommentPopup]);
|
||||||
|
|
||||||
const handleCommentClick = () => {
|
const handleCommentClick = () => {
|
||||||
if (!editor) return;
|
if (!isEditorReady(editor)) return;
|
||||||
|
|
||||||
const view = editor.view;
|
const view = editor.view;
|
||||||
const ystate = ySyncPluginKey.getState(view.state);
|
const ystate = ySyncPluginKey.getState(view.state);
|
||||||
|
|||||||
+1
-1
@@ -96,7 +96,7 @@ export const MoreInsertsGroup: FC<Props> = ({ editor, templateMode }) => {
|
|||||||
<Menu.Item
|
<Menu.Item
|
||||||
leftSection={<IconRotate2 size={16} />}
|
leftSection={<IconRotate2 size={16} />}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
editor.chain().focus().insertTransclusionSource().run()
|
editor.chain().focus().toggleTransclusionSource().run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("Synced block")}
|
{t("Synced block")}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import { usePageQuery } from "@/features/page/queries/page-query.ts";
|
|||||||
import { useSharePageQuery } from "@/features/share/queries/share-query.ts";
|
import { useSharePageQuery } from "@/features/share/queries/share-query.ts";
|
||||||
import { buildSharedPageUrl } from "@/features/page/page.utils.ts";
|
import { buildSharedPageUrl } from "@/features/page/page.utils.ts";
|
||||||
import { extractPageSlugId } from "@/lib";
|
import { extractPageSlugId } from "@/lib";
|
||||||
import { sanitizeUrl, copyToClipboard } from "@docmost/editor-ext";
|
import { sanitizeUrl, copyToClipboard, isEditorReady } from "@docmost/editor-ext";
|
||||||
import { normalizeUrl } from "@/lib/utils";
|
import { normalizeUrl } from "@/lib/utils";
|
||||||
|
|
||||||
const parseInternalLink = (
|
const parseInternalLink = (
|
||||||
@@ -313,7 +313,9 @@ export default function LinkView(props: MarkViewProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleRemoveLink = useCallback(() => {
|
const handleRemoveLink = useCallback(() => {
|
||||||
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
if (isEditorReady(editor)) {
|
||||||
|
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
||||||
|
}
|
||||||
setPopoverState("closed");
|
setPopoverState("closed");
|
||||||
}, [editor]);
|
}, [editor]);
|
||||||
|
|
||||||
@@ -345,7 +347,7 @@ export default function LinkView(props: MarkViewProps) {
|
|||||||
NodeFilter.SHOW_TEXT,
|
NodeFilter.SHOW_TEXT,
|
||||||
);
|
);
|
||||||
const textNode = walker.nextNode();
|
const textNode = walker.nextNode();
|
||||||
if (textNode) {
|
if (textNode && isEditorReady(editor)) {
|
||||||
const view = editor.view as any;
|
const view = editor.view as any;
|
||||||
view.domObserver.stop();
|
view.domObserver.stop();
|
||||||
textNode.nodeValue = val;
|
textNode.nodeValue = val;
|
||||||
|
|||||||
+10
-2
@@ -17,6 +17,7 @@ import {
|
|||||||
IconX,
|
IconX,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import { useEditor } from "@tiptap/react";
|
import { useEditor } from "@tiptap/react";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { searchAndReplaceStateAtom } from "@/features/editor/components/search-and-replace/atoms/search-and-replace-state-atom.ts";
|
import { searchAndReplaceStateAtom } from "@/features/editor/components/search-and-replace/atoms/search-and-replace-state-atom.ts";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
@@ -64,13 +65,13 @@ function SearchAndReplaceDialog({ editor, editable = true }: PageFindDialogDialo
|
|||||||
replaceButtonToggle();
|
replaceButtonToggle();
|
||||||
}
|
}
|
||||||
// Clear search term in editor
|
// Clear search term in editor
|
||||||
if (editor) {
|
if (isEditorReady(editor)) {
|
||||||
editor.commands.setSearchTerm("");
|
editor.commands.setSearchTerm("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToSelection = () => {
|
const goToSelection = () => {
|
||||||
if (!editor) return;
|
if (!isEditorReady(editor)) return;
|
||||||
|
|
||||||
const { results, resultIndex } = editor.storage.searchAndReplace;
|
const { results, resultIndex } = editor.storage.searchAndReplace;
|
||||||
//TODO: check type error
|
//TODO: check type error
|
||||||
@@ -90,27 +91,32 @@ function SearchAndReplaceDialog({ editor, editable = true }: PageFindDialogDialo
|
|||||||
};
|
};
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.nextSearchResult();
|
editor.commands.nextSearchResult();
|
||||||
goToSelection();
|
goToSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
const previous = () => {
|
const previous = () => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.previousSearchResult();
|
editor.commands.previousSearchResult();
|
||||||
goToSelection();
|
goToSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
const replace = () => {
|
const replace = () => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.setReplaceTerm(replaceText);
|
editor.commands.setReplaceTerm(replaceText);
|
||||||
editor.commands.replace();
|
editor.commands.replace();
|
||||||
goToSelection();
|
goToSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
const replaceAll = () => {
|
const replaceAll = () => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.setReplaceTerm(replaceText);
|
editor.commands.setReplaceTerm(replaceText);
|
||||||
editor.commands.replaceAll();
|
editor.commands.replaceAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.setSearchTerm(searchText);
|
editor.commands.setSearchTerm(searchText);
|
||||||
editor.commands.resetIndex();
|
editor.commands.resetIndex();
|
||||||
editor.commands.selectCurrentItem();
|
editor.commands.selectCurrentItem();
|
||||||
@@ -118,6 +124,7 @@ function SearchAndReplaceDialog({ editor, editable = true }: PageFindDialogDialo
|
|||||||
|
|
||||||
const handleOpenEvent = (e) => {
|
const handleOpenEvent = (e) => {
|
||||||
setPageFindState({ isOpen: true });
|
setPageFindState({ isOpen: true });
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
const selectedText = editor.state.doc.textBetween(
|
const selectedText = editor.state.doc.textBetween(
|
||||||
editor.state.selection.from,
|
editor.state.selection.from,
|
||||||
editor.state.selection.to,
|
editor.state.selection.to,
|
||||||
@@ -149,6 +156,7 @@ function SearchAndReplaceDialog({ editor, editable = true }: PageFindDialogDialo
|
|||||||
}, [pageFindState.isOpen]);
|
}, [pageFindState.isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.setCaseSensitive(caseSensitive.isCaseSensitive);
|
editor.commands.setCaseSensitive(caseSensitive.isCaseSensitive);
|
||||||
editor.commands.resetIndex();
|
editor.commands.resetIndex();
|
||||||
goToSelection();
|
goToSelection();
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export const TableOfContents: FC<TableOfContentsProps> = (props) => {
|
|||||||
const headerPaddingRef = useRef<HTMLDivElement | null>(null);
|
const headerPaddingRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
const handleScrollToHeading = (position: number) => {
|
const handleScrollToHeading = (position: number) => {
|
||||||
|
if (!props.editor || props.editor.isDestroyed) return;
|
||||||
const { view } = props.editor;
|
const { view } = props.editor;
|
||||||
|
|
||||||
const headerOffset = parseInt(
|
const headerOffset = parseInt(
|
||||||
@@ -73,16 +74,21 @@ export const TableOfContents: FC<TableOfContentsProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
const result = recalculateLinks(props.editor?.$nodes("heading"));
|
if (!props.editor || props.editor.isDestroyed) return;
|
||||||
|
|
||||||
|
const result = recalculateLinks(props.editor.$nodes("heading"));
|
||||||
|
|
||||||
setLinks(result.links);
|
setLinks(result.links);
|
||||||
setHeadingDOMNodes(result.nodes);
|
setHeadingDOMNodes(result.nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// "create" repopulates once the editor view mounts after this component
|
||||||
|
props.editor?.on("create", handleUpdate);
|
||||||
props.editor?.on("update", handleUpdate);
|
props.editor?.on("update", handleUpdate);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
props.editor?.off("create", handleUpdate);
|
||||||
props.editor?.off("update", handleUpdate);
|
props.editor?.off("update", handleUpdate);
|
||||||
};
|
};
|
||||||
}, [props.editor]);
|
}, [props.editor]);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { Menu, UnstyledButton } from "@mantine/core";
|
|||||||
import { IconChevronDown } from "@tabler/icons-react";
|
import { IconChevronDown } from "@tabler/icons-react";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { isCellSelection } from "@docmost/editor-ext";
|
import { isCellSelection, isEditorReady } from "@docmost/editor-ext";
|
||||||
import { CellChevronMenu } from "./menus/cell-chevron-menu";
|
import { CellChevronMenu } from "./menus/cell-chevron-menu";
|
||||||
import classes from "./handle.module.css";
|
import classes from "./handle.module.css";
|
||||||
|
|
||||||
@@ -27,7 +27,9 @@ export const CellChevron = React.memo(function CellChevron({
|
|||||||
tablePos,
|
tablePos,
|
||||||
}: CellChevronProps) {
|
}: CellChevronProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const cellDom = editor.view.nodeDOM(cellPos) as HTMLElement | null;
|
const cellDom = isEditorReady(editor)
|
||||||
|
? (editor.view.nodeDOM(cellPos) as HTMLElement | null)
|
||||||
|
: null;
|
||||||
|
|
||||||
const { refs, floatingStyles, middlewareData } = useFloating({
|
const { refs, floatingStyles, middlewareData } = useFloating({
|
||||||
placement: "top-end",
|
placement: "top-end",
|
||||||
@@ -61,6 +63,7 @@ export const CellChevron = React.memo(function CellChevron({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onOpen = useCallback(() => {
|
const onOpen = useCallback(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
const current = editor.state.selection;
|
const current = editor.state.selection;
|
||||||
|
|
||||||
// Preserve an existing multi-cell CellSelection that already covers
|
// Preserve an existing multi-cell CellSelection that already covers
|
||||||
@@ -86,6 +89,7 @@ export const CellChevron = React.memo(function CellChevron({
|
|||||||
}, [editor, cellPos]);
|
}, [editor, cellPos]);
|
||||||
|
|
||||||
const onClose = useCallback(() => {
|
const onClose = useCallback(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.unfreezeHandles();
|
editor.commands.unfreezeHandles();
|
||||||
}, [editor]);
|
}, [editor]);
|
||||||
|
|
||||||
|
|||||||
+3
@@ -1,6 +1,7 @@
|
|||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import type { Editor } from "@tiptap/react";
|
import type { Editor } from "@tiptap/react";
|
||||||
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
import { buildRowOrColumnSelection, Orientation } from "../lib/select-row-column";
|
import { buildRowOrColumnSelection, Orientation } from "../lib/select-row-column";
|
||||||
|
|
||||||
interface Args {
|
interface Args {
|
||||||
@@ -19,6 +20,7 @@ export function useColumnRowMenuLifecycle({
|
|||||||
tablePos,
|
tablePos,
|
||||||
}: Args) {
|
}: Args) {
|
||||||
const onOpen = useCallback(() => {
|
const onOpen = useCallback(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
const selection = buildRowOrColumnSelection(
|
const selection = buildRowOrColumnSelection(
|
||||||
editor.state,
|
editor.state,
|
||||||
tableNode,
|
tableNode,
|
||||||
@@ -33,6 +35,7 @@ export function useColumnRowMenuLifecycle({
|
|||||||
}, [editor, orientation, index, tableNode, tablePos]);
|
}, [editor, orientation, index, tableNode, tablePos]);
|
||||||
|
|
||||||
const onClose = useCallback(() => {
|
const onClose = useCallback(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
editor.commands.unfreezeHandles();
|
editor.commands.unfreezeHandles();
|
||||||
}, [editor]);
|
}, [editor]);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useCallback } from "react";
|
|||||||
import type { Editor } from "@tiptap/react";
|
import type { Editor } from "@tiptap/react";
|
||||||
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
import { TableMap } from "@tiptap/pm/tables";
|
import { TableMap } from "@tiptap/pm/tables";
|
||||||
|
import { isEditorReady } from "@docmost/editor-ext";
|
||||||
|
|
||||||
type Scope =
|
type Scope =
|
||||||
| { kind: "col"; index: number }
|
| { kind: "col"; index: number }
|
||||||
@@ -15,6 +16,7 @@ export function useTableClear(
|
|||||||
scope: Scope,
|
scope: Scope,
|
||||||
) {
|
) {
|
||||||
return useCallback(() => {
|
return useCallback(() => {
|
||||||
|
if (!isEditorReady(editor)) return;
|
||||||
const tr = editor.state.tr;
|
const tr = editor.state.tr;
|
||||||
const tableStart = tablePos + 1;
|
const tableStart = tablePos + 1;
|
||||||
const map = TableMap.get(tableNode);
|
const map = TableMap.get(tableNode);
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ import { useCallback, useMemo } from "react";
|
|||||||
import type { Editor } from "@tiptap/react";
|
import type { Editor } from "@tiptap/react";
|
||||||
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
import { TableMap } from "@tiptap/pm/tables";
|
import { TableMap } from "@tiptap/pm/tables";
|
||||||
import { moveColumn, moveRow } from "@docmost/editor-ext";
|
import { isEditorReady, moveColumn, moveRow } from "@docmost/editor-ext";
|
||||||
|
|
||||||
export type MoveDirection = "left" | "right" | "up" | "down";
|
export type MoveDirection = "left" | "right" | "up" | "down";
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export function useTableMoveRowColumn(
|
|||||||
const canMove = target >= 0 && target <= maxIndex;
|
const canMove = target >= 0 && target <= maxIndex;
|
||||||
|
|
||||||
const handleMove = useCallback(() => {
|
const handleMove = useCallback(() => {
|
||||||
if (!canMove) return;
|
if (!canMove || !isEditorReady(editor)) return;
|
||||||
const tr = editor.state.tr;
|
const tr = editor.state.tr;
|
||||||
const moved =
|
const moved =
|
||||||
orientation === "col"
|
orientation === "col"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|||||||
import {
|
import {
|
||||||
convertArrayOfRowsToTableNode,
|
convertArrayOfRowsToTableNode,
|
||||||
convertTableNodeToArrayOfRows,
|
convertTableNodeToArrayOfRows,
|
||||||
|
isEditorReady,
|
||||||
transpose,
|
transpose,
|
||||||
} from "@docmost/editor-ext";
|
} from "@docmost/editor-ext";
|
||||||
import {
|
import {
|
||||||
@@ -63,7 +64,7 @@ export function useTableSort({
|
|||||||
}, [tableNode, orientation, index]);
|
}, [tableNode, orientation, index]);
|
||||||
|
|
||||||
const handleSort = useCallback(() => {
|
const handleSort = useCallback(() => {
|
||||||
if (!canSort) return;
|
if (!canSort || !isEditorReady(editor)) return;
|
||||||
|
|
||||||
const rows = convertTableNodeToArrayOfRows(tableNode);
|
const rows = convertTableNodeToArrayOfRows(tableNode);
|
||||||
const axes = orientation === "col" ? rows : transpose(rows);
|
const axes = orientation === "col" ? rows : transpose(rows);
|
||||||
|
|||||||
@@ -152,7 +152,11 @@ export function TitleEditor({
|
|||||||
const debounceUpdate = useDebouncedCallback(saveTitle, 500);
|
const debounceUpdate = useDebouncedCallback(saveTitle, 500);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (titleEditor && title !== titleEditor.getText()) {
|
if (
|
||||||
|
titleEditor &&
|
||||||
|
!titleEditor.isDestroyed &&
|
||||||
|
title !== titleEditor.getText()
|
||||||
|
) {
|
||||||
titleEditor.commands.setContent(title);
|
titleEditor.commands.setContent(title);
|
||||||
}
|
}
|
||||||
}, [pageId, title, titleEditor]);
|
}, [pageId, title, titleEditor]);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export function HistoryEditor({
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editor || !content) return;
|
if (!editor || editor.isDestroyed || !content) return;
|
||||||
|
|
||||||
let decorationSet = DecorationSet.empty;
|
let decorationSet = DecorationSet.empty;
|
||||||
let addedCount = 0;
|
let addedCount = 0;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
Badge,
|
||||||
createTheme,
|
createTheme,
|
||||||
CSSVariablesResolver,
|
CSSVariablesResolver,
|
||||||
MantineColorsTuple,
|
MantineColorsTuple,
|
||||||
@@ -38,6 +39,15 @@ export const theme = createTheme({
|
|||||||
red,
|
red,
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
// Size badges to their content; fit-content collapses inside table cells.
|
||||||
|
Badge: Badge.extend({
|
||||||
|
styles: (_theme, props) => ({
|
||||||
|
root:
|
||||||
|
props.fullWidth || props.circle
|
||||||
|
? {}
|
||||||
|
: { width: "max-content", maxWidth: "100%" },
|
||||||
|
}),
|
||||||
|
}),
|
||||||
Tabs: Tabs.extend({
|
Tabs: Tabs.extend({
|
||||||
vars: (theme, props) => ({
|
vars: (theme, props) => ({
|
||||||
root: {
|
root: {
|
||||||
|
|||||||
+50
-50
@@ -47,29 +47,29 @@
|
|||||||
"@langchain/textsplitters": "1.0.1",
|
"@langchain/textsplitters": "1.0.1",
|
||||||
"@modelcontextprotocol/sdk": "1.29.0",
|
"@modelcontextprotocol/sdk": "1.29.0",
|
||||||
"@nest-lab/throttler-storage-redis": "^1.2.0",
|
"@nest-lab/throttler-storage-redis": "^1.2.0",
|
||||||
"@nestjs-labs/nestjs-ioredis": "^11.0.4",
|
"@nestjs-labs/nestjs-ioredis": "11.0.4",
|
||||||
"@nestjs/bullmq": "^11.0.4",
|
"@nestjs/bullmq": "11.0.4",
|
||||||
"@nestjs/cache-manager": "^3.1.0",
|
"@nestjs/cache-manager": "3.1.3",
|
||||||
"@nestjs/common": "^11.1.19",
|
"@nestjs/common": "11.1.27",
|
||||||
"@nestjs/config": "^4.0.4",
|
"@nestjs/config": "4.0.4",
|
||||||
"@nestjs/core": "^11.1.19",
|
"@nestjs/core": "11.1.27",
|
||||||
"@nestjs/event-emitter": "^3.0.1",
|
"@nestjs/event-emitter": "3.1.0",
|
||||||
"@nestjs/jwt": "11.0.2",
|
"@nestjs/jwt": "11.0.2",
|
||||||
"@nestjs/mapped-types": "^2.1.1",
|
"@nestjs/mapped-types": "2.1.1",
|
||||||
"@nestjs/passport": "^11.0.5",
|
"@nestjs/passport": "11.0.5",
|
||||||
"@nestjs/platform-fastify": "^11.1.19",
|
"@nestjs/platform-fastify": "11.1.27",
|
||||||
"@nestjs/platform-socket.io": "^11.1.19",
|
"@nestjs/platform-socket.io": "11.1.27",
|
||||||
"@nestjs/schedule": "^6.1.3",
|
"@nestjs/schedule": "6.1.3",
|
||||||
"@nestjs/terminus": "^11.1.1",
|
"@nestjs/terminus": "11.1.1",
|
||||||
"@nestjs/throttler": "^6.5.0",
|
"@nestjs/throttler": "6.5.0",
|
||||||
"@nestjs/websockets": "^11.1.19",
|
"@nestjs/websockets": "11.1.27",
|
||||||
"@node-saml/passport-saml": "^5.1.0",
|
"@node-saml/passport-saml": "5.1.0",
|
||||||
"@socket.io/redis-adapter": "^8.3.0",
|
"@socket.io/redis-adapter": "8.3.0",
|
||||||
"ai": "6.0.134",
|
"ai": "6.0.134",
|
||||||
"ai-sdk-ollama": "3.8.1",
|
"ai-sdk-ollama": "3.8.1",
|
||||||
"bcrypt": "6.0.0",
|
"bcrypt": "6.0.0",
|
||||||
"bowser": "2.14.1",
|
"bowser": "2.14.1",
|
||||||
"bullmq": "5.76.10",
|
"bullmq": "5.79.0",
|
||||||
"cache-manager": "7.2.8",
|
"cache-manager": "7.2.8",
|
||||||
"cheerio": "1.2.0",
|
"cheerio": "1.2.0",
|
||||||
"class-transformer": "0.5.1",
|
"class-transformer": "0.5.1",
|
||||||
@@ -79,49 +79,49 @@
|
|||||||
"fastify-ip": "2.0.0",
|
"fastify-ip": "2.0.0",
|
||||||
"fs-extra": "11.3.4",
|
"fs-extra": "11.3.4",
|
||||||
"happy-dom": "20.8.9",
|
"happy-dom": "20.8.9",
|
||||||
"ioredis": "^5.10.1",
|
"ioredis": "5.10.1",
|
||||||
"js-tiktoken": "^1.0.21",
|
"js-tiktoken": "1.0.21",
|
||||||
"jsonwebtoken": "^9.0.3",
|
"jsonwebtoken": "9.0.3",
|
||||||
"kysely": "^0.28.17",
|
"kysely": "0.28.17",
|
||||||
"kysely-migration-cli": "^0.4.2",
|
"kysely-migration-cli": "0.4.2",
|
||||||
"kysely-postgres-js": "^3.0.0",
|
"kysely-postgres-js": "3.0.0",
|
||||||
"ldapts": "^8.1.7",
|
"ldapts": "8.1.7",
|
||||||
"lib0": "^0.2.117",
|
"lib0": "0.2.117",
|
||||||
"mammoth": "^1.12.0",
|
"mammoth": "1.12.0",
|
||||||
"mime-types": "^3.0.2",
|
"mime-types": "3.0.2",
|
||||||
"msgpackr": "^1.11.9",
|
"msgpackr": "^1.11.9",
|
||||||
"nanoid": "5.1.7",
|
"nanoid": "5.1.7",
|
||||||
"nestjs-cls": "^6.2.0",
|
"nestjs-cls": "6.2.0",
|
||||||
"nestjs-kysely": "^3.1.2",
|
"nestjs-kysely": "3.1.2",
|
||||||
"nestjs-pino": "^4.6.1",
|
"nestjs-pino": "4.6.1",
|
||||||
"nodemailer": "^8.0.5",
|
"nodemailer": "9.0.1",
|
||||||
"openid-client": "^6.8.2",
|
"openid-client": "6.8.2",
|
||||||
"otpauth": "^9.5.0",
|
"otpauth": "9.5.0",
|
||||||
"p-limit": "^7.3.0",
|
"p-limit": "7.3.0",
|
||||||
"passport-google-oauth20": "^2.0.0",
|
"passport-google-oauth20": "2.0.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "4.0.1",
|
||||||
"pg-tsquery": "^8.4.2",
|
"pg-tsquery": "8.4.2",
|
||||||
"pgvector": "^0.2.1",
|
"pgvector": "^0.2.1",
|
||||||
"pino-http": "^11.0.0",
|
"pino-http": "11.0.0",
|
||||||
"pino-pretty": "^13.1.3",
|
"pino-pretty": "13.1.3",
|
||||||
"postgres": "^3.4.8",
|
"postgres": "3.4.8",
|
||||||
"postmark": "^4.0.7",
|
"postmark": "4.0.7",
|
||||||
"react": "19.2.7",
|
"react": "19.2.7",
|
||||||
"react-email": "6.0.8",
|
"react-email": "6.6.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "0.2.2",
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"scimmy": "1.3.5",
|
"scimmy": "1.3.5",
|
||||||
"socket.io": "^4.8.3",
|
"socket.io": "4.8.3",
|
||||||
"stripe": "^17.7.0",
|
"stripe": "^17.7.0",
|
||||||
"tlds": "1.261.0",
|
"tlds": "1.261.0",
|
||||||
"tmp-promise": "3.0.3",
|
"tmp-promise": "3.0.3",
|
||||||
"tseep": "1.3.1",
|
"tseep": "1.3.1",
|
||||||
"typesense": "^3.0.5",
|
"typesense": "3.0.5",
|
||||||
"undici": "7.24.0",
|
"undici": "7.28.0",
|
||||||
"ws": "^8.20.1",
|
"ws": "8.21.0",
|
||||||
"yauzl": "^3.2.1",
|
"yauzl": "3.2.1",
|
||||||
"zod": "^4.3.6"
|
"zod": "4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.28.0",
|
"@eslint/js": "^9.28.0",
|
||||||
|
|||||||
+35
-35
@@ -29,41 +29,41 @@
|
|||||||
"@joplin/turndown": "4.0.82",
|
"@joplin/turndown": "4.0.82",
|
||||||
"@joplin/turndown-plugin-gfm": "1.0.64",
|
"@joplin/turndown-plugin-gfm": "1.0.64",
|
||||||
"@sindresorhus/slugify": "3.0.0",
|
"@sindresorhus/slugify": "3.0.0",
|
||||||
"@tiptap/core": "3.20.4",
|
"@tiptap/core": "3.27.1",
|
||||||
"@tiptap/extension-audio": "3.20.4",
|
"@tiptap/extension-audio": "3.27.1",
|
||||||
"@tiptap/extension-code-block": "3.20.4",
|
"@tiptap/extension-code-block": "3.27.1",
|
||||||
"@tiptap/extension-collaboration": "3.20.4",
|
"@tiptap/extension-collaboration": "3.27.1",
|
||||||
"@tiptap/extension-collaboration-caret": "3.20.4",
|
"@tiptap/extension-collaboration-caret": "3.27.1",
|
||||||
"@tiptap/extension-color": "3.20.4",
|
"@tiptap/extension-color": "3.27.1",
|
||||||
"@tiptap/extension-document": "3.20.4",
|
"@tiptap/extension-document": "3.27.1",
|
||||||
"@tiptap/extension-heading": "3.20.4",
|
"@tiptap/extension-heading": "3.27.1",
|
||||||
"@tiptap/extension-highlight": "3.20.4",
|
"@tiptap/extension-highlight": "3.27.1",
|
||||||
"@tiptap/extension-history": "3.20.4",
|
"@tiptap/extension-history": "3.27.1",
|
||||||
"@tiptap/extension-image": "3.20.4",
|
"@tiptap/extension-image": "3.27.1",
|
||||||
"@tiptap/extension-link": "3.20.4",
|
"@tiptap/extension-link": "3.27.1",
|
||||||
"@tiptap/extension-list": "3.20.4",
|
"@tiptap/extension-list": "3.27.1",
|
||||||
"@tiptap/extension-placeholder": "3.20.4",
|
"@tiptap/extension-placeholder": "3.27.1",
|
||||||
"@tiptap/extension-subscript": "3.20.4",
|
"@tiptap/extension-subscript": "3.27.1",
|
||||||
"@tiptap/extension-superscript": "3.20.4",
|
"@tiptap/extension-superscript": "3.27.1",
|
||||||
"@tiptap/extension-table": "3.20.4",
|
"@tiptap/extension-table": "3.27.1",
|
||||||
"@tiptap/extension-text": "3.20.4",
|
"@tiptap/extension-text": "3.27.1",
|
||||||
"@tiptap/extension-text-align": "3.20.4",
|
"@tiptap/extension-text-align": "3.27.1",
|
||||||
"@tiptap/extension-text-style": "3.20.4",
|
"@tiptap/extension-text-style": "3.27.1",
|
||||||
"@tiptap/extension-typography": "3.20.4",
|
"@tiptap/extension-typography": "3.27.1",
|
||||||
"@tiptap/extension-unique-id": "3.20.4",
|
"@tiptap/extension-unique-id": "3.27.1",
|
||||||
"@tiptap/extension-youtube": "3.20.4",
|
"@tiptap/extension-youtube": "3.27.1",
|
||||||
"@tiptap/html": "3.20.4",
|
"@tiptap/html": "3.27.1",
|
||||||
"@tiptap/pm": "3.20.4",
|
"@tiptap/pm": "3.27.1",
|
||||||
"@tiptap/react": "3.20.4",
|
"@tiptap/react": "3.27.1",
|
||||||
"@tiptap/starter-kit": "3.20.4",
|
"@tiptap/starter-kit": "3.27.1",
|
||||||
"@tiptap/suggestion": "3.20.4",
|
"@tiptap/suggestion": "3.27.1",
|
||||||
"@tiptap/y-tiptap": "3.0.2",
|
"@tiptap/y-tiptap": "3.0.5",
|
||||||
"bytes": "3.1.2",
|
"bytes": "3.1.2",
|
||||||
"cross-env": "10.1.0",
|
"cross-env": "10.1.0",
|
||||||
"date-fns": "4.1.0",
|
"date-fns": "4.1.0",
|
||||||
"diff": "8.0.3",
|
"diff": "8.0.3",
|
||||||
"docx": "9.7.1",
|
"docx": "9.7.1",
|
||||||
"dompurify": "3.4.1",
|
"dompurify": "3.4.11",
|
||||||
"fractional-indexing-jittered": "1.0.0",
|
"fractional-indexing-jittered": "1.0.0",
|
||||||
"highlight.js": "11.11.1",
|
"highlight.js": "11.11.1",
|
||||||
"image-dimensions": "2.5.0",
|
"image-dimensions": "2.5.0",
|
||||||
@@ -102,10 +102,10 @@
|
|||||||
"prosemirror-changeset": "2.4.0",
|
"prosemirror-changeset": "2.4.0",
|
||||||
"y-prosemirror": "1.3.7",
|
"y-prosemirror": "1.3.7",
|
||||||
"glob": "13.0.6",
|
"glob": "13.0.6",
|
||||||
"ws": "8.20.1",
|
"ws": "8.21.0",
|
||||||
"dompurify": "3.4.1",
|
"dompurify": "3.4.11",
|
||||||
"tmp": "0.2.6",
|
"tmp": "0.2.7",
|
||||||
"hono": "4.12.18",
|
"hono": "4.12.25",
|
||||||
"mermaid": "11.15.0",
|
"mermaid": "11.15.0",
|
||||||
"nanoid@^3": "3.3.8",
|
"nanoid@^3": "3.3.8",
|
||||||
"socket.io-parser": "4.2.6",
|
"socket.io-parser": "4.2.6",
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
"lodash-es": "4.18.1",
|
"lodash-es": "4.18.1",
|
||||||
"lodash": "4.18.1",
|
"lodash": "4.18.1",
|
||||||
"@hono/node-server": "1.19.13",
|
"@hono/node-server": "1.19.13",
|
||||||
"undici": "7.24.0",
|
"undici": "7.28.0",
|
||||||
"ajv@^6": "6.14.0",
|
"ajv@^6": "6.14.0",
|
||||||
"ajv@^8": "8.18.0",
|
"ajv@^8": "8.18.0",
|
||||||
"underscore": "1.13.8",
|
"underscore": "1.13.8",
|
||||||
|
|||||||
Generated
+796
-1068
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user