68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
import { Extension } from "@tiptap/core";
|
|
|
|
const allowedFonts = [
|
|
"Inter",
|
|
"ui-sans-serif",
|
|
"ui-serif",
|
|
"ui-monospace",
|
|
] as const;
|
|
|
|
export type AllowedFontFamily = (typeof allowedFonts)[number];
|
|
|
|
declare module "@tiptap/core" {
|
|
interface Commands<ReturnType> {
|
|
fontFamily: {
|
|
setFontFamily: (fontFamily: string) => ReturnType;
|
|
unsetFontFamily: () => ReturnType;
|
|
};
|
|
}
|
|
}
|
|
|
|
export const FontFamily = Extension.create({
|
|
name: "fontFamily",
|
|
|
|
addGlobalAttributes() {
|
|
return [
|
|
{
|
|
types: ["textStyle"],
|
|
attributes: {
|
|
fontFamily: {
|
|
default: null,
|
|
parseHTML: (element) => {
|
|
const raw = (element as HTMLElement).style.fontFamily;
|
|
if (!raw) return null;
|
|
// Normalize: remove quotes and take first family only
|
|
const first = raw.split(",")[0]?.trim().replace(/^["']|["']$/g, "");
|
|
if (!first) return null;
|
|
return first;
|
|
},
|
|
renderHTML: (attributes) => {
|
|
const fontFamily = attributes.fontFamily as string | null;
|
|
if (!fontFamily) return {};
|
|
if (!allowedFonts.includes(fontFamily as AllowedFontFamily)) return {};
|
|
return { style: `font-family: ${fontFamily}` };
|
|
},
|
|
},
|
|
},
|
|
},
|
|
];
|
|
},
|
|
|
|
addCommands() {
|
|
return {
|
|
setFontFamily:
|
|
(fontFamily: string) =>
|
|
({ chain }) => {
|
|
if (!allowedFonts.includes(fontFamily as AllowedFontFamily)) return false;
|
|
return chain().setMark("textStyle", { fontFamily }).run();
|
|
},
|
|
unsetFontFamily:
|
|
() =>
|
|
({ chain }) => {
|
|
return chain().setMark("textStyle", { fontFamily: null }).removeEmptyTextStyle().run();
|
|
},
|
|
};
|
|
},
|
|
});
|
|
|