diff --git a/docs/menu.md b/docs/menu.md index 3a8e4409..440d6388 100644 --- a/docs/menu.md +++ b/docs/menu.md @@ -26,7 +26,7 @@ export class AppComponent implements OnInit, OnDestroy { ['link', 'image'], ['text_color', 'background_color'], ['align_left', 'align_center', 'align_right', 'align_justify'], - ['horizontal_rule'], + ['horizontal_rule', 'format_clear'], ]; colorPresets = ['red', '#FF0000', 'rgb(255, 0, 0)']; diff --git a/projects/ngx-editor/src/lib/Locals.ts b/projects/ngx-editor/src/lib/Locals.ts index 549a3baa..ba1de152 100644 --- a/projects/ngx-editor/src/lib/Locals.ts +++ b/projects/ngx-editor/src/lib/Locals.ts @@ -22,6 +22,7 @@ export const defaults: Record = { text_color: 'Text Color', background_color: 'Background Color', horizontal_rule: 'Horizontal rule', + format_clear: 'Clear Formatting', insertLink: 'Insert Link', removeLink: 'Remove Link', insertImage: 'Insert Image', diff --git a/projects/ngx-editor/src/lib/commands/FormatClear.ts b/projects/ngx-editor/src/lib/commands/FormatClear.ts new file mode 100644 index 00000000..ee6c63c2 --- /dev/null +++ b/projects/ngx-editor/src/lib/commands/FormatClear.ts @@ -0,0 +1,35 @@ +import type { EditorState, Transaction, Command } from 'prosemirror-state'; + +const SAFE_MARKS = ['link']; + +class FormatClear { + insert(): Command { + return (state: EditorState, dispatch?: (tr: Transaction) => void): boolean => { + const { tr } = state; + const { ranges, empty } = tr.selection; + + if (empty) { + return true; + } + + Object.entries(state.schema.marks).forEach(([markType, mark]) => { + if (SAFE_MARKS.includes(markType)) { + return; + } + + ranges.forEach((range) => { + tr.removeMark(range.$from.pos, range.$to.pos, mark as any); + }); + }); + + dispatch(tr); + return true; + }; + } + + canExecute(): boolean { + return true; + } +} + +export default FormatClear; diff --git a/projects/ngx-editor/src/lib/commands/index.ts b/projects/ngx-editor/src/lib/commands/index.ts index 32792489..7361ac7e 100644 --- a/projects/ngx-editor/src/lib/commands/index.ts +++ b/projects/ngx-editor/src/lib/commands/index.ts @@ -7,6 +7,7 @@ import TextAlign from './TextAlign'; import Link from './Link'; import Image from './Image'; import TextColor from './TextColor'; +import FormatClear from './FormatClear'; export const STRONG = new Mark('strong'); export const EM = new Mark('em'); @@ -15,6 +16,7 @@ export const UNDERLINE = new Mark('u'); export const STRIKE = new Mark('s'); export const BLOCKQUOTE = new Blockquote(); export const HORIZONTAL_RULE = new HorizontalRule(); +export const FORMAT_CLEAR = new FormatClear(); export const UL = new ListItem(true); export const OL = new ListItem(false); export const H1 = new Heading(1); diff --git a/projects/ngx-editor/src/lib/icons/format_clear.ts b/projects/ngx-editor/src/lib/icons/format_clear.ts new file mode 100644 index 00000000..868c65c7 --- /dev/null +++ b/projects/ngx-editor/src/lib/icons/format_clear.ts @@ -0,0 +1,3 @@ +export default ` + +`; diff --git a/projects/ngx-editor/src/lib/icons/index.ts b/projects/ngx-editor/src/lib/icons/index.ts index 307340c1..5f15e136 100644 --- a/projects/ngx-editor/src/lib/icons/index.ts +++ b/projects/ngx-editor/src/lib/icons/index.ts @@ -18,6 +18,7 @@ import alignJustify from './align_justify'; import textColor from './text_color'; import colorFill from './color_fill'; import horizontalRule from './horizontal_rule'; +import formatClear from './format_clear'; const DEFAULT_ICON_HEIGHT = 20; const DEFAULT_ICON_WIDTH = 20; @@ -42,6 +43,7 @@ const icons: Record = { text_color: textColor, color_fill: colorFill, horizontal_rule: horizontalRule, + format_clear: formatClear, }; class Icon { diff --git a/projects/ngx-editor/src/lib/modules/menu/MenuCommands.ts b/projects/ngx-editor/src/lib/modules/menu/MenuCommands.ts index 9d126bf8..6c79b081 100644 --- a/projects/ngx-editor/src/lib/modules/menu/MenuCommands.ts +++ b/projects/ngx-editor/src/lib/modules/menu/MenuCommands.ts @@ -25,6 +25,7 @@ export const ToggleCommands: Record = { export const InsertCommands: Record = { horizontal_rule: Commands.HORIZONTAL_RULE, + format_clear: Commands.FORMAT_CLEAR, }; export const Link = Commands.LINK; diff --git a/projects/ngx-editor/src/lib/modules/menu/menu.component.ts b/projects/ngx-editor/src/lib/modules/menu/menu.component.ts index 48ea2091..dccd195f 100644 --- a/projects/ngx-editor/src/lib/modules/menu/menu.component.ts +++ b/projects/ngx-editor/src/lib/modules/menu/menu.component.ts @@ -17,6 +17,7 @@ export const DEFAULT_TOOLBAR: Toolbar = [ ['link', 'image'], ['text_color', 'background_color'], ['align_left', 'align_center', 'align_right', 'align_justify'], + ['format_clear'], ]; export const TOOLBAR_MINIMAL: Toolbar = [ @@ -89,6 +90,7 @@ export class MenuComponent implements OnInit { insertCommands: ToolbarItem[] = [ 'horizontal_rule', + 'format_clear', ]; iconContainerClass = ['NgxEditor__MenuItem', 'NgxEditor__MenuItem--Icon']; diff --git a/projects/ngx-editor/src/lib/types.ts b/projects/ngx-editor/src/lib/types.ts index 075ff61f..d59719d1 100644 --- a/projects/ngx-editor/src/lib/types.ts +++ b/projects/ngx-editor/src/lib/types.ts @@ -25,7 +25,8 @@ export type TBItems = 'bold' | 'align_center' | 'align_right' | 'align_justify' -| 'horizontal_rule'; +| 'horizontal_rule' +| 'format_clear'; export type ToolbarDropdown = { heading?: TBHeadingItems[] }; export type ToolbarCustomMenuItem = (editorView: EditorView) => TCR;