From 3a35cc45a5ce35b165b7d5c1079b2ddbb92b1177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BA=A6=E9=A6=99=E7=BC=98?= <461023633@qq.com> Date: Sat, 21 Dec 2024 20:15:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AD=97=E4=BD=93=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/index.ts | 12 +++ src/components/menus/MenuButton.ts | 19 +++- .../menus/common/FontSizeDecrease.ts | 82 ++++++++++++++++ .../menus/common/FontSizeIncrease.ts | 82 ++++++++++++++++ src/components/menus/toolbar/Classic.ts | 31 +++++++ src/components/menus/toolbar/Ribbon.ts | 37 +++++++- .../menus/toolbar/base/FontFamily.ts | 93 +++++++++++++++++++ src/components/menus/toolbar/base/FontSize.ts | 92 ++++++++++++++++++ src/core/UAIExtensions.ts | 8 ++ src/extensions/FontSize.ts | 69 ++++++++++++++ 10 files changed, 523 insertions(+), 2 deletions(-) create mode 100644 src/components/menus/common/FontSizeDecrease.ts create mode 100644 src/components/menus/common/FontSizeIncrease.ts create mode 100644 src/components/menus/toolbar/base/FontFamily.ts create mode 100644 src/components/menus/toolbar/base/FontSize.ts create mode 100644 src/extensions/FontSize.ts diff --git a/src/components/index.ts b/src/components/index.ts index b4b7d68..ab24aef 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -11,11 +11,17 @@ import { Classic } from "./menus/toolbar/Classic.ts"; import { ScrollableDiv } from "./menus/toolbar/ScrollableDiv.ts"; import { MenuButton } from "./menus/MenuButton.ts"; +import { FontSizeIncrease } from "./menus/common/FontSizeIncrease.ts"; +import { FontSizeDecrease } from "./menus/common/FontSizeDecrease.ts"; + import { Undo } from "./menus/toolbar/base/Undo.ts"; import { Redo } from "./menus/toolbar/base/Redo.ts"; import { FormatPainter } from "./menus/toolbar/base/FormatPainter.ts"; import { ClearFormat } from "./menus/toolbar/base/ClearFormat.ts"; +import { FontFamily } from "./menus/toolbar/base/FontFamily.ts"; +import { FontSize } from "./menus/toolbar/base/FontSize.ts"; + // 注册组件 defineCustomElement('uai-editor-header', Header); defineCustomElement('uai-editor-editor', Editor); @@ -27,7 +33,13 @@ defineCustomElement('uai-editor-classic-menu', Classic); defineCustomElement('uai-editor-scrollable-div', ScrollableDiv); defineCustomElement('uai-editor-menu-button', MenuButton); +defineCustomElement('uai-editor-common-menu-font-size-increase', FontSizeIncrease); +defineCustomElement('uai-editor-common-menu-font-size-decrease', FontSizeDecrease); + defineCustomElement('uai-editor-base-menu-undo', Undo); defineCustomElement('uai-editor-base-menu-redo', Redo); defineCustomElement('uai-editor-base-menu-format-painter', FormatPainter); defineCustomElement('uai-editor-base-menu-clear-format', ClearFormat); + +defineCustomElement('uai-editor-base-menu-font-family', FontFamily); +defineCustomElement('uai-editor-base-menu-font-size', FontSize); diff --git a/src/components/menus/MenuButton.ts b/src/components/menus/MenuButton.ts index f9a7397..61d5320 100644 --- a/src/components/menus/MenuButton.ts +++ b/src/components/menus/MenuButton.ts @@ -9,7 +9,7 @@ import tippy, { Instance, Props } from "tippy.js"; * 菜单按钮选项 */ export type MenuButtonOptions = { - menuType: "button", + menuType: "button" | "select", enable: boolean, className?: string, header?: "ribbon" | "classic", @@ -55,6 +55,10 @@ export class MenuButton extends HTMLElement implements UAIEditorEventListener { // 按钮 this.createMenuButton() } + if (this.menuButtonOptions.menuType === "select") { + // 下拉选择 + this.createMenuSelect() + } // 提示信息 var tipsContent = this.menuButtonOptions.tooltip; @@ -129,4 +133,17 @@ export class MenuButton extends HTMLElement implements UAIEditorEventListener { this.menuButtonContent.appendChild(menuButtonText); } } + + /** + * 创建下拉选择框 + */ + createMenuSelect() { + this.menuButton = document.createElement("div"); + this.menuButton.classList.add("uai-menu-button"); + this.container.appendChild(this.menuButton); + + this.menuButtonContent = document.createElement("select"); + this.menuButtonContent.classList.add("uai-button-content"); + this.menuButton.appendChild(this.menuButtonContent); + } } \ No newline at end of file diff --git a/src/components/menus/common/FontSizeDecrease.ts b/src/components/menus/common/FontSizeDecrease.ts new file mode 100644 index 0000000..01d9628 --- /dev/null +++ b/src/components/menus/common/FontSizeDecrease.ts @@ -0,0 +1,82 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../MenuButton.ts"; +import icon from "../../../assets/icons/font-size-decrease.svg"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions } from "../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 公共菜单:减小字号 + */ +export class FontSizeDecrease extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "button", + enable: true, + icon: icon, + hideText: true, + text: t('base.fontSize.decrease'), + tooltip: t('base.fontSize.decrease'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.appendChild(this.menuButton); + + // 定义按钮点击事件,设置减小字号 + this.addEventListener("click", () => { + if (this.menuButtonOptions.enable) { + // 获取当前字号 + var fontSize = event.editor.getAttributes('textStyle').fontSize; + if (fontSize) { + const size = options.dicts?.fontSizes?.find(({ value }) => value === fontSize); + if (!size) { + return; + } + // 获取比当前字号小的字号 + const nextFont = options.dicts?.fontSizes?.find(({ order }) => order === +size.order - 1); + if (nextFont) { + event.editor.chain().focus().setFontSize(nextFont.value).run(); + } + } else { + event.editor.chain().focus().setFontSize("12pt").run(); + } + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/components/menus/common/FontSizeIncrease.ts b/src/components/menus/common/FontSizeIncrease.ts new file mode 100644 index 0000000..8869fdc --- /dev/null +++ b/src/components/menus/common/FontSizeIncrease.ts @@ -0,0 +1,82 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../MenuButton.ts"; +import icon from "../../../assets/icons/font-size-increase.svg"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions } from "../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 公共菜单:增大字号 + */ +export class FontSizeIncrease extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "button", + enable: true, + icon: icon, + hideText: true, + text: t('base.fontSize.increase'), + tooltip: t('base.fontSize.increase'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.appendChild(this.menuButton); + + // 定义按钮点击事件,设置增大字号 + this.addEventListener("click", () => { + if (this.menuButtonOptions.enable) { + // 获取当前字号 + var fontSize = event.editor.getAttributes('textStyle').fontSize; + if (fontSize) { + const size = options.dicts?.fontSizes?.find(({ value }) => value === fontSize); + if (!size) { + return; + } + // 获取比当前字号大的字号 + const nextFont = options.dicts?.fontSizes?.find(({ order }) => order === +size.order + 1); + if (nextFont) { + event.editor.chain().focus().setFontSize(nextFont.value).run(); + } + } else { + event.editor.chain().focus().setFontSize("18px").run(); + } + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/components/menus/toolbar/Classic.ts b/src/components/menus/toolbar/Classic.ts index 47eb8fe..98cf127 100644 --- a/src/components/menus/toolbar/Classic.ts +++ b/src/components/menus/toolbar/Classic.ts @@ -7,11 +7,17 @@ import { UAIEditorEventListener, UAIEditorOptions } from "../../../core/UAIEdito import menuIcon from "../../../assets/icons/menu.svg"; import { ScrollableDiv } from "./ScrollableDiv"; +import { FontSizeIncrease } from "../common/FontSizeIncrease.ts"; +import { FontSizeDecrease } from "../common/FontSizeDecrease.ts"; + import { Redo } from "./base/Redo"; import { Undo } from "./base/Undo"; import { FormatPainter } from "./base/FormatPainter"; import { ClearFormat } from "./base/ClearFormat"; +import { FontFamily } from "./base/FontFamily"; +import { FontSize } from "./base/FontSize"; + /** * 传统菜单栏 */ @@ -33,6 +39,11 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { baseMenuFormatPainter!: FormatPainter; baseMenuClearFormat!: ClearFormat; + baseMenuFontFamily!: FontFamily; + baseMenuFontSize!: FontSize; + baseMenuFontSizeIncrease!: FontSizeIncrease; + baseMenuFontSizeDecrease!: FontSizeDecrease; + constructor(defaultToolbarMenus: Record[]) { super(); this.defaultToolbarMenus = defaultToolbarMenus; @@ -118,6 +129,18 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { this.baseMenuClearFormat = new ClearFormat({ menuType: "button", enable: true }); this.eventComponents.push(this.baseMenuClearFormat); + + this.baseMenuFontFamily = new FontFamily({ menuType: "select", enable: true }); + this.eventComponents.push(this.baseMenuFontFamily); + + this.baseMenuFontSize = new FontSize({ menuType: "select", enable: true }); + this.eventComponents.push(this.baseMenuFontSize); + + this.baseMenuFontSizeIncrease = new FontSizeIncrease({ menuType: "button", enable: true }); + this.eventComponents.push(this.baseMenuFontSizeIncrease); + + this.baseMenuFontSizeDecrease = new FontSizeDecrease({ menuType: "button", enable: true }); + this.eventComponents.push(this.baseMenuFontSizeDecrease); } /** * 创建基础菜单 @@ -139,5 +162,13 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { group1.appendChild(this.baseMenuRedo); group1.appendChild(this.baseMenuFormatPainter); group1.appendChild(this.baseMenuClearFormat); + + const group2 = document.createElement("div"); + group2.classList.add("uai-classic-virtual-group"); + this.classicMenuBaseGroup.appendChild(group2); + group2.appendChild(this.baseMenuFontFamily); + group2.appendChild(this.baseMenuFontSize); + group2.appendChild(this.baseMenuFontSizeIncrease); + group2.appendChild(this.baseMenuFontSizeDecrease); } } \ No newline at end of file diff --git a/src/components/menus/toolbar/Ribbon.ts b/src/components/menus/toolbar/Ribbon.ts index 5168c3b..ca78754 100644 --- a/src/components/menus/toolbar/Ribbon.ts +++ b/src/components/menus/toolbar/Ribbon.ts @@ -7,12 +7,18 @@ import { UAIEditorEventListener, UAIEditorOptions } from "../../../core/UAIEdito import { t } from "i18next"; import { ScrollableDiv } from "./ScrollableDiv"; +import { FontSizeIncrease } from "../common/FontSizeIncrease.ts"; +import { FontSizeDecrease } from "../common/FontSizeDecrease.ts"; + import { Redo } from "./base/Redo"; import { Undo } from "./base/Undo"; import { FormatPainter } from "./base/FormatPainter"; import { ClearFormat } from "./base/ClearFormat"; +import { FontFamily } from "./base/FontFamily"; +import { FontSize } from "./base/FontSize"; + /** * 经典菜单栏 */ @@ -32,10 +38,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { // 基础菜单 baseMenuUndo!: Undo; baseMenuRedo!: Redo; - baseMenuFormatPainter!: FormatPainter; baseMenuClearFormat!: ClearFormat; + baseMenuFontFamily!: FontFamily; + baseMenuFontSize!: FontSize; + baseMenuFontSizeIncrease!: FontSizeIncrease; + baseMenuFontSizeDecrease!: FontSizeDecrease; + constructor(defaultToolbarMenus: Record[]) { super(); this.defaultToolbarMenus = defaultToolbarMenus; @@ -141,6 +151,18 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { this.baseMenuClearFormat = new ClearFormat({ menuType: "button", enable: true }); this.eventComponents.push(this.baseMenuClearFormat); + + this.baseMenuFontFamily = new FontFamily({ menuType: "select", enable: true }); + this.eventComponents.push(this.baseMenuFontFamily); + + this.baseMenuFontSize = new FontSize({ menuType: "select", enable: true }); + this.eventComponents.push(this.baseMenuFontSize); + + this.baseMenuFontSizeIncrease = new FontSizeIncrease({ menuType: "button", enable: true }); + this.eventComponents.push(this.baseMenuFontSizeIncrease); + + this.baseMenuFontSizeDecrease = new FontSizeDecrease({ menuType: "button", enable: true }); + this.eventComponents.push(this.baseMenuFontSizeDecrease); } /** @@ -171,5 +193,18 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { group1.appendChild(group1row2); group1row2.appendChild(this.baseMenuFormatPainter); group1row2.appendChild(this.baseMenuClearFormat); + + const group2 = document.createElement("div"); + group2.classList.add("uai-ribbon-virtual-group"); + this.ribbonMenuBaseGroup.appendChild(group2); + + const group2row1 = document.createElement("div"); + group2row1.classList.add("uai-ribbon-virtual-group-row"); + group2.appendChild(group2row1); + group2row1.appendChild(this.baseMenuFontFamily); + group2row1.appendChild(this.baseMenuFontSize); + group2row1.appendChild(this.baseMenuFontSizeIncrease); + group2row1.appendChild(this.baseMenuFontSizeDecrease); + } } \ No newline at end of file diff --git a/src/components/menus/toolbar/base/FontFamily.ts b/src/components/menus/toolbar/base/FontFamily.ts new file mode 100644 index 0000000..c9b4269 --- /dev/null +++ b/src/components/menus/toolbar/base/FontFamily.ts @@ -0,0 +1,93 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions } from "../../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 基础菜单:设置字体 + */ +export class FontFamily extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "select", + enable: true, + hideText: true, + text: t('base.fontFamily.text'), + tooltip: t('base.fontFamily.text'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.menuButton.container.classList.add("uai-editor-menu-select"); + this.menuButton.menuButtonContent.style.fontSize = "11px"; + this.menuButton.menuButtonContent.style.width = "125px"; + // 设置可选字体 + options.dicts?.fontFamilies?.forEach(font => { + const option = document.createElement("option"); + option.label = font.label; + option.value = `${font.value}`; + (this.menuButton.menuButtonContent as HTMLSelectElement).options.add(option); + }) + this.appendChild(this.menuButton); + + // 定义按钮点击事件,设置当前内容的字体 + this.addEventListener("change", (e: Event) => { + if (this.menuButtonOptions.enable) { + const fontFamily = (e.target as HTMLSelectElement).value; + if (fontFamily === "") { + event.editor.chain().focus().unsetFontFamily().run(); + } else { + event.editor.chain().focus().setFontFamily(fontFamily).run(); + } + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + if (this.menuButton.menuButtonContent && this.menuButtonOptions.enable) { + var fontFamily = event.editor.getAttributes('textStyle').fontFamily; + // 清除所有选项的选中状态 + (this.menuButton.menuButtonContent as HTMLSelectElement).querySelectorAll("option").forEach(option => { + option.selected = false; + }); + // 设置指定值的选项为选中状态 + const optionToSelect = (this.menuButton.menuButtonContent as HTMLSelectElement).querySelector(`option[value="${fontFamily}"]`) as HTMLOptionElement; + if (optionToSelect) { + optionToSelect.selected = true; + } + } + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/components/menus/toolbar/base/FontSize.ts b/src/components/menus/toolbar/base/FontSize.ts new file mode 100644 index 0000000..6bd5dd8 --- /dev/null +++ b/src/components/menus/toolbar/base/FontSize.ts @@ -0,0 +1,92 @@ +// Copyright (c) 2024-present AI-Labs + +import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions } from "../../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 基础菜单:设置字号 + */ +export class FontSize extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "select", + enable: true, + hideText: true, + text: t('base.fontSize.text'), + tooltip: t('base.fontSize.text'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.menuButton.container.classList.add("uai-editor-menu-select"); + this.menuButton.menuButtonContent.style.fontSize = "11px"; + this.menuButton.menuButtonContent.style.width = "65px"; + // 设置可选字号 + options.dicts?.fontSizes?.forEach(font => { + const option = document.createElement("option"); + option.label = `${font.label}`; + option.value = `${font.value}`; + (this.menuButton.menuButtonContent as HTMLSelectElement).options.add(option); + }) + this.appendChild(this.menuButton); + + // 定义按钮点击事件,设置当前内容的字号 + this.addEventListener("change", (e: Event) => { + if (this.menuButtonOptions.enable) { + const fontSize = (e.target as HTMLSelectElement).value; + if (fontSize === "") { + event.editor.chain().focus().unsetFontSize().run(); + } else { + event.editor.chain().focus().setFontSize(fontSize).run(); + } + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + if (this.menuButton.menuButtonContent && this.menuButtonOptions.enable) { + var fontSize = event.editor.getAttributes('textStyle').fontSize; + // 清除所有选项的选中状态 + (this.menuButton.menuButtonContent as HTMLSelectElement).querySelectorAll("option").forEach(option => { + option.selected = false; + }); + // 设置指定值的选项为选中状态 + const optionToSelect = (this.menuButton.menuButtonContent as HTMLSelectElement).querySelector(`option[value="${fontSize}"]`) as HTMLOptionElement; + if (optionToSelect) { + optionToSelect.selected = true; + } + } + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/core/UAIExtensions.ts b/src/core/UAIExtensions.ts index 4308cf9..0f10d1f 100644 --- a/src/core/UAIExtensions.ts +++ b/src/core/UAIExtensions.ts @@ -5,7 +5,10 @@ import { Extensions } from "@tiptap/core"; import { UAIEditor, UAIEditorOptions } from "./UAIEditor"; import { StarterKit } from "@tiptap/starter-kit"; +import { FontFamily } from "@tiptap/extension-font-family"; +import { TextStyle } from "@tiptap/extension-text-style"; +import FontSize from "../extensions/FontSize.ts"; /** * 定义编辑器的所有自定义扩展组件 @@ -19,6 +22,11 @@ export const allExtensions = (uaiEditor: UAIEditor, _options: UAIEditorOptions): bulletList: false, orderedList: false, }), + FontFamily, + FontSize.configure({ + + }), + TextStyle, ]; return extensions; diff --git a/src/extensions/FontSize.ts b/src/extensions/FontSize.ts new file mode 100644 index 0000000..cd40ebb --- /dev/null +++ b/src/extensions/FontSize.ts @@ -0,0 +1,69 @@ +// Copyright (c) 2024-present AI-Labs + +import { Extension } from '@tiptap/core' + +export interface FontSizeOptions { + types: string[] + defaultFontSize: string +} + +declare module '@tiptap/core' { + interface Commands { + setFontSize: { + /** + * 设置字体大小 + */ + setFontSize: (fontSize: any) => ReturnType + } + unsetFontSize: { + /** + * 取消字体大小设置 + */ + unsetFontSize: () => ReturnType + } + } +} + +export default Extension.create({ + name: 'fontSize', + addOptions() { + return { + types: ['textStyle'], + defaultFontSize: '14px', + } + }, + addGlobalAttributes() { + return [ + { + types: this.options.types, + attributes: { + fontSize: { + default: this.options.defaultFontSize, + parseHTML: (element) => + element.style.fontSize || this.options.defaultFontSize, + renderHTML: (attributes) => { + if (attributes.fontSize === this.options.defaultFontSize) { + return {} + } + return { style: `font-size: ${attributes.fontSize}` } + }, + }, + }, + }, + ] + }, + addCommands() { + return { + setFontSize: + (fontSize) => + ({ chain }) => { + return chain().setMark('textStyle', { fontSize }).run() + }, + unsetFontSize: + () => + ({ chain }) => { + return chain().setMark('textStyle', { fontSize: null }).removeEmptyTextStyle().run() + }, + } + }, +})