mirror of
https://github.com/docmost/docmost.git
synced 2026-05-14 12:44:16 +08:00
Compare commits
1 Commits
feat/pagebreak
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f4af4c3fc0 |
@@ -361,6 +361,8 @@
|
|||||||
"Create block quote.": "Create block quote.",
|
"Create block quote.": "Create block quote.",
|
||||||
"Insert code snippet.": "Insert code snippet.",
|
"Insert code snippet.": "Insert code snippet.",
|
||||||
"Insert horizontal rule divider": "Insert horizontal rule divider",
|
"Insert horizontal rule divider": "Insert horizontal rule divider",
|
||||||
|
"Page break": "Page break",
|
||||||
|
"Insert a page break for printing.": "Insert a page break for printing.",
|
||||||
"Upload any image from your device.": "Upload any image from your device.",
|
"Upload any image from your device.": "Upload any image from your device.",
|
||||||
"Upload any video from your device.": "Upload any video from your device.",
|
"Upload any video from your device.": "Upload any video from your device.",
|
||||||
"Upload any audio from your device.": "Upload any audio from your device.",
|
"Upload any audio from your device.": "Upload any audio from your device.",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
IconH2,
|
IconH2,
|
||||||
IconH3,
|
IconH3,
|
||||||
IconMenu4,
|
IconMenu4,
|
||||||
|
IconPageBreak,
|
||||||
IconTypography,
|
IconTypography,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -102,6 +103,12 @@ export const BlockTypeGroup: FC<Props> = ({ editor }) => {
|
|||||||
>
|
>
|
||||||
{t("Divider")}
|
{t("Divider")}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
leftSection={<IconPageBreak size={16} />}
|
||||||
|
onClick={() => editor.chain().focus().setPageBreak().run()}
|
||||||
|
>
|
||||||
|
{t("Page break")}
|
||||||
|
</Menu.Item>
|
||||||
</Menu.Dropdown>
|
</Menu.Dropdown>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
IconTable,
|
IconTable,
|
||||||
IconTypography,
|
IconTypography,
|
||||||
IconMenu4,
|
IconMenu4,
|
||||||
|
IconPageBreak,
|
||||||
IconCalendar,
|
IconCalendar,
|
||||||
IconAppWindow,
|
IconAppWindow,
|
||||||
IconSitemap,
|
IconSitemap,
|
||||||
@@ -164,6 +165,14 @@ const CommandGroups: SlashMenuGroupedItemsType = {
|
|||||||
command: ({ editor, range }: CommandProps) =>
|
command: ({ editor, range }: CommandProps) =>
|
||||||
editor.chain().focus().deleteRange(range).setHorizontalRule().run(),
|
editor.chain().focus().deleteRange(range).setHorizontalRule().run(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Page break",
|
||||||
|
description: "Insert a page break for printing.",
|
||||||
|
searchTerms: ["page", "break", "pagebreak", "print"],
|
||||||
|
icon: IconPageBreak,
|
||||||
|
command: ({ editor, range }: CommandProps) =>
|
||||||
|
editor.chain().focus().deleteRange(range).setPageBreak().run(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Image",
|
title: "Image",
|
||||||
description: "Upload any image from your device.",
|
description: "Upload any image from your device.",
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import {
|
|||||||
Excalidraw,
|
Excalidraw,
|
||||||
Embed,
|
Embed,
|
||||||
TiptapPdf,
|
TiptapPdf,
|
||||||
|
PageBreak,
|
||||||
SearchAndReplace,
|
SearchAndReplace,
|
||||||
Mention,
|
Mention,
|
||||||
TableDndExtension,
|
TableDndExtension,
|
||||||
@@ -366,6 +367,7 @@ export const mainExtensions = [
|
|||||||
TiptapPdf.configure({
|
TiptapPdf.configure({
|
||||||
view: PdfView,
|
view: PdfView,
|
||||||
}),
|
}),
|
||||||
|
PageBreak,
|
||||||
Subpages.configure({
|
Subpages.configure({
|
||||||
view: SubpagesView,
|
view: SubpagesView,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
@import "./media.css";
|
@import "./media.css";
|
||||||
@import "./code.css";
|
@import "./code.css";
|
||||||
@import "./print.css";
|
@import "./print.css";
|
||||||
|
@import "./page-break.css";
|
||||||
@import "./find.css";
|
@import "./find.css";
|
||||||
@import "./mention.css";
|
@import "./mention.css";
|
||||||
@import "./ordered-list.css";
|
@import "./ordered-list.css";
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
.ProseMirror .page-break {
|
||||||
|
position: relative;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
border-top: 1px dashed var(--mantine-color-default-border);
|
||||||
|
height: 0;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror[contenteditable="false"] .page-break {
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror[contenteditable="false"] .page-break::after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror .page-break::after {
|
||||||
|
content: "Page break";
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
background: var(--mantine-color-body);
|
||||||
|
color: var(--mantine-color-dimmed);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror .page-break.ProseMirror-selectednode {
|
||||||
|
border-top-color: var(--mantine-primary-color-filled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.ProseMirror .page-break {
|
||||||
|
break-before: always;
|
||||||
|
page-break-before: always;
|
||||||
|
visibility: hidden;
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror .page-break::after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
TiptapVideo,
|
TiptapVideo,
|
||||||
TiptapAudio,
|
TiptapAudio,
|
||||||
TiptapPdf,
|
TiptapPdf,
|
||||||
|
PageBreak,
|
||||||
TrailingNode,
|
TrailingNode,
|
||||||
Attachment,
|
Attachment,
|
||||||
Drawio,
|
Drawio,
|
||||||
@@ -94,6 +95,7 @@ export const tiptapExtensions = [
|
|||||||
TiptapVideo,
|
TiptapVideo,
|
||||||
TiptapAudio,
|
TiptapAudio,
|
||||||
TiptapPdf,
|
TiptapPdf,
|
||||||
|
PageBreak,
|
||||||
Callout,
|
Callout,
|
||||||
Attachment,
|
Attachment,
|
||||||
CustomCodeBlock,
|
CustomCodeBlock,
|
||||||
|
|||||||
@@ -31,5 +31,6 @@ export * from "./lib/recreate-transform";
|
|||||||
export * from "./lib/columns";
|
export * from "./lib/columns";
|
||||||
export * from "./lib/status";
|
export * from "./lib/status";
|
||||||
export * from "./lib/pdf";
|
export * from "./lib/pdf";
|
||||||
|
export * from "./lib/page-break";
|
||||||
export * from "./lib/resizable-nodeview";
|
export * from "./lib/resizable-nodeview";
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./page-break";
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { mergeAttributes, Node } from "@tiptap/core";
|
||||||
|
|
||||||
|
export interface PageBreakOptions {
|
||||||
|
HTMLAttributes: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "@tiptap/core" {
|
||||||
|
interface Commands<ReturnType> {
|
||||||
|
pageBreak: {
|
||||||
|
setPageBreak: () => ReturnType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PageBreak = Node.create<PageBreakOptions>({
|
||||||
|
name: "pageBreak",
|
||||||
|
|
||||||
|
group: "block",
|
||||||
|
|
||||||
|
atom: true,
|
||||||
|
|
||||||
|
selectable: true,
|
||||||
|
|
||||||
|
addOptions() {
|
||||||
|
return {
|
||||||
|
HTMLAttributes: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseHTML() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: `div[data-type="${this.name}"]`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
renderHTML({ HTMLAttributes }) {
|
||||||
|
return [
|
||||||
|
"div",
|
||||||
|
mergeAttributes(
|
||||||
|
{ "data-type": this.name, class: "page-break" },
|
||||||
|
this.options.HTMLAttributes,
|
||||||
|
HTMLAttributes,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
addCommands() {
|
||||||
|
return {
|
||||||
|
setPageBreak:
|
||||||
|
() =>
|
||||||
|
({ chain }) =>
|
||||||
|
chain()
|
||||||
|
.insertContent({ type: this.name })
|
||||||
|
.focus()
|
||||||
|
.run(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user