From d3b17282e0fc1a6f707473a264cd6f13bd4721bc Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 9 Nov 2022 10:50:41 +0000 Subject: [PATCH 01/23] chore: wip [] --- packages/rich-text/src/RichTextEditor.tsx | 2 + packages/rich-text/src/Toolbar/index.tsx | 4 ++ .../src/plugins/Marks/Superscript.tsx | 56 +++++++++++++++++++ packages/rich-text/src/plugins/Marks/index.ts | 9 ++- .../rich-text/src/test-utils/hyperscript.d.ts | 1 + packages/rich-text/src/types.ts | 2 + 6 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 packages/rich-text/src/plugins/Marks/Superscript.tsx diff --git a/packages/rich-text/src/RichTextEditor.tsx b/packages/rich-text/src/RichTextEditor.tsx index c3a15e4fc..cbbcc55d1 100644 --- a/packages/rich-text/src/RichTextEditor.tsx +++ b/packages/rich-text/src/RichTextEditor.tsx @@ -88,6 +88,8 @@ export const ConnectedRichTextEditor = (props: ConnectedProps) => { ); }, [isFirstRender, plugins, id, props.value]); + console.log(plugins); + return ( diff --git a/packages/rich-text/src/Toolbar/index.tsx b/packages/rich-text/src/Toolbar/index.tsx index 42ce11267..9c79f733b 100644 --- a/packages/rich-text/src/Toolbar/index.tsx +++ b/packages/rich-text/src/Toolbar/index.tsx @@ -17,6 +17,7 @@ import { ToolbarBoldButton } from '../plugins/Marks/Bold'; import { ToolbarCodeButton } from '../plugins/Marks/Code'; import { ToolbarItalicButton } from '../plugins/Marks/Italic'; import { ToolbarUnderlineButton } from '../plugins/Marks/Underline'; +import { ToolbarSuperscriptButton } from '../plugins/Marks/Superscript'; import { ToolbarQuoteButton } from '../plugins/Quote'; import { ToolbarTableButton } from '../plugins/Table'; import { useSdkContext } from '../SdkProvider'; @@ -78,6 +79,9 @@ const Toolbar = ({ isDisabled }: ToolbarProps) => { {isMarkEnabled(sdk.field, MARKS.BOLD) && } {isMarkEnabled(sdk.field, MARKS.ITALIC) && } + {isMarkEnabled(sdk.field, MARKS.SUPERSCRIPT) && ( + + )} {isMarkEnabled(sdk.field, MARKS.UNDERLINE) && ( )} diff --git a/packages/rich-text/src/plugins/Marks/Superscript.tsx b/packages/rich-text/src/plugins/Marks/Superscript.tsx new file mode 100644 index 000000000..75a7904cc --- /dev/null +++ b/packages/rich-text/src/plugins/Marks/Superscript.tsx @@ -0,0 +1,56 @@ +import * as React from 'react'; + +import { SuperscriptIcon } from '@contentful/f36-icons'; +import { createSuperscriptPlugin as createDefaultSuperscriptPlugin } from '@udecode/plate-basic-marks'; +import { MARKS } from '@contentful/rich-text-types'; +import { css } from 'emotion'; +import * as Slate from 'slate-react'; +import { someHtmlElement } from '@udecode/plate-core'; + +import { RichTextPlugin } from '../../types'; +import { createMarkToolbarButton } from './components/MarkToolbarButton'; +import { buildMarkEventHandler } from './helpers'; + +export const ToolbarSuperscriptButton = createMarkToolbarButton({ + title: 'Superscript', + mark: MARKS.SUPERSCRIPT, + icon: , +}); + +const styles = { + superscript: css({ + color: 'red', + }), +}; + +export function Superscript(props: Slate.RenderLeafProps) { + return ( + + {props.children} + + ); +} + +export const createSuperscriptPlugin = (): RichTextPlugin => + createDefaultSuperscriptPlugin({ + type: MARKS.SUPERSCRIPT, + component: Superscript, + handlers: { + onKeyDown: buildMarkEventHandler(MARKS.SUPERSCRIPT), + }, + deserializeHtml: { + rules: [ + { + validNodeName: ['SUP'], + }, + { + validStyle: { + color: ['red'], + }, + }, + ], + query: (el) => { + return !someHtmlElement(el, (node) => node.style.color !== 'red'); + }, + }, + }); diff --git a/packages/rich-text/src/plugins/Marks/index.ts b/packages/rich-text/src/plugins/Marks/index.ts index c330af4d7..10ae60b7f 100644 --- a/packages/rich-text/src/plugins/Marks/index.ts +++ b/packages/rich-text/src/plugins/Marks/index.ts @@ -3,8 +3,15 @@ import { createBoldPlugin } from './Bold'; import { createCodePlugin } from './Code'; import { createItalicPlugin } from './Italic'; import { createUnderlinePlugin } from './Underline'; +import { createSuperscriptPlugin } from './Superscript'; export const createMarksPlugin = (): RichTextPlugin => ({ key: 'Marks', - plugins: [createBoldPlugin(), createCodePlugin(), createItalicPlugin(), createUnderlinePlugin()], + plugins: [ + createBoldPlugin(), + createCodePlugin(), + createItalicPlugin(), + createUnderlinePlugin(), + createSuperscriptPlugin(), + ], }); diff --git a/packages/rich-text/src/test-utils/hyperscript.d.ts b/packages/rich-text/src/test-utils/hyperscript.d.ts index 1db26092d..1d711e047 100644 --- a/packages/rich-text/src/test-utils/hyperscript.d.ts +++ b/packages/rich-text/src/test-utils/hyperscript.d.ts @@ -12,6 +12,7 @@ declare namespace JSX { bold?: boolean; underline?: boolean; italic?: boolean; + superscript?: boolean; children?: string; }; diff --git a/packages/rich-text/src/types.ts b/packages/rich-text/src/types.ts index 9ee9312df..72bc4f9cf 100644 --- a/packages/rich-text/src/types.ts +++ b/packages/rich-text/src/types.ts @@ -12,6 +12,8 @@ export type CustomText = { [MARKS.CODE]?: boolean; [MARKS.ITALIC]?: boolean; [MARKS.UNDERLINE]?: boolean; + [MARKS.SUPERSCRIPT]?: boolean; + [MARKS.SUBSCRIPT]?: boolean; }; export type TextOrCustomElement = CustomElement | CustomText; From dd3c0662e8cdfae486127994326aaaea1add2525 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 12:27:30 +0000 Subject: [PATCH 02/23] feat: sub/superscript marks cancel each other [] --- packages/rich-text/package.json | 2 +- packages/rich-text/src/RichTextEditor.tsx | 2 - packages/rich-text/src/Toolbar/index.tsx | 4 ++ .../rich-text/src/plugins/Marks/Subscript.tsx | 41 +++++++++++++++++++ .../src/plugins/Marks/Superscript.tsx | 23 ++--------- .../Marks/components/MarkToolbarButton.tsx | 3 +- .../rich-text/src/plugins/Marks/helpers.ts | 18 ++++++-- packages/rich-text/src/plugins/Marks/index.ts | 2 + yarn.lock | 2 +- 9 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 packages/rich-text/src/plugins/Marks/Subscript.tsx diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 4d631f2bf..6641d95cf 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -33,7 +33,7 @@ "@contentful/field-editor-reference": "^5.5.2", "@contentful/field-editor-shared": "^1.1.3", "@contentful/rich-text-plain-text-renderer": "^15.12.1", - "@contentful/rich-text-types": "^15.12.3", + "@contentful/rich-text-types": "^15.14.0", "@popperjs/core": "^2.11.5", "@udecode/plate-basic-marks": "^10.4.0", "@udecode/plate-break": "^10.4.0", diff --git a/packages/rich-text/src/RichTextEditor.tsx b/packages/rich-text/src/RichTextEditor.tsx index cbbcc55d1..c3a15e4fc 100644 --- a/packages/rich-text/src/RichTextEditor.tsx +++ b/packages/rich-text/src/RichTextEditor.tsx @@ -88,8 +88,6 @@ export const ConnectedRichTextEditor = (props: ConnectedProps) => { ); }, [isFirstRender, plugins, id, props.value]); - console.log(plugins); - return ( diff --git a/packages/rich-text/src/Toolbar/index.tsx b/packages/rich-text/src/Toolbar/index.tsx index 9c79f733b..c52021579 100644 --- a/packages/rich-text/src/Toolbar/index.tsx +++ b/packages/rich-text/src/Toolbar/index.tsx @@ -18,6 +18,7 @@ import { ToolbarCodeButton } from '../plugins/Marks/Code'; import { ToolbarItalicButton } from '../plugins/Marks/Italic'; import { ToolbarUnderlineButton } from '../plugins/Marks/Underline'; import { ToolbarSuperscriptButton } from '../plugins/Marks/Superscript'; +import { ToolbarSubscriptButton } from '../plugins/Marks/Subscript'; import { ToolbarQuoteButton } from '../plugins/Quote'; import { ToolbarTableButton } from '../plugins/Table'; import { useSdkContext } from '../SdkProvider'; @@ -82,6 +83,9 @@ const Toolbar = ({ isDisabled }: ToolbarProps) => { {isMarkEnabled(sdk.field, MARKS.SUPERSCRIPT) && ( )} + {isMarkEnabled(sdk.field, MARKS.SUBSCRIPT) && ( + + )} {isMarkEnabled(sdk.field, MARKS.UNDERLINE) && ( )} diff --git a/packages/rich-text/src/plugins/Marks/Subscript.tsx b/packages/rich-text/src/plugins/Marks/Subscript.tsx new file mode 100644 index 000000000..b613532e1 --- /dev/null +++ b/packages/rich-text/src/plugins/Marks/Subscript.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; + +import { SubscriptIcon } from '@contentful/f36-icons'; +import { createSubscriptPlugin as createDefaultSubscriptPlugin } from '@udecode/plate-basic-marks'; +import { MARKS } from '@contentful/rich-text-types'; +import * as Slate from 'slate-react'; +import { someHtmlElement } from '@udecode/plate-core'; + +import { RichTextPlugin } from '../../types'; +import { createMarkToolbarButton } from './components/MarkToolbarButton'; +import { buildMarkEventHandler } from './helpers'; + +export const ToolbarSubscriptButton = createMarkToolbarButton({ + title: 'Subscript', + // TODO: use correct import when it merged + mark: 'subscript', + icon: , +}); + +export function Subscript(props: Slate.RenderLeafProps) { + return {props.children}; +} + +export const createSubscriptPlugin = (): RichTextPlugin => + createDefaultSubscriptPlugin({ + type: MARKS.SUBSCRIPT, + component: Subscript, + handlers: { + onKeyDown: buildMarkEventHandler(MARKS.SUBSCRIPT), + }, + deserializeHtml: { + rules: [ + { + validNodeName: ['SUB'], + }, + ], + query: (el) => { + return !someHtmlElement(el, (node) => node.style.fontWeight === 'normal'); + }, + }, + }); diff --git a/packages/rich-text/src/plugins/Marks/Superscript.tsx b/packages/rich-text/src/plugins/Marks/Superscript.tsx index 75a7904cc..684822bf9 100644 --- a/packages/rich-text/src/plugins/Marks/Superscript.tsx +++ b/packages/rich-text/src/plugins/Marks/Superscript.tsx @@ -3,7 +3,6 @@ import * as React from 'react'; import { SuperscriptIcon } from '@contentful/f36-icons'; import { createSuperscriptPlugin as createDefaultSuperscriptPlugin } from '@udecode/plate-basic-marks'; import { MARKS } from '@contentful/rich-text-types'; -import { css } from 'emotion'; import * as Slate from 'slate-react'; import { someHtmlElement } from '@udecode/plate-core'; @@ -13,22 +12,13 @@ import { buildMarkEventHandler } from './helpers'; export const ToolbarSuperscriptButton = createMarkToolbarButton({ title: 'Superscript', - mark: MARKS.SUPERSCRIPT, + // TODO: use correct import when it merged + mark: 'superscript', icon: , }); -const styles = { - superscript: css({ - color: 'red', - }), -}; - export function Superscript(props: Slate.RenderLeafProps) { - return ( - - {props.children} - - ); + return {props.children}; } export const createSuperscriptPlugin = (): RichTextPlugin => @@ -43,14 +33,9 @@ export const createSuperscriptPlugin = (): RichTextPlugin => { validNodeName: ['SUP'], }, - { - validStyle: { - color: ['red'], - }, - }, ], query: (el) => { - return !someHtmlElement(el, (node) => node.style.color !== 'red'); + return !someHtmlElement(el, (node) => node.style.fontWeight === 'normal'); }, }, }); diff --git a/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx b/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx index 825f4bd5f..298b5c6fa 100644 --- a/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx +++ b/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx @@ -6,6 +6,7 @@ import { isMarkActive, toggleMark } from '@udecode/plate-core'; import { useContentfulEditor } from '../../../ContentfulEditorProvider'; import { focus } from '../../../helpers/editor'; import { ToolbarButton } from '../../shared/ToolbarButton'; +import { toggleMarkAndDeactivateConflictingMarks } from '../helpers'; export interface MarkOptions { mark: MARKS; @@ -23,7 +24,7 @@ export const createMarkToolbarButton = ({ mark, title, icon }: MarkOptions) => { const isActive = isMarkActive(editor, mark); editor.tracking.onToolbarAction(isActive ? 'unmark' : 'mark', { markType: mark }); - toggleMark(editor, { key: mark }); + toggleMarkAndDeactivateConflictingMarks(editor, mark); focus(editor); }, [editor]); diff --git a/packages/rich-text/src/plugins/Marks/helpers.ts b/packages/rich-text/src/plugins/Marks/helpers.ts index 38ddad4ba..9d6aaa94a 100644 --- a/packages/rich-text/src/plugins/Marks/helpers.ts +++ b/packages/rich-text/src/plugins/Marks/helpers.ts @@ -1,9 +1,22 @@ -import { MARKS } from '@contentful/rich-text-types'; import { HotkeyPlugin, isMarkActive, KeyboardHandler, toggleMark } from '@udecode/plate-core'; import isHotkey from 'is-hotkey'; +import type { PlateEditor } from '@udecode/plate-core'; +import type { MARKS } from '@contentful/rich-text-types'; import { RichTextEditor } from '../../types'; +export const toggleMarkAndDeactivateConflictingMarks = ( + editor: PlateEditor, + mark: MARKS +) => { + toggleMark(editor, { key: mark }); + if (mark === 'subscript' && isMarkActive(editor, 'superscript')) { + toggleMark(editor, { key: 'superscript' }); + } else if (mark === 'superscript' && isMarkActive(editor, 'subscript')) { + toggleMark(editor, { key: 'subscript' }); + } +}; + export const buildMarkEventHandler = (type: MARKS): KeyboardHandler => (editor, { options: { hotkey } }) => @@ -13,7 +26,6 @@ export const buildMarkEventHandler = const isActive = isMarkActive(editor, type); editor.tracking.onShortcutAction(isActive ? 'unmark' : 'mark', { markType: type }); - - toggleMark(editor, { key: type as string }); + toggleMarkAndDeactivateConflictingMarks(editor, type); } }; diff --git a/packages/rich-text/src/plugins/Marks/index.ts b/packages/rich-text/src/plugins/Marks/index.ts index 10ae60b7f..99888b44b 100644 --- a/packages/rich-text/src/plugins/Marks/index.ts +++ b/packages/rich-text/src/plugins/Marks/index.ts @@ -4,6 +4,7 @@ import { createCodePlugin } from './Code'; import { createItalicPlugin } from './Italic'; import { createUnderlinePlugin } from './Underline'; import { createSuperscriptPlugin } from './Superscript'; +import { createSubscriptPlugin } from './Subscript'; export const createMarksPlugin = (): RichTextPlugin => ({ key: 'Marks', @@ -13,5 +14,6 @@ export const createMarksPlugin = (): RichTextPlugin => ({ createItalicPlugin(), createUnderlinePlugin(), createSuperscriptPlugin(), + createSubscriptPlugin(), ], }); diff --git a/yarn.lock b/yarn.lock index 51cc21dec..029868c5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2414,7 +2414,7 @@ dependencies: "@contentful/rich-text-types" "^15.12.1" -"@contentful/rich-text-types@^15.12.1", "@contentful/rich-text-types@^15.12.3": +"@contentful/rich-text-types@^15.12.1", "@contentful/rich-text-types@^15.13.2": version "15.13.2" resolved "https://registry.yarnpkg.com/@contentful/rich-text-types/-/rich-text-types-15.13.2.tgz#626956c31b4cc95aa618735d992e851d2ed61346" integrity sha512-cnVvJjRQ414rprnoMLR/S+18a7Hjp3dR4WhiQ/A6W/LSS5FDx1AbiDZACjIEaQEk5L6FX0oBHanIIbAUTA5YJw== From 8e967b357176305b2d8be43904afe7d5ca1eba2a Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 12:27:52 +0000 Subject: [PATCH 03/23] chore: removing unused import [] --- .../src/plugins/Marks/components/MarkToolbarButton.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx b/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx index 298b5c6fa..7e70ea86f 100644 --- a/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx +++ b/packages/rich-text/src/plugins/Marks/components/MarkToolbarButton.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { MARKS } from '@contentful/rich-text-types'; -import { isMarkActive, toggleMark } from '@udecode/plate-core'; +import { isMarkActive } from '@udecode/plate-core'; import { useContentfulEditor } from '../../../ContentfulEditorProvider'; import { focus } from '../../../helpers/editor'; @@ -36,7 +36,8 @@ export const createMarkToolbarButton = ({ mark, title, icon }: MarkOptions) => { testId={`${mark}-toolbar-button`} onClick={handleClick} isActive={isMarkActive(editor, mark)} - isDisabled={isDisabled}> + isDisabled={isDisabled} + > {icon} ); From b7f987d2db69429626d8d82ef739beab45c1fe5f Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 13:42:20 +0000 Subject: [PATCH 04/23] chore: adding test for pasting sub/superscript [] --- .../rich-text/RichTextEditor.Pasting.spec.ts | 16 +++ .../RichTextEditor.Pasting.spec.ts.snap | 114 ++++++++++++++---- 2 files changed, 107 insertions(+), 23 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts b/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts index 89f805c4c..cc3209f3a 100644 --- a/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts @@ -274,6 +274,22 @@ describe( }); }); + describe('Superscript and subscript marks', () => { + it('works when pasting subscript and superscript from another RT editor', () => { + // A simple "hello world" text with marks: superscript and subscript. + // Copied from the RT editor + richText.editor.click().paste({ + 'text/plain': 'HelloWorld', + 'text/html': + 'HelloWorld', + 'application/x-vnd.google-docs-document-slice-clip+wrapped': + '{"dih":3014089275,"data":"{\\"resolved\\":{\\"dsl_spacers\\":\\"HelloWorld\\",\\"dsl_styleslices\\":[{\\"stsl_type\\":\\"autogen\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"cell\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"code_snippet\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"collapsed_heading\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"column_sector\\",\\"stsl_leading\\":{\\"css_cols\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}},\\"css_lb\\":false,\\"css_ltr\\":true,\\"css_st\\":\\"continuous\\",\\"css_mb\\":null,\\"css_mh\\":null,\\"css_mf\\":null,\\"css_ml\\":null,\\"css_mr\\":null,\\"css_mt\\":null,\\"css_fi\\":null,\\"css_hi\\":null,\\"css_epfi\\":null,\\"css_ephi\\":null,\\"css_fpfi\\":null,\\"css_fphi\\":null,\\"css_ufphf\\":null,\\"css_pnsi\\":null,\\"css_fpo\\":null},\\"stsl_leadingType\\":\\"column_sector\\",\\"stsl_trailing\\":{\\"css_cols\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}},\\"css_lb\\":false,\\"css_ltr\\":true,\\"css_st\\":\\"continuous\\",\\"css_mb\\":null,\\"css_mh\\":null,\\"css_mf\\":null,\\"css_ml\\":null,\\"css_mr\\":null,\\"css_mt\\":null,\\"css_fi\\":null,\\"css_hi\\":null,\\"css_epfi\\":null,\\"css_ephi\\":null,\\"css_fpfi\\":null,\\"css_fphi\\":null,\\"css_ufphf\\":null,\\"css_pnsi\\":null,\\"css_fpo\\":null},\\"stsl_trailingType\\":\\"column_sector\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"comment\\",\\"stsl_styles\\":[{\\"cs_cids\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"doco_anchor\\",\\"stsl_styles\\":[{\\"das_a\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"document\\",\\"stsl_leading\\":{\\"ds_b\\":{\\"bg_c2\\":{\\"clr_type\\":0,\\"hclr_color\\":null}},\\"ds_df\\":{\\"df_dm\\":0},\\"ds_fi\\":null,\\"ds_hi\\":null,\\"ds_epfi\\":null,\\"ds_ephi\\":null,\\"ds_uephf\\":false,\\"ds_fpfi\\":null,\\"ds_fphi\\":null,\\"ds_ufphf\\":false,\\"ds_pnsi\\":1,\\"ds_mb\\":72,\\"ds_ml\\":72,\\"ds_mr\\":72,\\"ds_mt\\":72,\\"ds_ph\\":792,\\"ds_pw\\":612,\\"ds_rtd\\":\\"\\",\\"ds_mh\\":36,\\"ds_mf\\":36,\\"ds_ulhfl\\":false,\\"ds_lhs\\":1,\\"ds_fpo\\":false},\\"stsl_leadingType\\":\\"document\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"equation\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"equation_function\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"field\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"footnote\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"headings\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"horizontal_rule\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"ignore_spellcheck\\",\\"stsl_styles\\":[{\\"isc_osh\\":null}]},{\\"stsl_type\\":\\"import_warnings\\",\\"stsl_styles\\":[{\\"iws_iwids\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"language\\",\\"stsl_trailing\\":{\\"lgs_l\\":\\"en\\"},\\"stsl_trailingType\\":\\"language\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"link\\",\\"stsl_styles\\":[{\\"lnks_link\\":null}]},{\\"stsl_type\\":\\"list\\",\\"stsl_trailing\\":{\\"ls_nest\\":0,\\"ls_id\\":null,\\"ls_c\\":null,\\"ls_ts\\":{\\"ts_bd\\":false,\\"ts_fs\\":11,\\"ts_ff\\":\\"Arial\\",\\"ts_it\\":false,\\"ts_sc\\":false,\\"ts_st\\":false,\\"ts_tw\\":400,\\"ts_un\\":false,\\"ts_va\\":\\"nor\\",\\"ts_bgc2\\":{\\"clr_type\\":0,\\"hclr_color\\":null},\\"ts_fgc2\\":{\\"clr_type\\":0,\\"hclr_color\\":\\"#000000\\"},\\"ts_bd_i\\":false,\\"ts_fs_i\\":false,\\"ts_ff_i\\":false,\\"ts_it_i\\":false,\\"ts_sc_i\\":false,\\"ts_st_i\\":false,\\"ts_un_i\\":false,\\"ts_va_i\\":false,\\"ts_bgc2_i\\":false,\\"ts_fgc2_i\\":false}},\\"stsl_trailingType\\":\\"list\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"named_range\\",\\"stsl_styles\\":[{\\"nrs_ei\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"paragraph\\",\\"stsl_trailing\\":{\\"ps_al\\":0,\\"ps_awao\\":true,\\"ps_sd\\":null,\\"ps_bbtw\\":null,\\"ps_bb\\":null,\\"ps_bl\\":null,\\"ps_br\\":null,\\"ps_bt\\":null,\\"ps_hd\\":0,\\"ps_hdid\\":\\"\\",\\"ps_ifl\\":0,\\"ps_il\\":0,\\"ps_ir\\":0,\\"ps_klt\\":false,\\"ps_kwn\\":false,\\"ps_ltr\\":true,\\"ps_ls\\":1.15,\\"ps_lslm\\":1,\\"ps_pbb\\":false,\\"ps_sm\\":0,\\"ps_sa\\":0,\\"ps_sb\\":0,\\"ps_al_i\\":false,\\"ps_awao_i\\":false,\\"ps_sd_i\\":false,\\"ps_bbtw_i\\":false,\\"ps_bb_i\\":false,\\"ps_bl_i\\":false,\\"ps_br_i\\":false,\\"ps_bt_i\\":false,\\"ps_ifl_i\\":false,\\"ps_il_i\\":false,\\"ps_ir_i\\":false,\\"ps_klt_i\\":false,\\"ps_kwn_i\\":false,\\"ps_ls_i\\":false,\\"ps_lslm_i\\":false,\\"ps_pbb_i\\":false,\\"ps_rd\\":\\"\\",\\"ps_sm_i\\":false,\\"ps_sa_i\\":false,\\"ps_sb_i\\":false,\\"ps_shd\\":false,\\"ps_ts\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}},\\"stsl_trailingType\\":\\"paragraph\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"row\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"suppress_feature\\",\\"stsl_styles\\":[{\\"sfs_sst\\":false}]},{\\"stsl_type\\":\\"tbl\\",\\"stsl_styles\\":[]},{\\"stsl_type\\":\\"text\\",\\"stsl_styles\\":[{\\"ts_bd\\":false,\\"ts_fs\\":11,\\"ts_ff\\":\\"Arial\\",\\"ts_it\\":false,\\"ts_sc\\":false,\\"ts_st\\":false,\\"ts_tw\\":400,\\"ts_un\\":false,\\"ts_va\\":\\"sup\\",\\"ts_bgc2\\":{\\"clr_type\\":0,\\"hclr_color\\":null},\\"ts_fgc2\\":{\\"clr_type\\":0,\\"hclr_color\\":\\"#000000\\"},\\"ts_bd_i\\":false,\\"ts_fs_i\\":false,\\"ts_ff_i\\":false,\\"ts_it_i\\":false,\\"ts_sc_i\\":false,\\"ts_st_i\\":false,\\"ts_un_i\\":false,\\"ts_va_i\\":false,\\"ts_bgc2_i\\":false,\\"ts_fgc2_i\\":false},null,null,null,null,{\\"ts_bd\\":false,\\"ts_fs\\":11,\\"ts_ff\\":\\"Arial\\",\\"ts_it\\":false,\\"ts_sc\\":false,\\"ts_st\\":false,\\"ts_tw\\":400,\\"ts_un\\":false,\\"ts_va\\":\\"sub\\",\\"ts_bgc2\\":{\\"clr_type\\":0,\\"hclr_color\\":null},\\"ts_fgc2\\":{\\"clr_type\\":0,\\"hclr_color\\":\\"#000000\\"},\\"ts_bd_i\\":false,\\"ts_fs_i\\":false,\\"ts_ff_i\\":false,\\"ts_it_i\\":false,\\"ts_sc_i\\":false,\\"ts_st_i\\":false,\\"ts_un_i\\":false,\\"ts_va_i\\":false,\\"ts_bgc2_i\\":false,\\"ts_fgc2_i\\":false}]}],\\"dsl_metastyleslices\\":[{\\"stsl_type\\":\\"autocorrect\\",\\"stsl_styles\\":[{\\"ac_ot\\":null,\\"ac_ct\\":null,\\"ac_type\\":null,\\"ac_sm\\":{\\"asm_s\\":0,\\"asm_rl\\":0,\\"asm_l\\":\\"\\"},\\"ac_id\\":\\"\\"}]},{\\"stsl_type\\":\\"collapsed_content\\",\\"stsl_styles\\":[{\\"colc_icc\\":false}]},{\\"stsl_type\\":\\"composing_decoration\\",\\"stsl_styles\\":[{\\"cd_u\\":false,\\"cd_bgc\\":{\\"clr_type\\":0,\\"hclr_color\\":null}}]},{\\"stsl_type\\":\\"composing_region\\",\\"stsl_styles\\":[{\\"cr_c\\":false}]},{\\"stsl_type\\":\\"draft_comment\\",\\"stsl_styles\\":[{\\"dcs_cids\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"ignore_word\\",\\"stsl_styles\\":[{\\"iwos_i\\":false}]},{\\"stsl_type\\":\\"revision_diff\\",\\"stsl_styles\\":[{\\"revdiff_dt\\":0,\\"revdiff_a\\":\\"\\",\\"revdiff_aid\\":\\"\\"}]},{\\"stsl_type\\":\\"smart_todo\\",\\"stsl_styles\\":[{\\"sts_cid\\":null,\\"sts_ot\\":null,\\"sts_ac\\":null,\\"sts_hi\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}},\\"sts_pa\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}},\\"sts_dm\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"spellcheck\\",\\"stsl_styles\\":[{\\"sc_id\\":\\"\\",\\"sc_ow\\":null,\\"sc_sl\\":null,\\"sc_sugg\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}},\\"sc_sm\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}}}]},{\\"stsl_type\\":\\"voice_corrections\\",\\"stsl_styles\\":[{\\"vcs_c\\":{\\"cv\\":{\\"op\\":\\"set\\",\\"opValue\\":[]}},\\"vcs_id\\":\\"\\"}]},{\\"stsl_type\\":\\"voice_dotted_span\\",\\"stsl_styles\\":[{\\"vdss_p\\":null,\\"vdss_id\\":\\"\\"}]}],\\"dsl_suggestedinsertions\\":{\\"sgsl_sugg\\":[]},\\"dsl_suggesteddeletions\\":{\\"sgsl_sugg\\":[]},\\"dsl_entitypositionmap\\":{},\\"dsl_entitymap\\":{},\\"dsl_entitytypemap\\":{},\\"dsl_drawingrevisionaccesstokenmap\\":{},\\"dsl_relateddocslices\\":{},\\"dsl_nestedmodelmap\\":{}},\\"autotext_content\\":{}}","edi":"QT9bASY3_GwFN8ZN119g2Ja2EHnrx_nq6yjODnrlfjrbkZEpqMl5NY_AGJtzSbcFsVk9XklA8IoHTqo123xXoO8cLKmVgnTCRWC6udfsvDpa","edrk":"xKYajWttYyLMt_u511ACUFI3qewboAf7dCubtDmoDhoCHwlXkw..","dct":"kix","ds":false,"cses":false}', + }); + + richText.expectSnapshotValue(); + }); + }); + describe('copy from safari (no href in anchors)', () => { it('recognizes entry hyperlink', () => { richText.editor.click().paste({ diff --git a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap index d3f2257b8..7d7c65c3d 100644 --- a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap +++ b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap @@ -2955,6 +2955,7 @@ exports[`Rich Text Editor > Tables > Google Docs - around
#0`] = "data": {}, "nodeType": "document" }; + exports[`Rich Text Editor > Tables > removes table wrappers when pasting a single cell #0`] = { "nodeType": "document", @@ -2964,32 +2965,99 @@ exports[`Rich Text Editor > Tables > removes table wrappers when pasting a singl "nodeType": "paragraph", "data": {}, "content": [ - { - "nodeType": "text", - "value": "cell content with a link and inline entry", - "marks": [], - "data": {} - }, - { - "nodeType": "embedded-entry-inline", - "data": { - "target": { - "sys": { - "id": "example-entity-id", - "type": "Link", - "linkType": "Entry" - } + { + "nodeType": "text", + "value": "cell content with a link and inline entry", + "marks": [], + "data": {} + }, + { + "nodeType": "embedded-entry-inline", + "data": { + "target": { + "sys": { + "id": "example-entity-id", + "type": "Link", + "linkType": "Entry" } - }, - "content": [] + } }, - { - "nodeType": "text", - "value": ".", - "marks": [], - "data": {} - } + "content": [] + }, + { + "nodeType": "text", + "value": ".", + "marks": [], + "data": {} + } ] } ] }; + +exports[`Rich Text Editor > Superscript and subscript marks > works when pasting from another RT editor #0`] = +{ + "content": [ + { + "content": [ + { + "data": {}, + "marks": [ + { + "type": "bold" + }, + { + "type": "italic" + }, + { + "type": "underline" + }, + { + "type": "code" + } + ], + "nodeType": "text", + "value": "hello world" + } + ], + "data": {}, + "nodeType": "paragraph" + } + ], + "data": {}, + "nodeType": "document" +}; + +exports[`Rich Text Editor > Superscript and subscript marks > works when pasting subscript and superscript from another RT editor #0`] = +{ + "content": [ + { + "content": [ + { + "data": {}, + "marks": [ + { + "type": "superscript" + } + ], + "nodeType": "text", + "value": "Hello" + }, + { + "data": {}, + "marks": [ + { + "type": "subscript" + } + ], + "nodeType": "text", + "value": "World" + } + ], + "data": {}, + "nodeType": "paragraph" + } + ], + "data": {}, + "nodeType": "document" +}; From c293fbbee6b77efe8c7c03c0a97e9cb1cfe026a4 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 14:34:39 +0000 Subject: [PATCH 05/23] chore: adding tests for sub/superscript [] --- .../rich-text/RichTextEditor.spec.ts | 102 +++++++++++------- 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index 558d08381..4a2607abf 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -208,19 +208,21 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { }); describe('Marks', () => { + const toggleMarkViaToolbar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`).click(); [ [MARKS.BOLD, `{${mod}}b`], [MARKS.ITALIC, `{${mod}}i`], [MARKS.UNDERLINE, `{${mod}}u`], [MARKS.CODE, `{${mod}}/`], + // TODO replace with actual types when package update becomes available + ['superscript'], + ['subscript'], ].forEach(([mark, shortcut]) => { - const toggleMarkViaToolbar = () => cy.findByTestId(`${mark}-toolbar-button`).click(); - describe(`${mark} mark toggle via toolbar`, () => { it('allows writing marked text', () => { richText.editor.click(); - toggleMarkViaToolbar(); + toggleMarkViaToolbar(mark); richText.editor.type('some text'); @@ -234,7 +236,7 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { it('allows writing marked text by selecting text', () => { richText.editor.click().type('some text{selectall}'); - toggleMarkViaToolbar(); + toggleMarkViaToolbar(mark); const expectedValue = doc( block(BLOCKS.PARAGRAPH, {}, text('some text', [{ type: mark }])) @@ -246,8 +248,8 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { it('allows writing unmarked text', () => { richText.editor.click(); - toggleMarkViaToolbar(); - toggleMarkViaToolbar(); + toggleMarkViaToolbar(mark); + toggleMarkViaToolbar(mark); richText.editor.type('some text'); @@ -259,13 +261,13 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { it('allows writing unmarked text by selecting text', () => { richText.editor.click().type('some text{selectall}'); - toggleMarkViaToolbar(); + toggleMarkViaToolbar(mark); cy.wait(100); richText.editor.click().type('{selectall}'); - toggleMarkViaToolbar(); + toggleMarkViaToolbar(mark); const expectedValue = doc(block(BLOCKS.PARAGRAPH, {}, text('some text', []))); @@ -273,51 +275,77 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { }); }); - describe(`${mark} mark toggle via shortcut`, () => { - it('allows writing marked text', () => { - richText.editor.click().type(shortcut).type('some text'); + if (shortcut) { + describe(`${mark} mark toggle via shortcut`, () => { + it('allows writing marked text', () => { + richText.editor.click().type(shortcut).type('some text'); - const expectedValue = doc( - block(BLOCKS.PARAGRAPH, {}, text('some text', [{ type: mark }])) - ); + const expectedValue = doc( + block(BLOCKS.PARAGRAPH, {}, text('some text', [{ type: mark }])) + ); - richText.expectValue(expectedValue); - }); + richText.expectValue(expectedValue); + }); - it('allows writing marked text by selecting text', () => { - richText.editor.click().type('some text'); + it('allows writing marked text by selecting text', () => { + richText.editor.click().type('some text'); - cy.wait(100); + cy.wait(100); - richText.editor.type('{selectall}').type(shortcut); + richText.editor.type('{selectall}').type(shortcut); - const expectedValue = doc( - block(BLOCKS.PARAGRAPH, {}, text('some text', [{ type: mark }])) - ); + const expectedValue = doc( + block(BLOCKS.PARAGRAPH, {}, text('some text', [{ type: mark }])) + ); - richText.expectValue(expectedValue); - }); + richText.expectValue(expectedValue); + }); - it('allows writing unmarked text', () => { - richText.editor.click().type(shortcut).type(shortcut).type('some text'); + it('allows writing unmarked text', () => { + richText.editor.click().type(shortcut).type(shortcut).type('some text'); - const expectedValue = doc(block(BLOCKS.PARAGRAPH, {}, text('some text', []))); + const expectedValue = doc(block(BLOCKS.PARAGRAPH, {}, text('some text', []))); - richText.expectValue(expectedValue); - }); + richText.expectValue(expectedValue); + }); - it('allows writing unmarked text by selecting text', () => { - richText.editor.click().type('some text'); + it('allows writing unmarked text by selecting text', () => { + richText.editor.click().type('some text'); - cy.wait(100); + cy.wait(100); - richText.editor.type('{selectall}').type(shortcut).type('{selectall}').type(shortcut); + richText.editor.type('{selectall}').type(shortcut).type('{selectall}').type(shortcut); - const expectedValue = doc(block(BLOCKS.PARAGRAPH, {}, text('some text', []))); + const expectedValue = doc(block(BLOCKS.PARAGRAPH, {}, text('some text', []))); - richText.expectValue(expectedValue); + richText.expectValue(expectedValue); + }); }); - }); + } + }); + + it('should remove subscript when superscript mark is selected', () => { + richText.editor.click().type('hello there{selectall}'); + toggleMarkViaToolbar('subscript'); + richText.editor.click().type('{selectall}'); + toggleMarkViaToolbar('superscript'); + + const expectedValue = doc( + block(BLOCKS.PARAGRAPH, {}, text('should only be superscript', [{ type: 'superscript' }])) + ); + richText.expectValue(expectedValue); + }); + + it('should remove superscript when subscript mark is selected', () => { + richText.editor.click().type('hello there{selectall}'); + toggleMarkViaToolbar('superscript'); + richText.editor.click().type('{selectall}'); + toggleMarkViaToolbar('subscript'); + + const expectedValue = doc( + block(BLOCKS.PARAGRAPH, {}, text('should only be subscript', [{ type: 'subscript' }])) + ); + richText.expectValue(expectedValue); }); }); From a8d0102f41c9dca6d5d438283a4ee95df61db7ad Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 15:06:41 +0000 Subject: [PATCH 06/23] chore: replacing hard coded value [] --- .../rich-text/RichTextEditor.spec.ts | 21 +++++++++++-------- .../rich-text/src/plugins/Marks/Subscript.tsx | 3 +-- .../src/plugins/Marks/Superscript.tsx | 3 +-- .../rich-text/src/plugins/Marks/helpers.ts | 8 +++---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index 4a2607abf..fbfa3ab4e 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -214,9 +214,8 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { [MARKS.ITALIC, `{${mod}}i`], [MARKS.UNDERLINE, `{${mod}}u`], [MARKS.CODE, `{${mod}}/`], - // TODO replace with actual types when package update becomes available - ['superscript'], - ['subscript'], + [MARKS.SUPERSCRIPT], + [MARKS.SUBSCRIPT], ].forEach(([mark, shortcut]) => { describe(`${mark} mark toggle via toolbar`, () => { it('allows writing marked text', () => { @@ -326,24 +325,28 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { it('should remove subscript when superscript mark is selected', () => { richText.editor.click().type('hello there{selectall}'); - toggleMarkViaToolbar('subscript'); + toggleMarkViaToolbar(MARKS.SUBSCRIPT); richText.editor.click().type('{selectall}'); - toggleMarkViaToolbar('superscript'); + toggleMarkViaToolbar(MARKS.SUPERSCRIPT); const expectedValue = doc( - block(BLOCKS.PARAGRAPH, {}, text('should only be superscript', [{ type: 'superscript' }])) + block( + BLOCKS.PARAGRAPH, + {}, + text('should only be superscript', [{ type: MARKS.SUPERSCRIPT }]) + ) ); richText.expectValue(expectedValue); }); it('should remove superscript when subscript mark is selected', () => { richText.editor.click().type('hello there{selectall}'); - toggleMarkViaToolbar('superscript'); + toggleMarkViaToolbar(MARKS.SUPERSCRIPT); richText.editor.click().type('{selectall}'); - toggleMarkViaToolbar('subscript'); + toggleMarkViaToolbar(MARKS.SUBSCRIPT); const expectedValue = doc( - block(BLOCKS.PARAGRAPH, {}, text('should only be subscript', [{ type: 'subscript' }])) + block(BLOCKS.PARAGRAPH, {}, text('should only be subscript', [{ type: MARKS.SUBSCRIPT }])) ); richText.expectValue(expectedValue); }); diff --git a/packages/rich-text/src/plugins/Marks/Subscript.tsx b/packages/rich-text/src/plugins/Marks/Subscript.tsx index b613532e1..71162b306 100644 --- a/packages/rich-text/src/plugins/Marks/Subscript.tsx +++ b/packages/rich-text/src/plugins/Marks/Subscript.tsx @@ -12,8 +12,7 @@ import { buildMarkEventHandler } from './helpers'; export const ToolbarSubscriptButton = createMarkToolbarButton({ title: 'Subscript', - // TODO: use correct import when it merged - mark: 'subscript', + mark: MARKS.SUBSCRIPT, icon: , }); diff --git a/packages/rich-text/src/plugins/Marks/Superscript.tsx b/packages/rich-text/src/plugins/Marks/Superscript.tsx index 684822bf9..46f0817c5 100644 --- a/packages/rich-text/src/plugins/Marks/Superscript.tsx +++ b/packages/rich-text/src/plugins/Marks/Superscript.tsx @@ -12,8 +12,7 @@ import { buildMarkEventHandler } from './helpers'; export const ToolbarSuperscriptButton = createMarkToolbarButton({ title: 'Superscript', - // TODO: use correct import when it merged - mark: 'superscript', + mark: MARKS.SUPERSCRIPT', icon: , }); diff --git a/packages/rich-text/src/plugins/Marks/helpers.ts b/packages/rich-text/src/plugins/Marks/helpers.ts index 9d6aaa94a..afeff5448 100644 --- a/packages/rich-text/src/plugins/Marks/helpers.ts +++ b/packages/rich-text/src/plugins/Marks/helpers.ts @@ -10,10 +10,10 @@ export const toggleMarkAndDeactivateConflictingMarks = ( mark: MARKS ) => { toggleMark(editor, { key: mark }); - if (mark === 'subscript' && isMarkActive(editor, 'superscript')) { - toggleMark(editor, { key: 'superscript' }); - } else if (mark === 'superscript' && isMarkActive(editor, 'subscript')) { - toggleMark(editor, { key: 'subscript' }); + if (mark === MARKS.SUBSCRIPT && isMarkActive(editor, MARKS.SUPERSCRIPT)) { + toggleMark(editor, { key: MARKS.SUPERSCRIPT }); + } else if (mark === MARKS.SUPERSCRIPT && isMarkActive(editor, MARKS.SUBSCRIPT)) { + toggleMark(editor, { key: MARKS.SUBSCRIPT }); } }; From d00ff124ee81ed36678f858558b42b9ca7918936 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 15:15:58 +0000 Subject: [PATCH 07/23] chore: removing unused line [] --- packages/rich-text/src/test-utils/hyperscript.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rich-text/src/test-utils/hyperscript.d.ts b/packages/rich-text/src/test-utils/hyperscript.d.ts index 1d711e047..1db26092d 100644 --- a/packages/rich-text/src/test-utils/hyperscript.d.ts +++ b/packages/rich-text/src/test-utils/hyperscript.d.ts @@ -12,7 +12,6 @@ declare namespace JSX { bold?: boolean; underline?: boolean; italic?: boolean; - superscript?: boolean; children?: string; }; From a1068f9cfe5382c134239831970e3b543b0b49e0 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Mon, 14 Nov 2022 15:19:21 +0000 Subject: [PATCH 08/23] chore: fixing issue [] --- packages/rich-text/src/plugins/Marks/Superscript.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rich-text/src/plugins/Marks/Superscript.tsx b/packages/rich-text/src/plugins/Marks/Superscript.tsx index 46f0817c5..fd31fa25c 100644 --- a/packages/rich-text/src/plugins/Marks/Superscript.tsx +++ b/packages/rich-text/src/plugins/Marks/Superscript.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { SuperscriptIcon } from '@contentful/f36-icons'; -import { createSuperscriptPlugin as createDefaultSuperscriptPlugin } from '@udecode/plate-basic-marks'; import { MARKS } from '@contentful/rich-text-types'; -import * as Slate from 'slate-react'; +import { createSuperscriptPlugin as createDefaultSuperscriptPlugin } from '@udecode/plate-basic-marks'; import { someHtmlElement } from '@udecode/plate-core'; +import * as Slate from 'slate-react'; import { RichTextPlugin } from '../../types'; import { createMarkToolbarButton } from './components/MarkToolbarButton'; @@ -12,7 +12,7 @@ import { buildMarkEventHandler } from './helpers'; export const ToolbarSuperscriptButton = createMarkToolbarButton({ title: 'Superscript', - mark: MARKS.SUPERSCRIPT', + mark: MARKS.SUPERSCRIPT, icon: , }); From b9a59e8268add340590263227b4917bc85af1240 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 11:20:54 +0000 Subject: [PATCH 09/23] chore: updating rich-text-types [] --- yarn.lock | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 029868c5d..e3b7d7dea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2414,11 +2414,16 @@ dependencies: "@contentful/rich-text-types" "^15.12.1" -"@contentful/rich-text-types@^15.12.1", "@contentful/rich-text-types@^15.13.2": +"@contentful/rich-text-types@^15.12.1": version "15.13.2" resolved "https://registry.yarnpkg.com/@contentful/rich-text-types/-/rich-text-types-15.13.2.tgz#626956c31b4cc95aa618735d992e851d2ed61346" integrity sha512-cnVvJjRQ414rprnoMLR/S+18a7Hjp3dR4WhiQ/A6W/LSS5FDx1AbiDZACjIEaQEk5L6FX0oBHanIIbAUTA5YJw== +"@contentful/rich-text-types@^15.14.0": + version "15.14.0" + resolved "https://registry.yarnpkg.com/@contentful/rich-text-types/-/rich-text-types-15.14.0.tgz#9bc2ce5e4409f8333d4ad641f1d296aaad6de57e" + integrity sha512-KvyijiWyRFYodf5wjJmeA3L1ryVej015wEVQBrKvPwG4n7itbYczEPmxC10GWhg121qb5mfYVlGEmnAIXsBmIQ== + "@csstools/convert-colors@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" From e998790709c1b103d00fb8baedbdfce3d72fc84b Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 11:25:16 +0000 Subject: [PATCH 10/23] chore: fixing import [] --- packages/rich-text/src/plugins/Marks/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/plugins/Marks/helpers.ts b/packages/rich-text/src/plugins/Marks/helpers.ts index afeff5448..c7123255b 100644 --- a/packages/rich-text/src/plugins/Marks/helpers.ts +++ b/packages/rich-text/src/plugins/Marks/helpers.ts @@ -1,7 +1,7 @@ +import { MARKS } from '@contentful/rich-text-types'; import { HotkeyPlugin, isMarkActive, KeyboardHandler, toggleMark } from '@udecode/plate-core'; -import isHotkey from 'is-hotkey'; import type { PlateEditor } from '@udecode/plate-core'; -import type { MARKS } from '@contentful/rich-text-types'; +import isHotkey from 'is-hotkey'; import { RichTextEditor } from '../../types'; From 71a31df44966949222ce21d3d7b3583adcc807cf Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 12:55:11 +0000 Subject: [PATCH 11/23] chore: pinning version [] --- packages/rich-text/package.json | 2 +- yarn.lock | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 6641d95cf..8981537b7 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -33,7 +33,7 @@ "@contentful/field-editor-reference": "^5.5.2", "@contentful/field-editor-shared": "^1.1.3", "@contentful/rich-text-plain-text-renderer": "^15.12.1", - "@contentful/rich-text-types": "^15.14.0", + "@contentful/rich-text-types": "15.14.0", "@popperjs/core": "^2.11.5", "@udecode/plate-basic-marks": "^10.4.0", "@udecode/plate-break": "^10.4.0", diff --git a/yarn.lock b/yarn.lock index e3b7d7dea..d21d30d1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2414,12 +2414,7 @@ dependencies: "@contentful/rich-text-types" "^15.12.1" -"@contentful/rich-text-types@^15.12.1": - version "15.13.2" - resolved "https://registry.yarnpkg.com/@contentful/rich-text-types/-/rich-text-types-15.13.2.tgz#626956c31b4cc95aa618735d992e851d2ed61346" - integrity sha512-cnVvJjRQ414rprnoMLR/S+18a7Hjp3dR4WhiQ/A6W/LSS5FDx1AbiDZACjIEaQEk5L6FX0oBHanIIbAUTA5YJw== - -"@contentful/rich-text-types@^15.14.0": +"@contentful/rich-text-types@15.14.0", "@contentful/rich-text-types@^15.12.1": version "15.14.0" resolved "https://registry.yarnpkg.com/@contentful/rich-text-types/-/rich-text-types-15.14.0.tgz#9bc2ce5e4409f8333d4ad641f1d296aaad6de57e" integrity sha512-KvyijiWyRFYodf5wjJmeA3L1ryVej015wEVQBrKvPwG4n7itbYczEPmxC10GWhg121qb5mfYVlGEmnAIXsBmIQ== From 214ddefcabaa458e8b7169a410d1a87de12d6315 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 13:43:39 +0000 Subject: [PATCH 12/23] chore: fixing test [] --- cypress/integration/rich-text/RichTextEditor.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index fbfa3ab4e..d4ac250d3 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -332,8 +332,8 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { const expectedValue = doc( block( BLOCKS.PARAGRAPH, - {}, - text('should only be superscript', [{ type: MARKS.SUPERSCRIPT }]) + text('should only be superscript', [{ type: MARKS.SUPERSCRIPT }]), + {} ) ); richText.expectValue(expectedValue); @@ -346,7 +346,7 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { toggleMarkViaToolbar(MARKS.SUBSCRIPT); const expectedValue = doc( - block(BLOCKS.PARAGRAPH, {}, text('should only be subscript', [{ type: MARKS.SUBSCRIPT }])) + block(BLOCKS.PARAGRAPH, text('should only be subscript', [{ type: MARKS.SUBSCRIPT }]), {}) ); richText.expectValue(expectedValue); }); From 38b2cdb11e9ec0d91136a71bbeb115e4320553f0 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 14:15:18 +0000 Subject: [PATCH 13/23] chore: fixing breaking tests [] --- cypress/integration/rich-text/RichTextEditor.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index d4ac250d3..e9ca60625 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -324,7 +324,7 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { }); it('should remove subscript when superscript mark is selected', () => { - richText.editor.click().type('hello there{selectall}'); + richText.editor.click().type('should only be superscript{selectall}'); toggleMarkViaToolbar(MARKS.SUBSCRIPT); richText.editor.click().type('{selectall}'); toggleMarkViaToolbar(MARKS.SUPERSCRIPT); @@ -332,21 +332,21 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { const expectedValue = doc( block( BLOCKS.PARAGRAPH, - text('should only be superscript', [{ type: MARKS.SUPERSCRIPT }]), - {} + {}, + text('should only be superscript', [{ type: MARKS.SUPERSCRIPT }]) ) ); richText.expectValue(expectedValue); }); it('should remove superscript when subscript mark is selected', () => { - richText.editor.click().type('hello there{selectall}'); + richText.editor.click().type('should only be subscript{selectall}'); toggleMarkViaToolbar(MARKS.SUPERSCRIPT); richText.editor.click().type('{selectall}'); toggleMarkViaToolbar(MARKS.SUBSCRIPT); const expectedValue = doc( - block(BLOCKS.PARAGRAPH, text('should only be subscript', [{ type: MARKS.SUBSCRIPT }]), {}) + block(BLOCKS.PARAGRAPH, {}, text('should only be subscript', [{ type: MARKS.SUBSCRIPT }])) ); richText.expectValue(expectedValue); }); From 5d8bcd3a901508619fa5f7e01917634cb3d1942c Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 16:43:52 +0000 Subject: [PATCH 14/23] chore: adding test for mark validations [] --- packages/rich-text/src/RichTextEditor.mdx | 13 ++++- .../src/helpers/__tests__/validations.test.ts | 52 +++++++++++++++++++ packages/rich-text/src/helpers/validations.ts | 6 ++- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 packages/rich-text/src/helpers/__tests__/validations.test.ts diff --git a/packages/rich-text/src/RichTextEditor.mdx b/packages/rich-text/src/RichTextEditor.mdx index 233305d50..ac9bc4e59 100644 --- a/packages/rich-text/src/RichTextEditor.mdx +++ b/packages/rich-text/src/RichTextEditor.mdx @@ -20,7 +20,7 @@ import { documentToReactComponents } from '@contentful/rich-text-react-renderer' import { validateRichTextDocument } from './test-utils/validation'; import { css } from 'emotion'; import { assets, entries } from '../../reference/src/__fixtures__/fixtures'; - +import { MARKS } from '@contentful/rich-text-types'; # @contentful/field-editor-rich-text @@ -61,7 +61,16 @@ import { RichTextEditor } from '@contentful/field-editor-rich-text'; }; const initialValue = JSON.parse(window.localStorage.getItem('initialValue')) || undefined - const [field, mitt] = useMemo(() => createFakeFieldAPI(mock => mock, initialValue), []); + const [fakeField, mitt] = useMemo(() => createFakeFieldAPI(mock => mock, initialValue), []); + // Overriding mark validation here to show subscript and superscript marks + const field = { + ...fakeField, + validations: [ + { + enabledMarks: Object.values(MARKS) + } + ] + } const isDisabled = window.localStorage.getItem('initialDisabled') || false diff --git a/packages/rich-text/src/helpers/__tests__/validations.test.ts b/packages/rich-text/src/helpers/__tests__/validations.test.ts new file mode 100644 index 000000000..ae0deb358 --- /dev/null +++ b/packages/rich-text/src/helpers/__tests__/validations.test.ts @@ -0,0 +1,52 @@ +import { createFakeFieldAPI } from '@contentful/field-editor-test-utils'; +import { MARKS } from '@contentful/rich-text-types'; + +import { isMarkEnabled } from '../validations'; + +describe('validations', () => { + describe('isMarkEnabled', () => { + [MARKS.BOLD, MARKS.CODE, MARKS.ITALIC, MARKS.UNDERLINE].forEach((mark) => { + it(`returns true for ${mark} mark when no validation explicity set`, () => { + const [field] = createFakeFieldAPI(); + const actual = isMarkEnabled(field, mark); + expect(actual).toBe(true); + }); + it(`returns false for ${mark} mark when validation explicity set without it`, () => { + const [field] = createFakeFieldAPI(); + field.validations = [ + { enabledMarks: Object.values(MARKS).filter((markDefintion) => markDefintion !== mark) }, + ]; + const actual = isMarkEnabled(field, mark); + expect(actual).toBe(false); + }); + it(`returns true for ${mark} mark when validation explicity set with it`, () => { + const [field] = createFakeFieldAPI(); + field.validations = [{ enabledMarks: [mark] }]; + const actual = isMarkEnabled(field, mark); + expect(actual).toBe(true); + }); + }); + it('returns false for superscript mark if no validation explicitly set', () => { + const [field] = createFakeFieldAPI(); + const actual = isMarkEnabled(field, MARKS.SUPERSCRIPT); + expect(actual).toBe(false); + }); + it('returns true for superscript mark if validation explicitly set', () => { + const [field] = createFakeFieldAPI(); + field.validations = [{ enabledMarks: [MARKS.SUPERSCRIPT] }]; + const actual = isMarkEnabled(field, MARKS.SUPERSCRIPT); + expect(actual).toBe(true); + }); + it('returns false for subscript mark if no validation explicitly set', () => { + const [field] = createFakeFieldAPI(); + const actual = isMarkEnabled(field, MARKS.SUBSCRIPT); + expect(actual).toBe(false); + }); + it('returns true for subscript mark if validation explicitly set', () => { + const [field] = createFakeFieldAPI(); + field.validations = [{ enabledMarks: [MARKS.SUBSCRIPT] }]; + const actual = isMarkEnabled(field, MARKS.SUBSCRIPT); + expect(actual).toBe(true); + }); + }); +}); diff --git a/packages/rich-text/src/helpers/validations.ts b/packages/rich-text/src/helpers/validations.ts index c0af0fd94..806722064 100644 --- a/packages/rich-text/src/helpers/validations.ts +++ b/packages/rich-text/src/helpers/validations.ts @@ -1,6 +1,6 @@ /* eslint-disable you-dont-need-lodash-underscore/find */ import { FieldExtensionSDK } from '@contentful/app-sdk'; -import { BLOCKS, INLINES, TOP_LEVEL_BLOCKS } from '@contentful/rich-text-types'; +import { BLOCKS, INLINES, MARKS, TOP_LEVEL_BLOCKS } from '@contentful/rich-text-types'; import find from 'lodash/find'; import flow from 'lodash/flow'; import get from 'lodash/get'; @@ -30,6 +30,10 @@ const isFormattingOptionEnabled = (field, validationType, nodeTypeOrMark) => { // TODO: In the future, validations will always be opt-in. In that case // we don't need this step. if (enabledFormattings === undefined) { + if ([MARKS.SUBSCRIPT, MARKS.SUPERSCRIPT].includes(nodeTypeOrMark)) { + return false; + } + return true; } From f9563390e089a703c6791ada80ea5686d4ca08ed Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 17:02:18 +0000 Subject: [PATCH 15/23] chore: using override function for mocks [] --- .../src/helpers/__tests__/validations.test.ts | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/rich-text/src/helpers/__tests__/validations.test.ts b/packages/rich-text/src/helpers/__tests__/validations.test.ts index ae0deb358..c6dcf2be0 100644 --- a/packages/rich-text/src/helpers/__tests__/validations.test.ts +++ b/packages/rich-text/src/helpers/__tests__/validations.test.ts @@ -12,16 +12,23 @@ describe('validations', () => { expect(actual).toBe(true); }); it(`returns false for ${mark} mark when validation explicity set without it`, () => { - const [field] = createFakeFieldAPI(); - field.validations = [ - { enabledMarks: Object.values(MARKS).filter((markDefintion) => markDefintion !== mark) }, - ]; + const [field] = createFakeFieldAPI((field) => { + field.validations = [ + { + enabledMarks: Object.values(MARKS).filter((markDefintion) => markDefintion !== mark), + }, + ]; + return field; + }); + const actual = isMarkEnabled(field, mark); expect(actual).toBe(false); }); it(`returns true for ${mark} mark when validation explicity set with it`, () => { - const [field] = createFakeFieldAPI(); - field.validations = [{ enabledMarks: [mark] }]; + const [field] = createFakeFieldAPI((field) => { + field.validations = [{ enabledMarks: [mark] }]; + return field; + }); const actual = isMarkEnabled(field, mark); expect(actual).toBe(true); }); @@ -32,8 +39,10 @@ describe('validations', () => { expect(actual).toBe(false); }); it('returns true for superscript mark if validation explicitly set', () => { - const [field] = createFakeFieldAPI(); - field.validations = [{ enabledMarks: [MARKS.SUPERSCRIPT] }]; + const [field] = createFakeFieldAPI((field) => { + field.validations = [{ enabledMarks: [MARKS.SUPERSCRIPT] }]; + return field; + }); const actual = isMarkEnabled(field, MARKS.SUPERSCRIPT); expect(actual).toBe(true); }); @@ -43,8 +52,10 @@ describe('validations', () => { expect(actual).toBe(false); }); it('returns true for subscript mark if validation explicitly set', () => { - const [field] = createFakeFieldAPI(); - field.validations = [{ enabledMarks: [MARKS.SUBSCRIPT] }]; + const [field] = createFakeFieldAPI((field) => { + field.validations = [{ enabledMarks: [MARKS.SUBSCRIPT] }]; + return field; + }); const actual = isMarkEnabled(field, MARKS.SUBSCRIPT); expect(actual).toBe(true); }); From 5fee0717a38a1c83a518ddcf117624fe452f8bfa Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Tue, 15 Nov 2022 17:30:10 +0000 Subject: [PATCH 16/23] chore: adding tests for hiding showing super and subscript marks [] --- .../rich-text/RichTextEditor.spec.ts | 25 +++++++++++++++++++ packages/rich-text/src/RichTextEditor.mdx | 14 +++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index e9ca60625..fc5f7e436 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -208,7 +208,32 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { }); describe('Marks', () => { + const findMarkViaToolvar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`); const toggleMarkViaToolbar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`).click(); + + it(`hides ${MARKS.SUBSCRIPT} and ${MARKS.SUPERSCRIPT} marks if not explicitly allowed`, () => { + cy.setFieldValidations([]); + cy.reload(); + findMarkViaToolvar(MARKS.SUPERSCRIPT).should('not.exist'); + findMarkViaToolvar(MARKS.SUBSCRIPT).should('not.exist'); + }); + + it(`shows ${MARKS.SUBSCRIPT} and ${MARKS.SUPERSCRIPT} marks if explicitly allowed`, () => { + cy.setFieldValidations([{ enabledMarks: [MARKS.SUPERSCRIPT, MARKS.SUBSCRIPT] }]); + cy.reload(); + findMarkViaToolvar(MARKS.SUPERSCRIPT).should('be.visible'); + findMarkViaToolvar(MARKS.SUBSCRIPT).should('be.visible'); + }); + + it(`shows ${MARKS.BOLD}, ${MARKS.ITALIC}, ${MARKS.UNDERLINE}, ${MARKS.CODE} if not explicitly allowed`, () => { + cy.setFieldValidations([]); + cy.reload(); + findMarkViaToolvar(MARKS.BOLD).should('be.visible'); + findMarkViaToolvar(MARKS.ITALIC).should('be.visible'); + findMarkViaToolvar(MARKS.UNDERLINE).should('be.visible'); + findMarkViaToolvar(MARKS.CODE).should('be.visible'); + }); + [ [MARKS.BOLD, `{${mod}}b`], [MARKS.ITALIC, `{${mod}}i`], diff --git a/packages/rich-text/src/RichTextEditor.mdx b/packages/rich-text/src/RichTextEditor.mdx index ac9bc4e59..2de965de5 100644 --- a/packages/rich-text/src/RichTextEditor.mdx +++ b/packages/rich-text/src/RichTextEditor.mdx @@ -61,16 +61,16 @@ import { RichTextEditor } from '@contentful/field-editor-rich-text'; }; const initialValue = JSON.parse(window.localStorage.getItem('initialValue')) || undefined - const [fakeField, mitt] = useMemo(() => createFakeFieldAPI(mock => mock, initialValue), []); - // Overriding mark validation here to show subscript and superscript marks - const field = { - ...fakeField, - validations: [ + const fieldValidations = JSON.parse(window.localStorage.getItem('fieldValidations')) || undefined + const [field, mitt] = useMemo(() => createFakeFieldAPI(mock => { + // Overriding mark validation here to show all marks if no fieldValidations set + mock.validations = !!fieldValidations ? fieldValidations : [ { enabledMarks: Object.values(MARKS) } - ] - } + ]; + return mock + }, initialValue), []); const isDisabled = window.localStorage.getItem('initialDisabled') || false From 879d3a232829b8643d38c8784c221636034cb336 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 11:01:21 +0000 Subject: [PATCH 17/23] chore: tidying up [] --- .../rich-text/RichTextEditor.spec.ts | 18 +++++++++--------- .../rich-text/src/plugins/Marks/Subscript.tsx | 6 +----- .../src/plugins/Marks/Superscript.tsx | 4 ---- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index fc5f7e436..1722ec8fe 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -208,30 +208,30 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { }); describe('Marks', () => { - const findMarkViaToolvar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`); + const findMarkViaToolbar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`); const toggleMarkViaToolbar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`).click(); it(`hides ${MARKS.SUBSCRIPT} and ${MARKS.SUPERSCRIPT} marks if not explicitly allowed`, () => { cy.setFieldValidations([]); cy.reload(); - findMarkViaToolvar(MARKS.SUPERSCRIPT).should('not.exist'); - findMarkViaToolvar(MARKS.SUBSCRIPT).should('not.exist'); + findMarkViaToolbar(MARKS.SUPERSCRIPT).should('not.exist'); + findMarkViaToolbar(MARKS.SUBSCRIPT).should('not.exist'); }); it(`shows ${MARKS.SUBSCRIPT} and ${MARKS.SUPERSCRIPT} marks if explicitly allowed`, () => { cy.setFieldValidations([{ enabledMarks: [MARKS.SUPERSCRIPT, MARKS.SUBSCRIPT] }]); cy.reload(); - findMarkViaToolvar(MARKS.SUPERSCRIPT).should('be.visible'); - findMarkViaToolvar(MARKS.SUBSCRIPT).should('be.visible'); + findMarkViaToolbar(MARKS.SUPERSCRIPT).should('be.visible'); + findMarkViaToolbar(MARKS.SUBSCRIPT).should('be.visible'); }); it(`shows ${MARKS.BOLD}, ${MARKS.ITALIC}, ${MARKS.UNDERLINE}, ${MARKS.CODE} if not explicitly allowed`, () => { cy.setFieldValidations([]); cy.reload(); - findMarkViaToolvar(MARKS.BOLD).should('be.visible'); - findMarkViaToolvar(MARKS.ITALIC).should('be.visible'); - findMarkViaToolvar(MARKS.UNDERLINE).should('be.visible'); - findMarkViaToolvar(MARKS.CODE).should('be.visible'); + findMarkViaToolbar(MARKS.BOLD).should('be.visible'); + findMarkViaToolbar(MARKS.ITALIC).should('be.visible'); + findMarkViaToolbar(MARKS.UNDERLINE).should('be.visible'); + findMarkViaToolbar(MARKS.CODE).should('be.visible'); }); [ diff --git a/packages/rich-text/src/plugins/Marks/Subscript.tsx b/packages/rich-text/src/plugins/Marks/Subscript.tsx index 71162b306..fab13c0ff 100644 --- a/packages/rich-text/src/plugins/Marks/Subscript.tsx +++ b/packages/rich-text/src/plugins/Marks/Subscript.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; import { SubscriptIcon } from '@contentful/f36-icons'; -import { createSubscriptPlugin as createDefaultSubscriptPlugin } from '@udecode/plate-basic-marks'; import { MARKS } from '@contentful/rich-text-types'; +import { createSubscriptPlugin as createDefaultSubscriptPlugin } from '@udecode/plate-basic-marks'; import * as Slate from 'slate-react'; -import { someHtmlElement } from '@udecode/plate-core'; import { RichTextPlugin } from '../../types'; import { createMarkToolbarButton } from './components/MarkToolbarButton'; @@ -33,8 +32,5 @@ export const createSubscriptPlugin = (): RichTextPlugin => validNodeName: ['SUB'], }, ], - query: (el) => { - return !someHtmlElement(el, (node) => node.style.fontWeight === 'normal'); - }, }, }); diff --git a/packages/rich-text/src/plugins/Marks/Superscript.tsx b/packages/rich-text/src/plugins/Marks/Superscript.tsx index fd31fa25c..47639f288 100644 --- a/packages/rich-text/src/plugins/Marks/Superscript.tsx +++ b/packages/rich-text/src/plugins/Marks/Superscript.tsx @@ -3,7 +3,6 @@ import * as React from 'react'; import { SuperscriptIcon } from '@contentful/f36-icons'; import { MARKS } from '@contentful/rich-text-types'; import { createSuperscriptPlugin as createDefaultSuperscriptPlugin } from '@udecode/plate-basic-marks'; -import { someHtmlElement } from '@udecode/plate-core'; import * as Slate from 'slate-react'; import { RichTextPlugin } from '../../types'; @@ -33,8 +32,5 @@ export const createSuperscriptPlugin = (): RichTextPlugin => validNodeName: ['SUP'], }, ], - query: (el) => { - return !someHtmlElement(el, (node) => node.style.fontWeight === 'normal'); - }, }, }); From 410c9164adf8e30875add75e8f3349d70dc13538 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 11:13:23 +0000 Subject: [PATCH 18/23] chore: tidying up [] --- packages/rich-text/src/plugins/Marks/helpers.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/rich-text/src/plugins/Marks/helpers.ts b/packages/rich-text/src/plugins/Marks/helpers.ts index c7123255b..a7bcb07ef 100644 --- a/packages/rich-text/src/plugins/Marks/helpers.ts +++ b/packages/rich-text/src/plugins/Marks/helpers.ts @@ -9,12 +9,9 @@ export const toggleMarkAndDeactivateConflictingMarks = ( editor: PlateEditor, mark: MARKS ) => { - toggleMark(editor, { key: mark }); - if (mark === MARKS.SUBSCRIPT && isMarkActive(editor, MARKS.SUPERSCRIPT)) { - toggleMark(editor, { key: MARKS.SUPERSCRIPT }); - } else if (mark === MARKS.SUPERSCRIPT && isMarkActive(editor, MARKS.SUBSCRIPT)) { - toggleMark(editor, { key: MARKS.SUBSCRIPT }); - } + const subs = [MARKS.SUPERSCRIPT, MARKS.SUBSCRIPT]; + const clear = subs.includes(mark) ? subs : []; + toggleMark(editor, { key: mark, clear }); }; export const buildMarkEventHandler = From 9b2ffd3abe228bc4264f0bfc8fa53609b68a98e4 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 11:19:13 +0000 Subject: [PATCH 19/23] chore: updating cypress test name [] --- cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts b/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts index cc3209f3a..c4915d4ac 100644 --- a/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.Pasting.spec.ts @@ -275,9 +275,9 @@ describe( }); describe('Superscript and subscript marks', () => { - it('works when pasting subscript and superscript from another RT editor', () => { + it('works when pasting subscript and superscript from a google doc', () => { // A simple "hello world" text with marks: superscript and subscript. - // Copied from the RT editor + // Copied from a google doc richText.editor.click().paste({ 'text/plain': 'HelloWorld', 'text/html': From 9f7e651bace9ffaa50c51ea591d5f37f31cc8a81 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 11:24:53 +0000 Subject: [PATCH 20/23] chore: removing logic and tests [] --- .../rich-text/RichTextEditor.spec.ts | 14 ---------- .../src/helpers/__tests__/validations.test.ts | 26 ------------------- packages/rich-text/src/helpers/validations.ts | 6 +---- 3 files changed, 1 insertion(+), 45 deletions(-) diff --git a/cypress/integration/rich-text/RichTextEditor.spec.ts b/cypress/integration/rich-text/RichTextEditor.spec.ts index 1722ec8fe..06dded3a1 100644 --- a/cypress/integration/rich-text/RichTextEditor.spec.ts +++ b/cypress/integration/rich-text/RichTextEditor.spec.ts @@ -211,20 +211,6 @@ describe('Rich Text Editor', { viewportHeight: 2000 }, () => { const findMarkViaToolbar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`); const toggleMarkViaToolbar = (mark: MARKS) => cy.findByTestId(`${mark}-toolbar-button`).click(); - it(`hides ${MARKS.SUBSCRIPT} and ${MARKS.SUPERSCRIPT} marks if not explicitly allowed`, () => { - cy.setFieldValidations([]); - cy.reload(); - findMarkViaToolbar(MARKS.SUPERSCRIPT).should('not.exist'); - findMarkViaToolbar(MARKS.SUBSCRIPT).should('not.exist'); - }); - - it(`shows ${MARKS.SUBSCRIPT} and ${MARKS.SUPERSCRIPT} marks if explicitly allowed`, () => { - cy.setFieldValidations([{ enabledMarks: [MARKS.SUPERSCRIPT, MARKS.SUBSCRIPT] }]); - cy.reload(); - findMarkViaToolbar(MARKS.SUPERSCRIPT).should('be.visible'); - findMarkViaToolbar(MARKS.SUBSCRIPT).should('be.visible'); - }); - it(`shows ${MARKS.BOLD}, ${MARKS.ITALIC}, ${MARKS.UNDERLINE}, ${MARKS.CODE} if not explicitly allowed`, () => { cy.setFieldValidations([]); cy.reload(); diff --git a/packages/rich-text/src/helpers/__tests__/validations.test.ts b/packages/rich-text/src/helpers/__tests__/validations.test.ts index c6dcf2be0..7dacba707 100644 --- a/packages/rich-text/src/helpers/__tests__/validations.test.ts +++ b/packages/rich-text/src/helpers/__tests__/validations.test.ts @@ -33,31 +33,5 @@ describe('validations', () => { expect(actual).toBe(true); }); }); - it('returns false for superscript mark if no validation explicitly set', () => { - const [field] = createFakeFieldAPI(); - const actual = isMarkEnabled(field, MARKS.SUPERSCRIPT); - expect(actual).toBe(false); - }); - it('returns true for superscript mark if validation explicitly set', () => { - const [field] = createFakeFieldAPI((field) => { - field.validations = [{ enabledMarks: [MARKS.SUPERSCRIPT] }]; - return field; - }); - const actual = isMarkEnabled(field, MARKS.SUPERSCRIPT); - expect(actual).toBe(true); - }); - it('returns false for subscript mark if no validation explicitly set', () => { - const [field] = createFakeFieldAPI(); - const actual = isMarkEnabled(field, MARKS.SUBSCRIPT); - expect(actual).toBe(false); - }); - it('returns true for subscript mark if validation explicitly set', () => { - const [field] = createFakeFieldAPI((field) => { - field.validations = [{ enabledMarks: [MARKS.SUBSCRIPT] }]; - return field; - }); - const actual = isMarkEnabled(field, MARKS.SUBSCRIPT); - expect(actual).toBe(true); - }); }); }); diff --git a/packages/rich-text/src/helpers/validations.ts b/packages/rich-text/src/helpers/validations.ts index 806722064..c0af0fd94 100644 --- a/packages/rich-text/src/helpers/validations.ts +++ b/packages/rich-text/src/helpers/validations.ts @@ -1,6 +1,6 @@ /* eslint-disable you-dont-need-lodash-underscore/find */ import { FieldExtensionSDK } from '@contentful/app-sdk'; -import { BLOCKS, INLINES, MARKS, TOP_LEVEL_BLOCKS } from '@contentful/rich-text-types'; +import { BLOCKS, INLINES, TOP_LEVEL_BLOCKS } from '@contentful/rich-text-types'; import find from 'lodash/find'; import flow from 'lodash/flow'; import get from 'lodash/get'; @@ -30,10 +30,6 @@ const isFormattingOptionEnabled = (field, validationType, nodeTypeOrMark) => { // TODO: In the future, validations will always be opt-in. In that case // we don't need this step. if (enabledFormattings === undefined) { - if ([MARKS.SUBSCRIPT, MARKS.SUPERSCRIPT].includes(nodeTypeOrMark)) { - return false; - } - return true; } From d41af12273a8921133e3e9c1a8cd36e9f7c6e467 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 13:07:09 +0000 Subject: [PATCH 21/23] chore: updating snapshot title [] --- .../rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap index 7d7c65c3d..52758afd8 100644 --- a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap +++ b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap @@ -2995,7 +2995,7 @@ exports[`Rich Text Editor > Tables > removes table wrappers when pasting a singl ] }; -exports[`Rich Text Editor > Superscript and subscript marks > works when pasting from another RT editor #0`] = +exports[`Rich Text Editor > Superscript and subscript marks > works when pasting subscript and superscript from a google doc #0`] = { "content": [ { From 9f37decebe8a459651cdb85caa322a62f72464da Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 13:09:19 +0000 Subject: [PATCH 22/23] chore: updating snapshot [] --- .../rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap index 52758afd8..074b63675 100644 --- a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap +++ b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap @@ -3028,7 +3028,7 @@ exports[`Rich Text Editor > Superscript and subscript marks > works when pasting "nodeType": "document" }; -exports[`Rich Text Editor > Superscript and subscript marks > works when pasting subscript and superscript from another RT editor #0`] = +exports[`Rich Text Editor > Superscript and subscript marks > works when pasting subscript and superscript from a google doc #0`] = { "content": [ { From af8f78b2f72b671a055b8062f27ed516d1b4e518 Mon Sep 17 00:00:00 2001 From: Aodhagan Murphy Date: Wed, 16 Nov 2022 13:12:19 +0000 Subject: [PATCH 23/23] chore: updating snapshot [] --- .../rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap index 074b63675..35a69dcf8 100644 --- a/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap +++ b/cypress/integration/rich-text/__snapshots__/RichTextEditor.Pasting.spec.ts.snap @@ -2995,7 +2995,7 @@ exports[`Rich Text Editor > Tables > removes table wrappers when pasting a singl ] }; -exports[`Rich Text Editor > Superscript and subscript marks > works when pasting subscript and superscript from a google doc #0`] = +exports[`Rich Text Editor > works when pasting from another RT editor > works when pasting subscript and superscript from a google doc #0`] = { "content": [ {