feat(email): WYSIWYG template editor with variable substitution
- Add emailSubject{De,En} + emailBodyHtml{De,En} to ShopSettings
- New RichTextEditor component (TipTap) with toolbar + variable insert
- Settings UI: Email templates section per language
- email.server.ts: substitute {{var}} placeholders, fall back to defaults
- Default vars: invoiceNumber, customerName, customerFirstName, orderName,
totalGross, dueDate, companyName, ownerName
This commit is contained in:
@@ -0,0 +1,253 @@
|
|||||||
|
import { useEditor, EditorContent } from "@tiptap/react";
|
||||||
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
|
import Link from "@tiptap/extension-link";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
interface RichTextEditorProps {
|
||||||
|
/** Hidden form field name; the rendered HTML is mirrored into it. */
|
||||||
|
name: string;
|
||||||
|
/** Visible label rendered above the editor. */
|
||||||
|
label: string;
|
||||||
|
/** Initial HTML loaded into the editor. */
|
||||||
|
defaultValue?: string;
|
||||||
|
/** Optional helper text shown below the editor. */
|
||||||
|
helpText?: string;
|
||||||
|
/** Insertable variable tokens shown as quick-insert buttons. */
|
||||||
|
variables?: { token: string; label?: string }[];
|
||||||
|
/** Min editor height in px. */
|
||||||
|
minHeight?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TipTap-based WYSIWYG editor that mirrors its HTML content into a hidden
|
||||||
|
* input so the parent <Form> can submit it like any other field.
|
||||||
|
*
|
||||||
|
* Variables like {{invoiceNumber}} are inserted as plain text — the email
|
||||||
|
* renderer is responsible for substituting them at send time.
|
||||||
|
*/
|
||||||
|
export function RichTextEditor({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
defaultValue = "",
|
||||||
|
helpText,
|
||||||
|
variables = [],
|
||||||
|
minHeight = 200,
|
||||||
|
}: RichTextEditorProps) {
|
||||||
|
// TipTap calls into the DOM on init; defer mounting until after hydration
|
||||||
|
// so SSR markup matches the initial client render.
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
useEffect(() => setMounted(true), []);
|
||||||
|
|
||||||
|
const editor = useEditor({
|
||||||
|
immediatelyRender: false,
|
||||||
|
extensions: [
|
||||||
|
StarterKit.configure({
|
||||||
|
// Drop heading levels we don't need to keep the toolbar focused.
|
||||||
|
heading: { levels: [2, 3] },
|
||||||
|
}),
|
||||||
|
Link.configure({ openOnClick: false }),
|
||||||
|
],
|
||||||
|
content: defaultValue || "<p></p>",
|
||||||
|
editorProps: {
|
||||||
|
attributes: {
|
||||||
|
class: "wysiwyg-editor",
|
||||||
|
style: `min-height:${minHeight}px;padding:8px 12px;border:1px solid #c9cccf;border-top:0;border-radius:0 0 6px 6px;background:#fff;outline:none;`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Keep editor disposed cleanly on unmount.
|
||||||
|
useEffect(() => () => editor?.destroy(), [editor]);
|
||||||
|
|
||||||
|
const html = editor?.getHTML() ?? defaultValue;
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
// Server / pre-hydration fallback: a textarea so the value is still
|
||||||
|
// submittable if JS fails or before TipTap mounts.
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{label ? (
|
||||||
|
<label style={{ display: "block", fontSize: 14, fontWeight: 500, marginBottom: 6 }}>
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
) : null}
|
||||||
|
<textarea
|
||||||
|
name={name}
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
style={{ width: "100%", minHeight, padding: 8, border: "1px solid #c9cccf", borderRadius: 6 }}
|
||||||
|
/>
|
||||||
|
{helpText ? (
|
||||||
|
<div style={{ fontSize: 12, color: "#6d7175", marginTop: 4 }}>{helpText}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{label ? (
|
||||||
|
<label style={{ display: "block", fontSize: 14, fontWeight: 500, marginBottom: 6 }}>
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
) : null}
|
||||||
|
<div
|
||||||
|
role="toolbar"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
gap: 4,
|
||||||
|
padding: 6,
|
||||||
|
border: "1px solid #c9cccf",
|
||||||
|
borderRadius: "6px 6px 0 0",
|
||||||
|
background: "#f6f6f7",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleBold().run()}
|
||||||
|
active={editor?.isActive("bold") ?? false}
|
||||||
|
label="B"
|
||||||
|
title="Bold"
|
||||||
|
bold
|
||||||
|
/>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleItalic().run()}
|
||||||
|
active={editor?.isActive("italic") ?? false}
|
||||||
|
label="I"
|
||||||
|
title="Italic"
|
||||||
|
italic
|
||||||
|
/>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleStrike().run()}
|
||||||
|
active={editor?.isActive("strike") ?? false}
|
||||||
|
label="S"
|
||||||
|
title="Strikethrough"
|
||||||
|
/>
|
||||||
|
<Sep />
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().setParagraph().run()}
|
||||||
|
active={editor?.isActive("paragraph") ?? false}
|
||||||
|
label="¶"
|
||||||
|
title="Paragraph"
|
||||||
|
/>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
|
active={editor?.isActive("heading", { level: 2 }) ?? false}
|
||||||
|
label="H2"
|
||||||
|
title="Heading 2"
|
||||||
|
/>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
|
active={editor?.isActive("heading", { level: 3 }) ?? false}
|
||||||
|
label="H3"
|
||||||
|
title="Heading 3"
|
||||||
|
/>
|
||||||
|
<Sep />
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleBulletList().run()}
|
||||||
|
active={editor?.isActive("bulletList") ?? false}
|
||||||
|
label="• List"
|
||||||
|
title="Bullet list"
|
||||||
|
/>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().toggleOrderedList().run()}
|
||||||
|
active={editor?.isActive("orderedList") ?? false}
|
||||||
|
label="1. List"
|
||||||
|
title="Numbered list"
|
||||||
|
/>
|
||||||
|
<Sep />
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => {
|
||||||
|
const url = window.prompt("URL");
|
||||||
|
if (url) editor?.chain().focus().setLink({ href: url }).run();
|
||||||
|
else editor?.chain().focus().unsetLink().run();
|
||||||
|
}}
|
||||||
|
active={editor?.isActive("link") ?? false}
|
||||||
|
label="Link"
|
||||||
|
title="Insert/remove link"
|
||||||
|
/>
|
||||||
|
<Sep />
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().undo().run()}
|
||||||
|
active={false}
|
||||||
|
label="↺"
|
||||||
|
title="Undo"
|
||||||
|
/>
|
||||||
|
<ToolbarButton
|
||||||
|
onClick={() => editor?.chain().focus().redo().run()}
|
||||||
|
active={false}
|
||||||
|
label="↻"
|
||||||
|
title="Redo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<EditorContent editor={editor} />
|
||||||
|
<input type="hidden" name={name} value={html} />
|
||||||
|
{variables.length > 0 ? (
|
||||||
|
<div style={{ marginTop: 6, display: "flex", flexWrap: "wrap", gap: 4, alignItems: "center" }}>
|
||||||
|
<span style={{ fontSize: 12, color: "#6d7175", marginRight: 4 }}>Insert variable:</span>
|
||||||
|
{variables.map((v) => (
|
||||||
|
<button
|
||||||
|
key={v.token}
|
||||||
|
type="button"
|
||||||
|
onClick={() => editor?.chain().focus().insertContent(v.token).run()}
|
||||||
|
style={{
|
||||||
|
fontSize: 12,
|
||||||
|
padding: "2px 8px",
|
||||||
|
border: "1px solid #c9cccf",
|
||||||
|
borderRadius: 12,
|
||||||
|
background: "#fff",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
title={`Inserts ${v.token}`}
|
||||||
|
>
|
||||||
|
{v.label ?? v.token}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{helpText ? (
|
||||||
|
<div style={{ fontSize: 12, color: "#6d7175", marginTop: 4 }}>{helpText}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ToolbarButton({
|
||||||
|
onClick,
|
||||||
|
active,
|
||||||
|
label,
|
||||||
|
title,
|
||||||
|
bold,
|
||||||
|
italic,
|
||||||
|
}: {
|
||||||
|
onClick: () => void;
|
||||||
|
active: boolean;
|
||||||
|
label: string;
|
||||||
|
title: string;
|
||||||
|
bold?: boolean;
|
||||||
|
italic?: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onClick}
|
||||||
|
title={title}
|
||||||
|
style={{
|
||||||
|
padding: "4px 10px",
|
||||||
|
background: active ? "#e3e5e7" : "#fff",
|
||||||
|
border: "1px solid #c9cccf",
|
||||||
|
borderRadius: 4,
|
||||||
|
fontWeight: bold ? 700 : 500,
|
||||||
|
fontStyle: italic ? "italic" : "normal",
|
||||||
|
cursor: "pointer",
|
||||||
|
fontSize: 13,
|
||||||
|
minWidth: 28,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Sep() {
|
||||||
|
return <span aria-hidden style={{ width: 1, background: "#c9cccf", margin: "2px 4px" }} />;
|
||||||
|
}
|
||||||
@@ -165,8 +165,8 @@ export default function InvoicesPage() {
|
|||||||
</s-stack>
|
</s-stack>
|
||||||
|
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<s-stack direction="inline" gap="small" alignItems="center">
|
<s-stack direction="inline" gap="base" alignItems="center">
|
||||||
<s-spinner size="small" accessibilityLabel="Loading orders" />
|
<s-spinner size="base" accessibilityLabel="Loading orders" />
|
||||||
<s-text tone="neutral">Loading…</s-text>
|
<s-text tone="neutral">Loading…</s-text>
|
||||||
</s-stack>
|
</s-stack>
|
||||||
) : orders.length === 0 ? (
|
) : orders.length === 0 ? (
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
deleteStoredLogo,
|
deleteStoredLogo,
|
||||||
storeUploadedLogo,
|
storeUploadedLogo,
|
||||||
} from "../services/invoice/logoCache.server";
|
} from "../services/invoice/logoCache.server";
|
||||||
|
import { RichTextEditor } from "../components/RichTextEditor";
|
||||||
|
|
||||||
interface SettingsFieldErrors {
|
interface SettingsFieldErrors {
|
||||||
vatId?: string;
|
vatId?: string;
|
||||||
@@ -152,6 +153,10 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
|||||||
smtpFromName: str("smtpFromName"),
|
smtpFromName: str("smtpFromName"),
|
||||||
smtpFromEmail: str("smtpFromEmail"),
|
smtpFromEmail: str("smtpFromEmail"),
|
||||||
smtpReplyTo: str("smtpReplyTo"),
|
smtpReplyTo: str("smtpReplyTo"),
|
||||||
|
emailSubjectDe: str("emailSubjectDe"),
|
||||||
|
emailBodyHtmlDe: str("emailBodyHtmlDe"),
|
||||||
|
emailSubjectEn: str("emailSubjectEn"),
|
||||||
|
emailBodyHtmlEn: str("emailBodyHtmlEn"),
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.shopSettings.upsert({
|
await db.shopSettings.upsert({
|
||||||
@@ -361,6 +366,43 @@ export default function SettingsRoute() {
|
|||||||
</s-stack>
|
</s-stack>
|
||||||
</s-section>
|
</s-section>
|
||||||
|
|
||||||
|
<s-section heading="Email templates">
|
||||||
|
<s-stack direction="block" gap="base">
|
||||||
|
<s-paragraph>
|
||||||
|
These templates are used when sending the invoice PDF by email.
|
||||||
|
Leave a field empty to fall back to the built-in default.
|
||||||
|
</s-paragraph>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label="Subject (German)"
|
||||||
|
name="emailSubjectDe"
|
||||||
|
defaultValue={settings.emailSubjectDe}
|
||||||
|
helpText="Variables like {{invoiceNumber}} are substituted at send time."
|
||||||
|
/>
|
||||||
|
<RichTextEditor
|
||||||
|
name="emailBodyHtmlDe"
|
||||||
|
label="Body (German)"
|
||||||
|
defaultValue={settings.emailBodyHtmlDe}
|
||||||
|
variables={EMAIL_VARS}
|
||||||
|
minHeight={220}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label="Subject (English)"
|
||||||
|
name="emailSubjectEn"
|
||||||
|
defaultValue={settings.emailSubjectEn}
|
||||||
|
helpText="Variables like {{invoiceNumber}} are substituted at send time."
|
||||||
|
/>
|
||||||
|
<RichTextEditor
|
||||||
|
name="emailBodyHtmlEn"
|
||||||
|
label="Body (English)"
|
||||||
|
defaultValue={settings.emailBodyHtmlEn}
|
||||||
|
variables={EMAIL_VARS}
|
||||||
|
minHeight={220}
|
||||||
|
/>
|
||||||
|
</s-stack>
|
||||||
|
</s-section>
|
||||||
|
|
||||||
<s-section>
|
<s-section>
|
||||||
<s-stack direction="inline" gap="base" justifyContent="end" alignItems="center">
|
<s-stack direction="inline" gap="base" justifyContent="end" alignItems="center">
|
||||||
{isSaving ? <s-text tone="neutral">Saving…</s-text> : null}
|
{isSaving ? <s-text tone="neutral">Saving…</s-text> : null}
|
||||||
@@ -374,6 +416,17 @@ export default function SettingsRoute() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EMAIL_VARS = [
|
||||||
|
{ token: "{{invoiceNumber}}" },
|
||||||
|
{ token: "{{customerName}}" },
|
||||||
|
{ token: "{{customerFirstName}}" },
|
||||||
|
{ token: "{{orderName}}" },
|
||||||
|
{ token: "{{totalGross}}" },
|
||||||
|
{ token: "{{dueDate}}" },
|
||||||
|
{ token: "{{companyName}}" },
|
||||||
|
{ token: "{{ownerName}}" },
|
||||||
|
];
|
||||||
|
|
||||||
interface FieldProps {
|
interface FieldProps {
|
||||||
label: string;
|
label: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -63,9 +63,26 @@ export async function sendInvoiceEmail(
|
|||||||
// Build email content.
|
// Build email content.
|
||||||
const language = pickLanguage(args.customerLocale ?? settings.defaultLanguage);
|
const language = pickLanguage(args.customerLocale ?? settings.defaultLanguage);
|
||||||
const t = getStrings(language);
|
const t = getStrings(language);
|
||||||
const subject = `${t.invoice} ${invoice.invoiceNumber}` +
|
const customer = parseCustomer(invoice.customerJson);
|
||||||
|
const totals = parseTotals(invoice.totalsJson);
|
||||||
|
const vars = buildTemplateVars({
|
||||||
|
invoice,
|
||||||
|
settings,
|
||||||
|
customerName: customer.customerName ?? "",
|
||||||
|
customerFirstName: (customer.customerName ?? "").split(/\s+/)[0] ?? "",
|
||||||
|
totalGross: totals.totalGross ?? "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const customSubject = language === "en" ? settings.emailSubjectEn : settings.emailSubjectDe;
|
||||||
|
const subject = customSubject
|
||||||
|
? renderTemplate(customSubject, vars)
|
||||||
|
: `${t.invoice} ${invoice.invoiceNumber}` +
|
||||||
(settings.companyName ? ` — ${settings.companyName}` : "");
|
(settings.companyName ? ` — ${settings.companyName}` : "");
|
||||||
const body = renderEmailBody({
|
|
||||||
|
const customBodyHtml = language === "en" ? settings.emailBodyHtmlEn : settings.emailBodyHtmlDe;
|
||||||
|
const body = customBodyHtml
|
||||||
|
? renderHtmlBody(renderTemplate(customBodyHtml, vars))
|
||||||
|
: renderEmailBody({
|
||||||
settings,
|
settings,
|
||||||
invoiceNumber: invoice.invoiceNumber,
|
invoiceNumber: invoice.invoiceNumber,
|
||||||
language,
|
language,
|
||||||
@@ -203,3 +220,91 @@ function escapeHtml(s: string): string {
|
|||||||
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]!,
|
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Template variables ----------------------------------------------------
|
||||||
|
|
||||||
|
interface TemplateVars {
|
||||||
|
invoiceNumber: string;
|
||||||
|
customerName: string;
|
||||||
|
customerFirstName: string;
|
||||||
|
orderName: string;
|
||||||
|
totalGross: string;
|
||||||
|
dueDate: string;
|
||||||
|
companyName: string;
|
||||||
|
ownerName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTemplateVars(args: {
|
||||||
|
invoice: { invoiceNumber: string; orderName: string };
|
||||||
|
settings: ShopSettings;
|
||||||
|
customerName: string;
|
||||||
|
customerFirstName: string;
|
||||||
|
totalGross: string;
|
||||||
|
}): TemplateVars {
|
||||||
|
const dueMs = Number((args.invoice as unknown as { dueDate?: string | Date }).dueDate ?? 0);
|
||||||
|
return {
|
||||||
|
invoiceNumber: args.invoice.invoiceNumber,
|
||||||
|
orderName: args.invoice.orderName,
|
||||||
|
customerName: args.customerName,
|
||||||
|
customerFirstName: args.customerFirstName,
|
||||||
|
totalGross: args.totalGross,
|
||||||
|
dueDate: dueMs ? new Date(dueMs).toLocaleDateString() : "",
|
||||||
|
companyName: args.settings.companyName,
|
||||||
|
ownerName: args.settings.ownerName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Substitutes {{token}} placeholders in `template`. Unknown tokens are left
|
||||||
|
* in place so the user notices typos instead of silent blanks. Values are
|
||||||
|
* inserted verbatim — callers are responsible for HTML-escaping if needed.
|
||||||
|
*/
|
||||||
|
function renderTemplate(template: string, vars: TemplateVars): string {
|
||||||
|
return template.replace(/\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g, (full, key) => {
|
||||||
|
const v = (vars as unknown as Record<string, string | undefined>)[key];
|
||||||
|
return v === undefined ? full : v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Strips HTML tags to produce a plain-text fallback for the multipart email. */
|
||||||
|
function htmlToText(html: string): string {
|
||||||
|
return html
|
||||||
|
.replace(/<br\s*\/?>(?=\s|$)/gi, "\n")
|
||||||
|
.replace(/<\/p>/gi, "\n\n")
|
||||||
|
.replace(/<[^>]+>/g, "")
|
||||||
|
.replace(/ /g, " ")
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, "'")
|
||||||
|
.replace(/\n{3,}/g, "\n\n")
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderHtmlBody(html: string): { text: string; html: string } {
|
||||||
|
return { html, text: htmlToText(html) };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InvoiceCustomerSnapshot {
|
||||||
|
customerEmail?: string;
|
||||||
|
customerName?: string;
|
||||||
|
}
|
||||||
|
function parseCustomer(json: string): InvoiceCustomerSnapshot {
|
||||||
|
try {
|
||||||
|
return JSON.parse(json) as InvoiceCustomerSnapshot;
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InvoiceTotalsSnapshot {
|
||||||
|
totalGross?: string;
|
||||||
|
}
|
||||||
|
function parseTotals(json: string): InvoiceTotalsSnapshot {
|
||||||
|
try {
|
||||||
|
return JSON.parse(json) as InvoiceTotalsSnapshot;
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Generated
+637
-4
@@ -18,6 +18,10 @@
|
|||||||
"@shopify/app-bridge-react": "^4.2.4",
|
"@shopify/app-bridge-react": "^4.2.4",
|
||||||
"@shopify/shopify-app-react-router": "^1.1.0",
|
"@shopify/shopify-app-react-router": "^1.1.0",
|
||||||
"@shopify/shopify-app-session-storage-prisma": "^8.0.0",
|
"@shopify/shopify-app-session-storage-prisma": "^8.0.0",
|
||||||
|
"@tiptap/extension-link": "^3.23.1",
|
||||||
|
"@tiptap/pm": "^3.23.1",
|
||||||
|
"@tiptap/react": "^3.23.1",
|
||||||
|
"@tiptap/starter-kit": "^3.23.1",
|
||||||
"@types/nodemailer": "^8.0.0",
|
"@types/nodemailer": "^8.0.0",
|
||||||
"isbot": "^5.1.31",
|
"isbot": "^5.1.31",
|
||||||
"nodemailer": "^8.0.7",
|
"nodemailer": "^8.0.7",
|
||||||
@@ -1130,6 +1134,34 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@floating-ui/core": {
|
||||||
|
"version": "1.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
|
||||||
|
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/utils": "^0.2.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/dom": {
|
||||||
|
"version": "1.7.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
|
||||||
|
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/core": "^1.7.5",
|
||||||
|
"@floating-ui/utils": "^0.2.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/utils": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
|
||||||
|
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@graphql-codegen/add": {
|
"node_modules/@graphql-codegen/add": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz",
|
||||||
@@ -4132,6 +4164,434 @@
|
|||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tiptap/core": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-8YvSGiJTeU5wPuGiYIIYgyiyaaT1CAx+kJL0bju0w871OvbJJj0T/ywhcmxGXW6pOal2T8X2xt9ZqE+vib0VJw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-blockquote": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-FdVZLZOkL06j3WLXOC2UeX7++Cj3qI2vfohruMJiz4vk1Q5UUH7G4+AykFzjzBJHrdEpkiRUkRpU1KZIWdbluw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-bold": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-EAYdNzyOjlQh2VBY1EhdxtiTjVMaOAD6P0ezms60dKRjd4oj/8grfXfUqwgo4NVdFb11Ks85vXoHuXJSylfR4A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-bubble-menu": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-1advMCpPkHD/3ucZhYmNau8B4tF0L6iRAFhUOglp5bBZDuq13+rYujh3cm4vFmjH9KqThzpcUDn+ZU2c+mTMyw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/dom": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-bullet-list": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-owWnBBI4t+jqVDY0naDjhsAmrNGldh4czouef2K+mEf032B7uGsDVCwKp1qaX1JZesyYDfvXOaIwT22hNID2mw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-code": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-nGuhb4YghgTfkejwWHrD9GSpwcC5kkVmm2sN/UY4yceDw+PkyysYKJWZehRLTOC8GNgSAhq/EeQeq14Xwk6dyg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-code-block": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-BdJGqM57CsKgYrQUZz78vIG8Yn7EpsE2pA7iKn5tYoSXpYtt0IaU4qB1heH7lwWD/vVCAm0YQVD7/0F+0++yhA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-document": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-NA5Rx59HRwG6Hb6LwLpC5lE7z6vCj6f90S7RNNsnE+CyiXNR/OhY2BcjuxiGnascHvsnsAbvxGU3ymKMDgvDVg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-dropcursor": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-WRN7e/h9m3uI5j9/+L6jcPhHbTL6aKxfFfQWZHNf5M8TqSL1P+/2h034td0XMj3n48i4fWyzjVUV9+sz6t2fDw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extensions": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-floating-menu": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-XrYHpLn1DpLFSGTko9F9xgbNamL6fGpWkK4wqgwPVbg/SJwQCDO/9p5D3DtJTwD+xgw4sQ9as4O6rt6jx8JT+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@floating-ui/dom": "^1.0.0",
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-gapcursor": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-E4hB0xquUpEXy7kboLBazrFyRCsN0j0fsTFR8udgQf5xetAVPhOexSTKuzOcU/n0kxsKJin7laYYEag/Fd2KNw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extensions": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-hard-break": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-XYkCKC5RVqMmmBk+nd22/6IDDx1OC54sdStH5VEHtfOrarriO0JztK8Mr0TijPPk9N4rKXsmndYZM2xyWZZytQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-heading": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-1z9yCSp8fevgX3r/4kWXO3of0WFCQWfYjWfHANvoJ4JQTYBkARjXlj1tbk5rrAJBFDDfKRkUpZOurXKgGo+h+g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-horizontal-rule": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-30XUHXdEZxcz1FCWjz9HW2EEq06NQcAye6rXGnvHo6Y60iJ6MRsrX5byvceFNF9DTVtOIcUFBQ/psIiRcoi0KA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-italic": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-lZB9YCjoVNDoPMguya66nBvaS/2YpGN5iAcjAGx/JQkCAZeOAtl9+ALMzbWPKH6tQP6m98YtkY1T7RXr++T0bA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-link": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-uOeyLqYQI0WG62agpFG24kVHSn3Z48gD8Y0uLLJbtzh/nDFC3d9So2sQGWlSVyMzsgkJ4k/9jNnxxsVO8qgJOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"linkifyjs": "^4.3.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-list": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-v1AeXPpagslgRZdOp7WdjCoO4TjjNP8RM2R6Gqx0/inGaNXnM8zCMshOxZlAb03Ad7kq/4RGJmkpM/Jjsi6dEQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-list-item": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-Fk/884un5OSLCFxe2TbOmfp3sLMB5b76CnMjaSrvgfiaZnsV2WlJZGPXxCAPbxNIATTykNlSBsVuMBO7we64Vg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-list-keymap": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-sHbE5sxiJzhgGn94GUAzD4qKM9SyImBrOlAGS/EIe+pausjqQE7xi+YW0gRo2jG+gXhSYl4/oAGXQXzmSInSUQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-ordered-list": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-3GG7YFhVJWw/HWmRxvMMUC296x7TPBQRLsH4ryEC1SMAmVJnbTIvetyvIcLqLEXGW7Rj41S7SO8qjOXVceSOTA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-paragraph": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-GC7b6yAjASl1q9sNkPmukZmVYMfxx03EEhpMMrLYJY9GBz82Ald927yYQsOqf2aKA/Rjo/aZMYCGtjXkGk6aBA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-strike": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-+R5LG0ZW9SDZc4weA79uq6uUduVsCEph9tRcoQCRA82IVIiPYSTxTLew9odalmk/Mc7vdZvOK5jjtO5jUVw/rg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-text": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-k1Ki9bBV6mLz1mFP+Laqh1YHJ2MY0P8XzaMqpkgMndEBIJQ3XcpWQc5bfAlRnYcOI9ZXDbAgQ8CwgArxHmQWCQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-underline": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-+PvHyVozHyxJ9oWCIQx5JHBZ7LAa/sFJUOFaKyfmel4gL9AbP52MmvrciXARlZHd1WCULJtdbLan0+x5/D/9hQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extensions": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-7UIn+idaVTVhdlP0KmgzBh8Csmwck357Dq4te5DuAxhSkN1gsXHlq39mpx907UYKJdSOgd+GMFeyOziPwSmbOQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/pm": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-8G+TkNsUHHAAJYREpA6fw+Dw/m2Y3Go4/QMQM8RYepid+wTeE1wSv7sBA/CBrphhYmJSWeTyCPtgQIxnTJXMCA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-changeset": "^2.3.0",
|
||||||
|
"prosemirror-commands": "^1.6.2",
|
||||||
|
"prosemirror-dropcursor": "^1.8.1",
|
||||||
|
"prosemirror-gapcursor": "^1.3.2",
|
||||||
|
"prosemirror-history": "^1.4.1",
|
||||||
|
"prosemirror-keymap": "^1.2.2",
|
||||||
|
"prosemirror-model": "^1.24.1",
|
||||||
|
"prosemirror-schema-list": "^1.5.0",
|
||||||
|
"prosemirror-state": "^1.4.3",
|
||||||
|
"prosemirror-tables": "^1.6.4",
|
||||||
|
"prosemirror-transform": "^1.10.2",
|
||||||
|
"prosemirror-view": "^1.38.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/react": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-43zUwKOcsxRIcgiDbcEUagojhPIez2OIryaNG/uiDcRzkrUteiTu2wSJndkQqwouwh3wJEm+KOw8xybNYvU+qA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/use-sync-external-store": "^0.0.6",
|
||||||
|
"fast-equals": "^5.3.3",
|
||||||
|
"use-sync-external-store": "^1.4.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@tiptap/extension-bubble-menu": "^3.23.1",
|
||||||
|
"@tiptap/extension-floating-menu": "^3.23.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.23.1",
|
||||||
|
"@tiptap/pm": "3.23.1",
|
||||||
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/starter-kit": {
|
||||||
|
"version": "3.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.23.1.tgz",
|
||||||
|
"integrity": "sha512-CURePHQagBaZIDJrHH3of4Nmi0VYGpZ6yBlkdFxFHBxY9aeG2/h5kn+oHo8GbzkSFsRV+9olzRgDTOULVgs8pQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tiptap/core": "^3.23.1",
|
||||||
|
"@tiptap/extension-blockquote": "^3.23.1",
|
||||||
|
"@tiptap/extension-bold": "^3.23.1",
|
||||||
|
"@tiptap/extension-bullet-list": "^3.23.1",
|
||||||
|
"@tiptap/extension-code": "^3.23.1",
|
||||||
|
"@tiptap/extension-code-block": "^3.23.1",
|
||||||
|
"@tiptap/extension-document": "^3.23.1",
|
||||||
|
"@tiptap/extension-dropcursor": "^3.23.1",
|
||||||
|
"@tiptap/extension-gapcursor": "^3.23.1",
|
||||||
|
"@tiptap/extension-hard-break": "^3.23.1",
|
||||||
|
"@tiptap/extension-heading": "^3.23.1",
|
||||||
|
"@tiptap/extension-horizontal-rule": "^3.23.1",
|
||||||
|
"@tiptap/extension-italic": "^3.23.1",
|
||||||
|
"@tiptap/extension-link": "^3.23.1",
|
||||||
|
"@tiptap/extension-list": "^3.23.1",
|
||||||
|
"@tiptap/extension-list-item": "^3.23.1",
|
||||||
|
"@tiptap/extension-list-keymap": "^3.23.1",
|
||||||
|
"@tiptap/extension-ordered-list": "^3.23.1",
|
||||||
|
"@tiptap/extension-paragraph": "^3.23.1",
|
||||||
|
"@tiptap/extension-strike": "^3.23.1",
|
||||||
|
"@tiptap/extension-text": "^3.23.1",
|
||||||
|
"@tiptap/extension-underline": "^3.23.1",
|
||||||
|
"@tiptap/extensions": "^3.23.1",
|
||||||
|
"@tiptap/pm": "^3.23.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ts-morph/common": {
|
"node_modules/@ts-morph/common": {
|
||||||
"version": "0.26.1",
|
"version": "0.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.26.1.tgz",
|
||||||
@@ -4231,7 +4691,6 @@
|
|||||||
"version": "15.7.15",
|
"version": "15.7.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
||||||
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
|
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/qrcode": {
|
"node_modules/@types/qrcode": {
|
||||||
@@ -4248,7 +4707,6 @@
|
|||||||
"version": "18.3.28",
|
"version": "18.3.28",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
|
||||||
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
@@ -4259,7 +4717,6 @@
|
|||||||
"version": "18.3.7",
|
"version": "18.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
||||||
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^18.0.0"
|
"@types/react": "^18.0.0"
|
||||||
@@ -4272,6 +4729,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/use-sync-external-store": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.18.1",
|
"version": "8.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
@@ -6126,7 +6589,6 @@
|
|||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/damerau-levenshtein": {
|
"node_modules/damerau-levenshtein": {
|
||||||
@@ -7400,6 +7862,15 @@
|
|||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-equals": {
|
||||||
|
"version": "5.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz",
|
||||||
|
"integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||||
@@ -9537,6 +10008,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/linkifyjs": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/listr2": {
|
"node_modules/listr2": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz",
|
||||||
@@ -10378,6 +10855,12 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/orderedmap": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/own-keys": {
|
"node_modules/own-keys": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
|
||||||
@@ -10815,6 +11298,135 @@
|
|||||||
"react-is": "^16.13.1"
|
"react-is": "^16.13.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prosemirror-changeset": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-transform": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-commands": {
|
||||||
|
"version": "1.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz",
|
||||||
|
"integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.10.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-dropcursor": {
|
||||||
|
"version": "1.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz",
|
||||||
|
"integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.1.0",
|
||||||
|
"prosemirror-view": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-gapcursor": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-keymap": "^1.0.0",
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-history": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.2.2",
|
||||||
|
"prosemirror-transform": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.31.0",
|
||||||
|
"rope-sequence": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-keymap": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"w3c-keyname": "^2.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-model": {
|
||||||
|
"version": "1.25.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz",
|
||||||
|
"integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"orderedmap": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-schema-list": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-state": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.27.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-tables": {
|
||||||
|
"version": "1.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz",
|
||||||
|
"integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-keymap": "^1.2.3",
|
||||||
|
"prosemirror-model": "^1.25.4",
|
||||||
|
"prosemirror-state": "^1.4.4",
|
||||||
|
"prosemirror-transform": "^1.10.5",
|
||||||
|
"prosemirror-view": "^1.41.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-transform": {
|
||||||
|
"version": "1.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.0.tgz",
|
||||||
|
"integrity": "sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-view": {
|
||||||
|
"version": "1.41.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.8.tgz",
|
||||||
|
"integrity": "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.20.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@@ -11392,6 +12004,12 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rope-sequence": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/run-async": {
|
"node_modules/run-async": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||||
@@ -13128,6 +13746,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/use-sync-external-store": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@@ -13301,6 +13928,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/w3c-keyname": {
|
||||||
|
"version": "2.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||||
|
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/wcwidth": {
|
"node_modules/wcwidth": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||||
|
|||||||
@@ -33,6 +33,10 @@
|
|||||||
"@shopify/app-bridge-react": "^4.2.4",
|
"@shopify/app-bridge-react": "^4.2.4",
|
||||||
"@shopify/shopify-app-react-router": "^1.1.0",
|
"@shopify/shopify-app-react-router": "^1.1.0",
|
||||||
"@shopify/shopify-app-session-storage-prisma": "^8.0.0",
|
"@shopify/shopify-app-session-storage-prisma": "^8.0.0",
|
||||||
|
"@tiptap/extension-link": "^3.23.1",
|
||||||
|
"@tiptap/pm": "^3.23.1",
|
||||||
|
"@tiptap/react": "^3.23.1",
|
||||||
|
"@tiptap/starter-kit": "^3.23.1",
|
||||||
"@types/nodemailer": "^8.0.0",
|
"@types/nodemailer": "^8.0.0",
|
||||||
"isbot": "^5.1.31",
|
"isbot": "^5.1.31",
|
||||||
"nodemailer": "^8.0.7",
|
"nodemailer": "^8.0.7",
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
-- RedefineTables
|
||||||
|
PRAGMA defer_foreign_keys=ON;
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_ShopSettings" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"shopDomain" TEXT NOT NULL,
|
||||||
|
"companyName" TEXT NOT NULL DEFAULT '',
|
||||||
|
"legalForm" TEXT NOT NULL DEFAULT '',
|
||||||
|
"ownerName" TEXT NOT NULL DEFAULT '',
|
||||||
|
"addressLine1" TEXT NOT NULL DEFAULT '',
|
||||||
|
"addressLine2" TEXT NOT NULL DEFAULT '',
|
||||||
|
"postalCode" TEXT NOT NULL DEFAULT '',
|
||||||
|
"city" TEXT NOT NULL DEFAULT '',
|
||||||
|
"countryCode" TEXT NOT NULL DEFAULT 'AT',
|
||||||
|
"phone" TEXT NOT NULL DEFAULT '',
|
||||||
|
"email" TEXT NOT NULL DEFAULT '',
|
||||||
|
"website" TEXT NOT NULL DEFAULT '',
|
||||||
|
"vatId" TEXT NOT NULL DEFAULT '',
|
||||||
|
"taxNumber" TEXT NOT NULL DEFAULT '',
|
||||||
|
"registrationNo" TEXT NOT NULL DEFAULT '',
|
||||||
|
"registrationCourt" TEXT NOT NULL DEFAULT '',
|
||||||
|
"bankName" TEXT NOT NULL DEFAULT '',
|
||||||
|
"iban" TEXT NOT NULL DEFAULT '',
|
||||||
|
"bic" TEXT NOT NULL DEFAULT '',
|
||||||
|
"giroCodeEnabled" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"numberingMode" TEXT NOT NULL DEFAULT 'shopify_order_number',
|
||||||
|
"invoicePrefix" TEXT NOT NULL DEFAULT 'RE-',
|
||||||
|
"invoiceSeed" INTEGER NOT NULL DEFAULT 1000,
|
||||||
|
"defaultLanguage" TEXT NOT NULL DEFAULT 'de',
|
||||||
|
"paymentTermDays" INTEGER NOT NULL DEFAULT 14,
|
||||||
|
"footerNote" TEXT NOT NULL DEFAULT '',
|
||||||
|
"footerNoteEn" TEXT NOT NULL DEFAULT '',
|
||||||
|
"kleinunternehmer" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"logoUrl" TEXT NOT NULL DEFAULT '',
|
||||||
|
"smtpHost" TEXT NOT NULL DEFAULT '',
|
||||||
|
"smtpPort" INTEGER NOT NULL DEFAULT 587,
|
||||||
|
"smtpSecure" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"smtpUser" TEXT NOT NULL DEFAULT '',
|
||||||
|
"smtpPassword" TEXT NOT NULL DEFAULT '',
|
||||||
|
"smtpFromName" TEXT NOT NULL DEFAULT '',
|
||||||
|
"smtpFromEmail" TEXT NOT NULL DEFAULT '',
|
||||||
|
"smtpReplyTo" TEXT NOT NULL DEFAULT '',
|
||||||
|
"emailSubjectDe" TEXT NOT NULL DEFAULT '',
|
||||||
|
"emailBodyHtmlDe" TEXT NOT NULL DEFAULT '',
|
||||||
|
"emailSubjectEn" TEXT NOT NULL DEFAULT '',
|
||||||
|
"emailBodyHtmlEn" TEXT NOT NULL DEFAULT '',
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_ShopSettings" ("addressLine1", "addressLine2", "bankName", "bic", "city", "companyName", "countryCode", "createdAt", "defaultLanguage", "email", "footerNote", "footerNoteEn", "giroCodeEnabled", "iban", "id", "invoicePrefix", "invoiceSeed", "kleinunternehmer", "legalForm", "logoUrl", "numberingMode", "ownerName", "paymentTermDays", "phone", "postalCode", "registrationCourt", "registrationNo", "shopDomain", "smtpFromEmail", "smtpFromName", "smtpHost", "smtpPassword", "smtpPort", "smtpReplyTo", "smtpSecure", "smtpUser", "taxNumber", "updatedAt", "vatId", "website") SELECT "addressLine1", "addressLine2", "bankName", "bic", "city", "companyName", "countryCode", "createdAt", "defaultLanguage", "email", "footerNote", "footerNoteEn", "giroCodeEnabled", "iban", "id", "invoicePrefix", "invoiceSeed", "kleinunternehmer", "legalForm", "logoUrl", "numberingMode", "ownerName", "paymentTermDays", "phone", "postalCode", "registrationCourt", "registrationNo", "shopDomain", "smtpFromEmail", "smtpFromName", "smtpHost", "smtpPassword", "smtpPort", "smtpReplyTo", "smtpSecure", "smtpUser", "taxNumber", "updatedAt", "vatId", "website" FROM "ShopSettings";
|
||||||
|
DROP TABLE "ShopSettings";
|
||||||
|
ALTER TABLE "new_ShopSettings" RENAME TO "ShopSettings";
|
||||||
|
CREATE UNIQUE INDEX "ShopSettings_shopDomain_key" ON "ShopSettings"("shopDomain");
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
PRAGMA defer_foreign_keys=OFF;
|
||||||
@@ -93,6 +93,12 @@ model ShopSettings {
|
|||||||
smtpFromEmail String @default("")
|
smtpFromEmail String @default("")
|
||||||
smtpReplyTo String @default("")
|
smtpReplyTo String @default("")
|
||||||
|
|
||||||
|
// Email templates (HTML, with {{var}} placeholders). Empty = use defaults.
|
||||||
|
emailSubjectDe String @default("")
|
||||||
|
emailBodyHtmlDe String @default("")
|
||||||
|
emailSubjectEn String @default("")
|
||||||
|
emailBodyHtmlEn String @default("")
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user