diff --git a/packages/docs/docs/packages/heading.mdx b/packages/docs/docs/packages/heading.mdx index 3adebb1d..21ac9710 100644 --- a/packages/docs/docs/packages/heading.mdx +++ b/packages/docs/docs/packages/heading.mdx @@ -56,6 +56,8 @@ const schema = new Schema({ ...edimParagraphNodes(), ...edimHeadingNodes({ nodeName: 'heading', + allowAlign: true, + levels: [2, 4, 6], }), }, }); @@ -84,6 +86,7 @@ const plugins: Plugin[] = [ }), ...edimCorePlugins(), ]; + const view = new EditorView(document.querySelector('#editor'), { state: EditorState.create({ schema: schema, diff --git a/packages/docs/src/components/examples/packages/heading.tsx b/packages/docs/src/components/examples/packages/heading.tsx index 9e08a456..dacb6135 100644 --- a/packages/docs/src/components/examples/packages/heading.tsx +++ b/packages/docs/src/components/examples/packages/heading.tsx @@ -25,6 +25,8 @@ const schema = new Schema({ ...edimParagraphNodes(), ...edimHeadingNodes({ nodeName: 'heading', + allowAlign: true, + levels: [2, 4, 6], }), }, }); diff --git a/packages/font-family/src/schemas/font-family.ts b/packages/font-family/src/schemas/font-family.ts index f7ea2489..85ae124d 100644 --- a/packages/font-family/src/schemas/font-family.ts +++ b/packages/font-family/src/schemas/font-family.ts @@ -61,7 +61,6 @@ export const edimFontFamilyMarks = ( acc[font.fontFamily] = font; return acc; }, {}); - console.log(fontByNames); const markSpec: EdimFontFamilyMarkSpec = { fonts: mergedConfigs.fonts, @@ -82,7 +81,6 @@ export const edimFontFamilyMarks = ( } if (mergedConfigs.fonts && !fontByNames[fontFamily]) { - console.log('false'); return false; } return { diff --git a/packages/heading/src/plugins/heading.ts b/packages/heading/src/plugins/heading.ts index 7f8a1c0b..3d6afe28 100644 --- a/packages/heading/src/plugins/heading.ts +++ b/packages/heading/src/plugins/heading.ts @@ -4,7 +4,6 @@ import { NodeType } from 'prosemirror-model'; export interface EdimHeadingPluginConfigs { nodeType: NodeType; - level?: number; } export const edimHeadingPlugins = (configs: EdimHeadingPluginConfigs) => { diff --git a/packages/heading/src/plugins/input-rules.ts b/packages/heading/src/plugins/input-rules.ts index 26b23535..ae849d8c 100644 --- a/packages/heading/src/plugins/input-rules.ts +++ b/packages/heading/src/plugins/input-rules.ts @@ -1,22 +1,22 @@ import { Plugin as PMPlugin } from 'prosemirror-state'; import { NodeType } from 'prosemirror-model'; import { inputRules, textblockTypeInputRule } from 'prosemirror-inputrules'; -import { EDIM_DEFAULT_HEADING_LEVEL } from '../schemas'; +import { EdimHeadingNodeSpec } from '../schemas'; export interface EdimHeadingInputRulePluginConfigs { nodeType: NodeType; - level?: number; } export const edimHeadingInputRulePlugins = ( configs: EdimHeadingInputRulePluginConfigs, ): PMPlugin[] => { - const level = configs?.level || EDIM_DEFAULT_HEADING_LEVEL; + const levels = (configs.nodeType.spec as EdimHeadingNodeSpec).meta.levels; + const levelRegex = levels.map((level) => `#{${level}}`).join('|'); return [ inputRules({ rules: [ textblockTypeInputRule( - new RegExp('^(#{1,' + level + '})\\s$'), + new RegExp(`^(${levelRegex})\\s`), configs.nodeType, (match) => ({ level: match[1].length }), ), diff --git a/packages/heading/src/plugins/keymaps.ts b/packages/heading/src/plugins/keymaps.ts index 2ab09b97..092714c3 100644 --- a/packages/heading/src/plugins/keymaps.ts +++ b/packages/heading/src/plugins/keymaps.ts @@ -2,24 +2,23 @@ import { setBlockType } from 'prosemirror-commands'; import { keymap } from 'prosemirror-keymap'; import { NodeType } from 'prosemirror-model'; import { Plugin as PMPlugin, Command } from 'prosemirror-state'; -import { EDIM_DEFAULT_HEADING_LEVEL } from '../schemas'; +import { EdimHeadingNodeSpec } from '../schemas'; export interface EdimHeadingKeymapPluginConfigs { nodeType: NodeType; - level?: number; } export const edimHeadingKeymapPlugins = ( configs: EdimHeadingKeymapPluginConfigs, ): PMPlugin[] => { - const level = configs?.level || EDIM_DEFAULT_HEADING_LEVEL; + const levels = (configs.nodeType.spec as EdimHeadingNodeSpec).meta.levels; const headingKeymaps: Record = {}; - for (let i = 1; i <= level; i++) { - headingKeymaps['Alt-Mod-' + i] = setBlockType(configs.nodeType, { - level: i, + levels.forEach((level) => { + headingKeymaps['Alt-Mod-' + level] = setBlockType(configs.nodeType, { + level: level, }); - } + }); return [keymap(headingKeymaps)]; }; diff --git a/packages/heading/src/schemas/heading.ts b/packages/heading/src/schemas/heading.ts index 0da2db94..edee1802 100644 --- a/packages/heading/src/schemas/heading.ts +++ b/packages/heading/src/schemas/heading.ts @@ -1,12 +1,14 @@ import { parseQuillTextAlign } from '@edim-editor/core'; import { NodeSpec } from 'prosemirror-model'; -export const EDIM_HEADING_DEFAULT_NODE_NAME = 'heading'; -export const EDIM_DEFAULT_HEADING_LEVEL = 6; - export type EdimHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6; export type EdimHeadingAlign = 'left' | 'right' | 'center' | null; +export const EDIM_HEADING_DEFAULT_NODE_NAME = 'heading'; +export const EDIM_HEADING_ALLOWED_LEVELS: EdimHeadingLevel[] = [ + 1, 2, 3, 4, 5, 6, +]; + export interface EdimHeadingAttrs { level: EdimHeadingLevel; align: EdimHeadingAlign; @@ -23,21 +25,18 @@ export interface EdimHeadingNodeSpec extends NodeSpec { }; meta: { levels: EdimHeadingLevel[]; - maxIndent: number; }; } export interface EdimHeadingNodeConfigs { - allowIndent?: boolean; allowAlign?: boolean; - level?: EdimHeadingLevel[]; + levels?: EdimHeadingLevel[]; nodeName?: string; } const EDIM_DEFAULT_HEADING_NODE_CONFIGS: Required = { - allowIndent: true, allowAlign: true, - level: [1, 2, 3, 4, 5, 6], + levels: EDIM_HEADING_ALLOWED_LEVELS.slice(), nodeName: EDIM_HEADING_DEFAULT_NODE_NAME, }; @@ -49,33 +48,39 @@ export const edimHeadingNodes = ( ...configs, }; + if ( + !mergedConfigs.levels.every((level) => + EDIM_HEADING_ALLOWED_LEVELS.includes(level), + ) + ) { + throw new Error('Invalid heading levels'); + } + const nodeSpec: EdimHeadingNodeSpec = { attrs: { level: { - default: 1, + default: mergedConfigs.levels[0], }, align: { default: 'left', }, }, meta: { - levels: mergedConfigs.level, - maxIndent: 6, + levels: mergedConfigs.levels, }, content: 'inline*', group: 'block', defining: true, - parseDOM: [1, 2, 3, 4, 5, 6].map((level) => ({ + parseDOM: mergedConfigs.levels.map((level) => ({ tag: `h${level}`, getAttrs: (node) => { const dom = node as HTMLElement; const align = dom.getAttribute('data-text-align'); const quillAlign = parseQuillTextAlign(dom); - const indent = Number(dom.getAttribute('data-indent')); + return { level, align: align || quillAlign || null, - indent: indent || 0, }; }, })), diff --git a/packages/menubar/src/components/text-type/text-type.ts b/packages/menubar/src/components/text-type/text-type.ts index cba1a8d8..19d5f085 100644 --- a/packages/menubar/src/components/text-type/text-type.ts +++ b/packages/menubar/src/components/text-type/text-type.ts @@ -8,7 +8,7 @@ import { classes, html, } from '@edim-editor/ui'; -import { EdimHeadingLevel } from '@edim-editor/heading'; +import { EdimHeadingNodeSpec } from '@edim-editor/heading'; import { mac, transformRangeToBlock } from '@edim-editor/core'; import { getTextType } from '../../utils'; @@ -21,10 +21,12 @@ export const EdimMenubarTextTypeSelect = () => { const paragraphNodeType = context.options.textType.paragraphNodeType; const headingNodeType = context.options.textType.headingNodeType; + const headingNodeSpec = headingNodeType.spec as EdimHeadingNodeSpec; + const textType = getTextType(context.editorView.state); const textTypeOptions = [ - ...([1, 2, 3, 4, 5, 6] as EdimHeadingLevel[]).map((level) => ({ + ...headingNodeSpec.meta.levels.map((level) => ({ value: `h${level}`, label: `Heading ${level}`, Element: EdimHeadingByNumber[level], diff --git a/packages/menubar/src/utils/current-font.ts b/packages/menubar/src/utils/current-font.ts deleted file mode 100644 index c4e6da5f..00000000 --- a/packages/menubar/src/utils/current-font.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { markActive } from '@edim-editor/core'; -import { EdimFontFamilyAttrs } from '@edim-editor/font-family'; -import { EditorState, TextSelection } from 'prosemirror-state'; - -export const currentFontFamily = (state: EditorState) => { - const selection = state.selection; - - if (!(selection instanceof TextSelection)) { - return 'default'; - } - - const actived = markActive(state, state.schema.marks['font_family']); - if (!actived) { - return 'default'; - } - - const storedFont = state.storedMarks?.find( - (mark) => mark.type === state.schema.marks['font_family'], - )?.attrs as EdimFontFamilyAttrs; - - if (storedFont) { - return storedFont.fontFamily; - } - - const fromFont = selection.$from - .marks() - .find((mark) => mark.type === state.schema.marks['font_family']) - ?.attrs as EdimFontFamilyAttrs; - - const toFont = selection.$from - .marks() - .find((mark) => mark.type === state.schema.marks['font_family']) - ?.attrs as EdimFontFamilyAttrs; - - if (!fromFont || !toFont) { - return 'default'; - } - - if (fromFont.fontFamily !== toFont.fontFamily) { - return 'default'; - } - - return fromFont.fontFamily; -}; diff --git a/packages/menubar/src/utils/index.ts b/packages/menubar/src/utils/index.ts index cc5b7d5a..7c2cbb39 100644 --- a/packages/menubar/src/utils/index.ts +++ b/packages/menubar/src/utils/index.ts @@ -1,3 +1,2 @@ export * from './current-text-type'; export * from './current-align-type'; -export * from './current-font';