Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(RichTextInput): deserialization of <sup> and <sub> #2523

Merged
merged 5 commits into from
Jun 6, 2023

Conversation

kark
Copy link
Contributor

@kark kark commented May 16, 2023

Summary

This PR is meant to fix:

  • <sup> and <sub> deserialization
    2023-06-01 11 00 15
  • issue with rich text state resetting
  • removes unnecessary wrapping every text node with paragraph in the deserialization function
  • adds a more complex story to enable manual tests of <RichTextInput> and LocalizedRichTextInput>

⚠️ ⚠️ ⚠️ it does not cover #2522 ⚠️ ⚠️ ⚠️

@changeset-bot
Copy link

changeset-bot bot commented May 16, 2023

🦋 Changeset detected

Latest commit: f2f725f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 93 packages
Name Type
@commercetools-uikit/rich-text-utils Patch
@commercetools-uikit/localized-rich-text-input Patch
@commercetools-uikit/rich-text-input Patch
@commercetools-uikit/inputs Patch
@commercetools-frontend/ui-kit Patch
@commercetools-uikit/design-system Patch
@commercetools-uikit/calendar-time-utils Patch
@commercetools-uikit/calendar-utils Patch
@commercetools-uikit/hooks Patch
@commercetools-uikit/i18n Patch
@commercetools-uikit/localized-utils Patch
@commercetools-uikit/utils Patch
@commercetools-uikit/accessible-hidden Patch
@commercetools-uikit/avatar Patch
@commercetools-uikit/card Patch
@commercetools-uikit/collapsible-motion Patch
@commercetools-uikit/collapsible-panel Patch
@commercetools-uikit/collapsible Patch
@commercetools-uikit/constraints Patch
@commercetools-uikit/data-table-manager Patch
@commercetools-uikit/data-table Patch
@commercetools-uikit/field-errors Patch
@commercetools-uikit/field-label Patch
@commercetools-uikit/grid Patch
@commercetools-uikit/icons Patch
@commercetools-uikit/label Patch
@commercetools-uikit/link Patch
@commercetools-uikit/loading-spinner Patch
@commercetools-uikit/messages Patch
@commercetools-uikit/notifications Patch
@commercetools-uikit/pagination Patch
@commercetools-uikit/primary-action-dropdown Patch
@commercetools-uikit/stamp Patch
@commercetools-uikit/tag Patch
@commercetools-uikit/text Patch
@commercetools-uikit/tooltip Patch
@commercetools-uikit/view-switcher Patch
@commercetools-uikit/accessible-button Patch
@commercetools-uikit/flat-button Patch
@commercetools-uikit/icon-button Patch
@commercetools-uikit/link-button Patch
@commercetools-uikit/primary-button Patch
@commercetools-uikit/secondary-button Patch
@commercetools-uikit/secondary-icon-button Patch
@commercetools-uikit/async-creatable-select-field Patch
@commercetools-uikit/async-select-field Patch
@commercetools-uikit/creatable-select-field Patch
@commercetools-uikit/date-field Patch
@commercetools-uikit/date-range-field Patch
@commercetools-uikit/date-time-field Patch
@commercetools-uikit/localized-multiline-text-field Patch
@commercetools-uikit/localized-text-field Patch
@commercetools-uikit/money-field Patch
@commercetools-uikit/multiline-text-field Patch
@commercetools-uikit/number-field Patch
@commercetools-uikit/password-field Patch
@commercetools-uikit/radio-field Patch
@commercetools-uikit/search-select-field Patch
@commercetools-uikit/select-field Patch
@commercetools-uikit/text-field Patch
@commercetools-uikit/time-field Patch
@commercetools-uikit/async-creatable-select-input Patch
@commercetools-uikit/async-select-input Patch
@commercetools-uikit/checkbox-input Patch
@commercetools-uikit/creatable-select-input Patch
@commercetools-uikit/date-input Patch
@commercetools-uikit/date-range-input Patch
@commercetools-uikit/date-time-input Patch
@commercetools-uikit/input-utils Patch
@commercetools-uikit/localized-money-input Patch
@commercetools-uikit/localized-multiline-text-input Patch
@commercetools-uikit/localized-text-input Patch
@commercetools-uikit/money-input Patch
@commercetools-uikit/multiline-text-input Patch
@commercetools-uikit/number-input Patch
@commercetools-uikit/password-input Patch
@commercetools-uikit/radio-input Patch
@commercetools-uikit/search-select-input Patch
@commercetools-uikit/search-text-input Patch
@commercetools-uikit/select-input Patch
@commercetools-uikit/select-utils Patch
@commercetools-uikit/selectable-search-input Patch
@commercetools-uikit/text-input Patch
@commercetools-uikit/time-input Patch
@commercetools-uikit/toggle-input Patch
@commercetools-uikit/spacings-inline Patch
@commercetools-uikit/spacings-inset-squish Patch
@commercetools-uikit/spacings-inset Patch
@commercetools-uikit/spacings-stack Patch
@commercetools-uikit/buttons Patch
@commercetools-uikit/fields Patch
@commercetools-uikit/spacings Patch
visual-testing-app Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented May 16, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
ui-kit ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 6, 2023 6:53am

