diff --git a/.changeset/healthy-poems-approve.md b/.changeset/healthy-poems-approve.md new file mode 100644 index 0000000000..57cc537c31 --- /dev/null +++ b/.changeset/healthy-poems-approve.md @@ -0,0 +1,6 @@ +--- +'@commercetools-uikit/rich-text-input': minor +'@commercetools-uikit/rich-text-utils': minor +--- + +rich-text-inputs are supporting soft-linebreaks (shift + enter) now diff --git a/packages/components/inputs/rich-text-input/src/editor.tsx b/packages/components/inputs/rich-text-input/src/editor.tsx index b72f0fd697..b2283f2408 100644 --- a/packages/components/inputs/rich-text-input/src/editor.tsx +++ b/packages/components/inputs/rich-text-input/src/editor.tsx @@ -24,6 +24,7 @@ import { HiddenInput, Element, Leaf, + Softbreaker, toggleMark, resetEditor, focusEditor, @@ -132,10 +133,10 @@ const Editor = forwardRef((props: TEditorProps, forwardedRef) => { }, [editor] ); - /* + /* Resetting the editor requires access to `editor` object returned from `useSlate` hook. Therefore, `reset` function is attached to the passed `ref` object via `useImperativeHandle` hook - to be called from the parent component. + to be called from the parent component. e.g. */ useImperativeHandle(forwardedRef, () => { @@ -205,6 +206,11 @@ const Editor = forwardRef((props: TEditorProps, forwardedRef) => { break; } } + + if (event.shiftKey && event.key === 'Enter') { + event.preventDefault(); + editor.insertText(Softbreaker.placeholderCharacter); + } }} /> {props.children} diff --git a/packages/components/inputs/rich-text-input/src/rich-text-input.story.js b/packages/components/inputs/rich-text-input/src/rich-text-input.story.js index a28b7b3432..8a866e5412 100644 --- a/packages/components/inputs/rich-text-input/src/rich-text-input.story.js +++ b/packages/components/inputs/rich-text-input/src/rich-text-input.story.js @@ -16,7 +16,8 @@ import Readme from '../README.md'; // Create our initial value... -const initialValue = '

H1 heading

'; +const initialValue = + '

Heading

This is a paragraph.

New sentence, same paragraph, but with soft-linebreak (Shift + Enter).

'; storiesOf('Components|Inputs', module) .addDecorator(withKnobs) @@ -92,8 +93,12 @@ storiesOf('Components|Inputs', module) onChange={onChange} value={value} /> - Output -
{value}
+ + {value === initialValue ? 'Initial HTML-Input:' : 'HTML-Output:'} + +
+            {value}
+          
); diff --git a/packages/components/inputs/rich-text-utils/src/html/html.spec.js b/packages/components/inputs/rich-text-utils/src/html/html.spec.js index 293af85355..81fc2c7ee1 100644 --- a/packages/components/inputs/rich-text-utils/src/html/html.spec.js +++ b/packages/components/inputs/rich-text-utils/src/html/html.spec.js @@ -106,7 +106,7 @@ describe('html', () => { '
  1. Computermouse for controlling
hello

world


'; expect(html.serialize(html.deserialize(htmlValue))).toEqual( - '
  1. Computermouse for controlling
hello

world

' + '
  1. Computermouse for controlling
hello

world


' ); }); }); @@ -124,35 +124,69 @@ describe('html', () => { describe('with invalid markup passed to text node', () => { it('should properly serialize and replace with information', () => { const htmlValue = `

\r\nBitte beachten Sie: Die Lieferung erfolgt nach Verfügbarkeit - Jahrgangs- und Designwünschen können wir leider nicht nachkommen. Wir danken Ihnen für Ihr Verständnis.\r\n

\r\n\r\n

Informationen zum Gold Känguru 1/4

\r\n

\r\nDer Australian Nugget (Gold Känguru) ist eine australische Goldmünze, die erstmals 1986 von der Perth Mint geprägt wurde und sich vor allem dank der jährlich wechselnden Motive auf der Vorderseite weltweiter Beliebtheit erfreut. Die Münze hat einen Feingehalt von 999,9 und gilt als offizielles Zahlungsmittel.\r\n

\r\n\r\n

\r\nSeit 1987 wird der Australian Nugget in den Stückelungen 1/20 Unze, 1/10 Unze, 1/4 Unze, 1/2 Unze und 1 Unze geprägt, der Nennwert liegt zwischen 5 und 100 australischen Dollar. Mittlerweile existieren aber auch größere Stückelungen mit einem Gewicht von 2 Unzen, 10 Unzen sowie 1 Kilogramm. Im Jahr 2010 wurde eine 2-Dollar-Version der Münze mit einem Gewicht von 0,5 Gramm aufgelegt. 2011 stellte die Perth Mint zudem eine Ausgabe der Münze mit einem Gewicht von 1 Tonne vor – damit ist der Gold Känguru zugleich die kleinste und grösste Anlagemünze der Welt.\r\n

\r\n\r\n

\r\nBis 1989 wurden auf der Vorderseite der Münze außergewöhnliche, in Australien gefundene Goldnuggets abgebildet – daher auch der Name Australian Nugget. Seit 1990 zeigt die Goldmünze jährlich wechselnde Motive von Kängurus, der offizielle Name lautet seitdem „Australian Kangaroo“. Größere Einheiten des Gold Känguru, wie die 2-Unzen-, 10-Unzen- und 1-Kilogramm-Version tragen jährlich das gleiche Motiv des „Red Kangaroo“. Auf der Rückseite der Goldmünze findet sich - wie bei allen Commonwealth-Münzen - das Porträt von Königin Elizabeth II.\r\n

\r\n

\r\n

\r\n

\r\nGold Känguru 1/4 kaufen bei philoro kaufen\r\n

\r\n

\r\n\tNeben der Gold Känguru 1/4/strong> finden Sie bei uns eine breite Auswahl renommierter Goldmünzen aus aller Welt. Gerne bieten wir Ihnen zum Thema Anlagemünzen unsere umfassende Beratung an. Wir garantieren für die von uns vertriebenen Produkte höchste Qualität. Deshalb arbeiten wir ausschliesslich mit international anerkannten und etablierten Herstellern zusammen.\r\n

\r\n\r\n

\r\nBesuchen Sie uns in einer unserer Filialen und überzeugen Sie sich selbst, oder bestellen Sie einfach und bequem online.\r\n

\r\n`; + expect(html.serialize(html.deserialize(htmlValue))).toEqual( + `


Bitte beachten Sie: Die Lieferung erfolgt nach Verfügbarkeit - Jahrgangs- und Designwünschen können wir leider nicht nachkommen. Wir danken Ihnen für Ihr Verständnis.



Informationen zum Gold Känguru 1/4



Der Australian Nugget (Gold Känguru) ist eine australische Goldmünze, die erstmals 1986 von der Perth Mint geprägt wurde und sich vor allem dank der jährlich wechselnden Motive auf der Vorderseite weltweiter Beliebtheit erfreut. Die Münze hat einen Feingehalt von 999,9 und gilt als offizielles Zahlungsmittel.




Seit 1987 wird der Australian Nugget in den Stückelungen 1/20 Unze, 1/10 Unze, 1/4 Unze, 1/2 Unze und 1 Unze geprägt, der Nennwert liegt zwischen 5 und 100 australischen Dollar. Mittlerweile existieren aber auch größere Stückelungen mit einem Gewicht von 2 Unzen, 10 Unzen sowie 1 Kilogramm. Im Jahr 2010 wurde eine 2-Dollar-Version der Münze mit einem Gewicht von 0,5 Gramm aufgelegt. 2011 stellte die Perth Mint zudem eine Ausgabe der Münze mit einem Gewicht von 1 Tonne vor – damit ist der Gold Känguru zugleich die kleinste und grösste Anlagemünze der Welt.




Bis 1989 wurden auf der Vorderseite der Münze außergewöhnliche, in Australien gefundene Goldnuggets abgebildet – daher auch der Name Australian Nugget. Seit 1990 zeigt die Goldmünze jährlich wechselnde Motive von Kängurus, der offizielle Name lautet seitdem „Australian Kangaroo“. Größere Einheiten des Gold Känguru, wie die 2-Unzen-, 10-Unzen- und 1-Kilogramm-Version tragen jährlich das gleiche Motiv des „Red Kangaroo“. Auf der Rückseite der Goldmünze findet sich - wie bei allen Commonwealth-Münzen - das Porträt von Königin Elizabeth II.





Gold Känguru 1/4 kaufen bei philoro kaufen



\tNeben der Gold Känguru 1/4/strong> finden Sie bei uns eine breite Auswahl renommierter Goldmünzen aus aller Welt. Gerne bieten wir Ihnen zum Thema Anlagemünzen unsere umfassende Beratung an. Wir garantieren für die von uns vertriebenen Produkte höchste Qualität. Deshalb arbeiten wir ausschliesslich mit international anerkannten und etablierten Herstellern zusammen.



Invalid markup
` + ); + }); + }); + + describe('handles (soft-)line-breaks', () => { + it('does remove line-break (\\n) characters from html-input', () => { + const htmlValue = `

How much\n is the fish?

`; + + expect(html.deserialize(htmlValue)).toEqual([ + { children: [{ text: 'How much is the fish?' }], type: 'paragraph' }, + ]); + }); + it('does transform
tags into slate-nodes', () => { + const htmlValue = `

How much
is the fish?


`; + + expect(html.deserialize(htmlValue)).toEqual([ + { + children: [ + { + text: 'How much', + }, + { + text: '\n', + }, + { + text: ' is the fish?', + }, + ], + type: 'paragraph', + }, + { + text: '\n', + }, + ]); + }); + + it('does transform line-break characters (\\n) into
tags', () => { + const node = { + children: [ + { + text: 'How much', + }, + { + text: '\n', + }, + { + text: ' is the fish?', + }, + ], + type: 'paragraph', + }; + + expect(html.serialize(node)).toEqual( + `

How much
is the fish?

` + ); + }); + it('does preserve
tags (line-breaks) from html-input to html-output', () => { + const htmlValue = `

How much
is the fish?

`; expect(html.serialize(html.deserialize(htmlValue))).toEqual( - `

-Bitte beachten Sie: Die Lieferung erfolgt nach Verfügbarkeit - Jahrgangs- und Designwünschen können wir leider nicht nachkommen. Wir danken Ihnen für Ihr Verständnis. -

- -

Informationen zum Gold Känguru 1/4

-

-Der Australian Nugget (Gold Känguru) ist eine australische Goldmünze, die erstmals 1986 von der Perth Mint geprägt wurde und sich vor allem dank der jährlich wechselnden Motive auf der Vorderseite weltweiter Beliebtheit erfreut. Die Münze hat einen Feingehalt von 999,9 und gilt als offizielles Zahlungsmittel. -

- -

-Seit 1987 wird der Australian Nugget in den Stückelungen 1/20 Unze, 1/10 Unze, 1/4 Unze, 1/2 Unze und 1 Unze geprägt, der Nennwert liegt zwischen 5 und 100 australischen Dollar. Mittlerweile existieren aber auch größere Stückelungen mit einem Gewicht von 2 Unzen, 10 Unzen sowie 1 Kilogramm. Im Jahr 2010 wurde eine 2-Dollar-Version der Münze mit einem Gewicht von 0,5 Gramm aufgelegt. 2011 stellte die Perth Mint zudem eine Ausgabe der Münze mit einem Gewicht von 1 Tonne vor – damit ist der Gold Känguru zugleich die kleinste und grösste Anlagemünze der Welt. -

- -

-Bis 1989 wurden auf der Vorderseite der Münze außergewöhnliche, in Australien gefundene Goldnuggets abgebildet – daher auch der Name Australian Nugget. Seit 1990 zeigt die Goldmünze jährlich wechselnde Motive von Kängurus, der offizielle Name lautet seitdem „Australian Kangaroo“. Größere Einheiten des Gold Känguru, wie die 2-Unzen-, 10-Unzen- und 1-Kilogramm-Version tragen jährlich das gleiche Motiv des „Red Kangaroo“. Auf der Rückseite der Goldmünze findet sich - wie bei allen Commonwealth-Münzen - das Porträt von Königin Elizabeth II. -

-

-

-

-Gold Känguru 1/4 kaufen bei philoro kaufen -

-

-\tNeben der Gold Känguru 1/4/strong> finden Sie bei uns eine breite Auswahl renommierter Goldmünzen aus aller Welt. Gerne bieten wir Ihnen zum Thema Anlagemünzen unsere umfassende Beratung an. Wir garantieren für die von uns vertriebenen Produkte höchste Qualität. Deshalb arbeiten wir ausschliesslich mit international anerkannten und etablierten Herstellern zusammen. -

- -Invalid markup -` + '

How much
is the fish?

' ); }); }); diff --git a/packages/components/inputs/rich-text-utils/src/html/html.tsx b/packages/components/inputs/rich-text-utils/src/html/html.tsx index ac34ee8ba4..e740ba8f60 100644 --- a/packages/components/inputs/rich-text-utils/src/html/html.tsx +++ b/packages/components/inputs/rich-text-utils/src/html/html.tsx @@ -15,6 +15,7 @@ import parse from 'style-to-object'; import isEmpty from 'lodash/isEmpty'; import type { HistoryEditor } from 'slate-history'; import { BLOCK_TAGS, MARK_TAGS } from '../tags'; +import { Softbreaker } from '../slate-helpers'; type Html = string; @@ -70,6 +71,10 @@ const serializeNode = (node: TNode): Html => { if (node.strikethrough) { string = `${string}`; } + + // Replace all Linebreaks (that are caused by the editor) with a br-tag + string = Softbreaker.serialize(string); + return string; } @@ -204,6 +209,10 @@ const deserializeElement = ( const { nodeName } = el; let parent = el; + if (nodeName === 'BR') { + return Softbreaker.getSlatePlaceholder(); + } + if ( nodeName === 'PRE' && el.childNodes[0] && @@ -287,7 +296,7 @@ const deserializeElement = ( }; const deserialize = (html: Html) => { const document = new DOMParser().parseFromString( - html || '

', + Softbreaker.cleanHtml(html) || '

', 'text/html' ); return deserializeElement(document.body); diff --git a/packages/components/inputs/rich-text-utils/src/index.ts b/packages/components/inputs/rich-text-utils/src/index.ts index c3c94fa32f..f5ff6469b3 100644 --- a/packages/components/inputs/rich-text-utils/src/index.ts +++ b/packages/components/inputs/rich-text-utils/src/index.ts @@ -7,6 +7,7 @@ export { default as version } from './version'; export { Element, Leaf, + Softbreaker, isMarkActive, isBlockActive, toggleMark, diff --git a/packages/components/inputs/rich-text-utils/src/slate-helpers.tsx b/packages/components/inputs/rich-text-utils/src/slate-helpers.tsx index 3b09a7f240..f000d273db 100644 --- a/packages/components/inputs/rich-text-utils/src/slate-helpers.tsx +++ b/packages/components/inputs/rich-text-utils/src/slate-helpers.tsx @@ -22,7 +22,7 @@ import html, { const LIST_TYPES = [BLOCK_TAGS.ol, BLOCK_TAGS.ul]; -/* +/* From Slate's own implementation of rich text editor https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx#L133:L179 */ @@ -92,7 +92,7 @@ const Element = ({ attributes, children, element }: RenderElementProps) => { } }; -/* +/* From Slate's own implementation of rich text editor https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx#L181:L199 */ @@ -122,7 +122,7 @@ const Leaf = ({ attributes, children, leaf }: RenderLeafProps) => { return {children}; }; -/* +/* From Slate's own implementation of rich text editor https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx#L128:L131 */ @@ -131,7 +131,7 @@ const isMarkActive = (editor: TEditor, format: Format) => { return marks ? marks[format as keyof typeof marks] === true : false; }; -/* +/* From Slate's own implementation of rich text editor https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx#L101:L09 */ @@ -145,7 +145,7 @@ const toggleMark = (editor: Editor, format: Format) => { } }; -/* +/* From Slate's own implementation of rich text editor https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx#L111:L126 */ @@ -164,7 +164,7 @@ const isBlockActive = (editor: TEditor, format: Format) => { return Boolean(match); }; -/* +/* From slate's own implementation of rich text editor https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx#L67:L99 */ @@ -240,9 +240,44 @@ const focusEditor = (editor: Editor) => { Transforms.select(editor, Editor.end(editor, [])); }; +/** + * Softbreaker is a helper that is used to ensure + * that slate editor can handle html-linebreaks correctly. + */ +const Softbreaker = { + /** + * The character that slate-editor considers a soft-linebreak + */ + placeholderCharacter: '\n', + /** + * Returns a formatted version of the soft-linebreak character + * which can be used by internal slate editor functions + */ + getSlatePlaceholder() { + return { + text: this.placeholderCharacter, + }; + }, + /** + * replaces the slate-placeholder character with the html + * equivalent =
+ */ + serialize(str: string) { + return str.split(this.placeholderCharacter).join('
'); + }, + /** + * Initial HMTL needs to be cleaned from soft-linebreak characters, + * otherwise they are being transformed into
tags + */ + cleanHtml(html: string) { + return html.split(this.placeholderCharacter).join(''); + }, +}; + export { Element, Leaf, + Softbreaker, isMarkActive, isBlockActive, toggleMark,