el: HTMLElement | ChildNode,
textContent: TElement | TText | (TElement | TText)[]
) =>
el.parentNode?.nodeName === 'BODY' // root element, because body is eventually turned to React fragment
? wrapWithParagraph(textContent)
? wrapWithFragment(textContent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be a problem in case of new line?

In the below screenshot, there are two individual elements and above condition would be true since the parentNode is 'BODY' in this case, isn't it?

This would make the text to be in the single line without any space between them if the <p> tag is removed.

Screenshot 2023-05-16 at 10 47 04

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks,
I'm not sure I 100% understand the question but let me try to answer.
You're right that in this case we'll have:

Body                                          
  |                                            
  |                                            
  |----P                                       
  |    |                                       
  |    |                                       
  |    |                                       
  |    +------ #text (this is first line)                        
  |                                            
  |                                            
  +-----P                                      
        |                                      
        |                                      
        +------#text (this is second line)                           

This function only replaces <body> with <></>.
Therefore, if you provide:

<LocalizedRichTextInput
        onChange={() => {}}
        value={{
          en: '<p>this is the first line</p><p>this is the second line</p>',
        }}
        selectedLanguage="en"
        horizontalConstraint={7}
        defaultExpandMultilineText={true}
      />

the wrapping paragraphs are there.
I don't get the part how do you expect the <p>s to be removed? They will always be there if this content is typed in the input by the user.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed explanation. I understand what you mean.
However I am confused since you linked this issue which talks about removing <p> tags from unformatted text content. So does this PR removes <p> only if there is only one <p> tag at the top level?

This was my overall assumption.
If users type anything in rich text editor without formatting (i.e, not clicking bold or italic, etc) then text will not be wrapped by any elements like <p>.
If the users type anything and format their content, then respective HTML elements will be wrapped.
Is my understanding or expectations correct or is this something not possible to achieve it?

Copy link
Contributor Author

@kark kark May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again,

If users type anything in rich text editor without formatting (i.e, not clicking bold or italic, etc) then text will not be wrapped by any elements like <p>.

Got it. Not sure, I need to check that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If users type anything in rich text editor without formatting (i.e, not clicking bold or italic, etc) then text will not be wrapped by any elements like <p>.
If the users type anything and format their content, then respective HTML elements will be wrapped.
Is my understanding or expectations correct or is this something not possible to achieve it?

To my understanding, a richt-text input always emits HTML and always wraps the content into an element by default. For instance, typing just some text is considered a paragraph thus wrapping it into a <p> is in theory correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not sure about this one, but since the component is formatting text, I believe it needs to output some kind of rich information where we don’t only get the content but also its structure and styles. I mean, we need to know if a text is part of a list, if it’s a header, etc.

For what I can see in other libraries, the output uses to be HTML (which includes content, structure and styles) or JSON where all of those can be represented (example).

If the first element in the output is a list, I guess we wouldn’t be questioning if we want it to be wrapped in a ul/ol.

I’m not sure I understand the underlying problem.

@kark kark force-pushed the kk-change-root-node-rich-text-input branch from eb896ce to e0df0c6 Compare May 31, 2023 07:51
@kark kark changed the title fix(RichTextInput): wrap root node with a fragment instead of a paragraph fix(RichTextInput): deserialization of <sup> and <sub> May 31, 2023
@kark kark force-pushed the kk-change-root-node-rich-text-input branch from 1ba547b to c2aa1bb Compare May 31, 2023 10:44
editor.apply({
type: 'insert_node',
path: [0],
node: newState[0],
Copy link
Contributor Author

@kark kark May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously the implementation was buggy, as only the first provided node was added when ref.current.resetValue function was called

Comment on lines -282 to -285
// each non-empty text node must be wrapped with a paragraph
return children.map((child) =>
Text.isText(child) && child.text ? wrapWithParagraph(child) : child
);
Copy link
Contributor Author

@kark kark May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed, it was added as a hot fix of a bug, but text nodes can in fact be added without a wrapping paragraph. This was added here but this approach was not correct as I think of it in retrospect.

Comment on lines +207 to +206
(Array.isArray(value) &&
value.every((node) => SlateElement.isElement(node) || Text.isText(node)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a valid condition now, since text nodes don't need a wrapping paragraph

Comment on lines +152 to +153
SUP: () => ({ superscript: true }),
SUB: () => ({ subscript: true }),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually the missing piece that is a root cause of the bug

@kark kark marked this pull request as ready for review May 31, 2023 12:05
@kark kark requested review from a team and jaikumar-tj May 31, 2023 12:06
);
});
});
});
describe('multiple nested text nodes within parent text node', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Copy link
Contributor

@CarlosCortizasCT CarlosCortizasCT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! 💪

Copy link
Contributor

@chloe0592 chloe0592 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 😎 👏

Copy link
Contributor

@Rhotimee Rhotimee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @kark 👏🏽👏🏽

@kark kark force-pushed the kk-change-root-node-rich-text-input branch from 6b441ec to f2f725f Compare June 6, 2023 06:52
@kark kark merged commit ac30c7d into main Jun 6, 2023
@kark kark deleted the kk-change-root-node-rich-text-input branch June 6, 2023 07:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants