From 92d3147f02d9b8a8f1e82951bc8742f021c080f7 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 8 Jul 2024 12:59:36 +0200 Subject: [PATCH 01/14] add handling for wrapped code text for native devices --- .../InlineCodeBlock/WrappedText.tsx | 108 +++++++++--------- 1 file changed, 51 insertions(+), 57 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index 3045c15c471b..a5fe8b18e50a 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -1,6 +1,6 @@ -import React, {Fragment} from 'react'; -import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; -import {View} from 'react-native'; +import React, {useState} from 'react'; +import {TextLayoutEventData, View} from 'react-native'; +import type {NativeSyntheticEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import {containsOnlyEmojis} from '@libs/EmojiUtils'; @@ -11,77 +11,71 @@ type WrappedTextProps = ChildrenProps & { /** Style to be applied to Text */ textStyles?: StyleProp; - /** - * Style for each individual word (token) in the text. Note that a token can also include whitespace characters between words. - */ + /** Style for each individual word (token) in the text */ wordStyles?: StyleProp; }; -/** - * Breaks the text into matrix - * - * @example - * const text = "My Name is Rajat"; - * const resultMatrix = getTextMatrix(text); - * console.log(resultMatrix); - * // Output: - * // [ - * // ['My', ' ', 'Name', ' ', 'is', ' ', 'Rajat'], - * // ] - */ -function getTextMatrix(text: string): string[][] { - return text.split('\n').map((row) => row.split(CONST.REGEX.SPACE_OR_EMOJI).filter((value) => value !== '')); -} - -/** - * Validates if the text contains any emoji - */ +/** Validates if the text contains any emoji */ function containsEmoji(text: string): boolean { return CONST.REGEX.EMOJIS.test(text); } function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { + const [lines, setLines] = useState([]); const styles = useThemeStyles(); if (typeof children !== 'string') { return null; } - const textMatrix = getTextMatrix(children); + type TextLayoutEvent = NativeSyntheticEvent; + + const handleTextLayout = (event: TextLayoutEvent) => { + const { + nativeEvent: {lines: textLines}, + } = event; + setLines(textLines.map((line: {text: string}) => line.text)); + }; - return textMatrix.map((rowText, rowIndex) => ( - - {rowText.map((colText, colIndex) => ( - // Outer View is important to vertically center the Text - - - - {Array.from(colText).map((char, charIndex) => - containsOnlyEmojis(char) ? ( - - {char} - - ) : ( - char - ), - )} - + return ( + <> + {!!lines.length ? ( + lines.map((line, index) => ( + + + + {Array.from(line).map((char, charIndex) => + containsOnlyEmojis(char) ? ( + + {char} + + ) : ( + char + ), + )} + + + )) + ) : ( + + + {children} + - ))} - - )); + )} + + ); } WrappedText.displayName = 'WrappedText'; From ebeed08b6f1ce82a8c4566ae1ea9ce03b9a449f2 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:17:14 +0200 Subject: [PATCH 02/14] fix lint issues --- .../InlineCodeBlock/WrappedText.tsx | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index a5fe8b18e50a..661d3e5eeb7e 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -1,6 +1,6 @@ import React, {useState} from 'react'; -import {TextLayoutEventData, View} from 'react-native'; -import type {NativeSyntheticEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; +import type {NativeSyntheticEvent, TextLayoutEventData, StyleProp, TextStyle, ViewStyle} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import {containsOnlyEmojis} from '@libs/EmojiUtils'; @@ -37,45 +37,46 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { setLines(textLines.map((line: {text: string}) => line.text)); }; - return ( - <> - {!!lines.length ? ( - lines.map((line, index) => ( - - - - {Array.from(line).map((char, charIndex) => - containsOnlyEmojis(char) ? ( - - {char} - - ) : ( - char - ), - )} - - - - )) - ) : ( - - - {children} + if (!lines.length) { + return ( + + + {children} + + + ); + } + + return (<> + {lines.map((line, index) => ( + + + + {Array.from(line).map((char, charIndex) => + containsOnlyEmojis(char) ? ( + + {char} + + ) : ( + char + ), + )} - )} - - ); + + ))} + ); } WrappedText.displayName = 'WrappedText'; From e8441ef9cafb5b04da8a96fb5ec32067375a6206 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:18:06 +0200 Subject: [PATCH 03/14] correct imports and prettier --- .../InlineCodeBlock/WrappedText.tsx | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index 661d3e5eeb7e..ef8d66e365dc 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -1,6 +1,6 @@ import React, {useState} from 'react'; import {View} from 'react-native'; -import type {NativeSyntheticEvent, TextLayoutEventData, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import type {NativeSyntheticEvent, StyleProp, TextLayoutEventData, TextStyle, ViewStyle} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import {containsOnlyEmojis} from '@libs/EmojiUtils'; @@ -50,33 +50,35 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { ); } - return (<> - {lines.map((line, index) => ( - - - - {Array.from(line).map((char, charIndex) => - containsOnlyEmojis(char) ? ( - - {char} - - ) : ( - char - ), - )} - + return ( + <> + {lines.map((line, index) => ( + + + + {Array.from(line).map((char, charIndex) => + containsOnlyEmojis(char) ? ( + + {char} + + ) : ( + char + ), + )} + + - - ))} - ); + ))} + + ); } WrappedText.displayName = 'WrappedText'; From 5764928860c95a9c2df0e09aab59d97c7dd1f530 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:48:48 +0200 Subject: [PATCH 04/14] split long singular words into mulltiple strings --- .../InlineCodeBlock/WrappedText.tsx | 90 +++++++++++-------- src/styles/variables.ts | 1 + 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index ef8d66e365dc..4fd48b63d626 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -1,70 +1,90 @@ -import React, {useState} from 'react'; +import React, {Fragment} from 'react'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import {View} from 'react-native'; -import type {NativeSyntheticEvent, StyleProp, TextLayoutEventData, TextStyle, ViewStyle} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import {containsOnlyEmojis} from '@libs/EmojiUtils'; import CONST from '@src/CONST'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import variables from '@styles/variables'; +import useWindowDimensions from '@hooks/useWindowDimensions'; type WrappedTextProps = ChildrenProps & { /** Style to be applied to Text */ textStyles?: StyleProp; - /** Style for each individual word (token) in the text */ + /** + * Style for each individual word (token) in the text. Note that a token can also include whitespace characters between words. + */ wordStyles?: StyleProp; }; -/** Validates if the text contains any emoji */ +/** + * Breaks the text into matrix + * + * @example + * const text = "My Name is Rajat"; + * const resultMatrix = getTextMatrix(text); + * console.log(resultMatrix); + * // Output: + * // [ + * // ['My', ' ', 'Name', ' ', 'is', ' ', 'Rajat'], + * // ] + */ +function getTextMatrix(text: string): string[][] { + return text.split('\n').map((row) => row.split(CONST.REGEX.SPACE_OR_EMOJI).filter((value) => value !== '')); +} + +/** + * Validates if the text contains any emoji + */ function containsEmoji(text: string): boolean { return CONST.REGEX.EMOJIS.test(text); } +/** + * Splits long words into multiple strings + */ +function splitLongWord(word: string, maxLength: number): string[] { + if (word.length <= maxLength) { + return [word]; + } + + return word.match(new RegExp(`.{1,${maxLength}}`, 'g')) || []; +} + function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { - const [lines, setLines] = useState([]); const styles = useThemeStyles(); + const {windowWidth} = useWindowDimensions(); if (typeof children !== 'string') { return null; } - type TextLayoutEvent = NativeSyntheticEvent; - - const handleTextLayout = (event: TextLayoutEvent) => { - const { - nativeEvent: {lines: textLines}, - } = event; - setLines(textLines.map((line: {text: string}) => line.text)); - }; + const charWidth = variables.fontSizeLabel * variables.fontSizeToWidthRatio; + const charsPerLine = Math.floor(windowWidth / charWidth); - if (!lines.length) { - return ( - - - {children} - - - ); - } + const textMatrix = getTextMatrix(children).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); - return ( - <> - {lines.map((line, index) => ( + return textMatrix.map((rowText, rowIndex) => ( + + {rowText.map((colText, colIndex) => ( + // Outer View is important to vertically center the Text - - - {Array.from(line).map((char, charIndex) => + + + {Array.from(colText).map((char, charIndex) => containsOnlyEmojis(char) ? ( {char} @@ -77,8 +97,8 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { ))} - - ); + + )); } WrappedText.displayName = 'WrappedText'; diff --git a/src/styles/variables.ts b/src/styles/variables.ts index c0c058352d00..1cc0a2b5bdf7 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -215,6 +215,7 @@ export default { onboardingModalWidth: 500, welcomeVideoDelay: 1000, explanationModalDelay: 2000, + fontSizeToWidthRatio: getValueUsingPixelRatio(0.8, 1), // The height of the empty list is 14px (2px for borders and 12px for vertical padding) // This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility From e74c97e0149df0d5fa7bd9bc9c66093b241c2806 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:49:40 +0200 Subject: [PATCH 05/14] fix prettier and lint errors --- src/components/InlineCodeBlock/WrappedText.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index 4fd48b63d626..b331ce902fcb 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -3,11 +3,11 @@ import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import {View} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; import {containsOnlyEmojis} from '@libs/EmojiUtils'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; -import variables from '@styles/variables'; -import useWindowDimensions from '@hooks/useWindowDimensions'; type WrappedTextProps = ChildrenProps & { /** Style to be applied to Text */ @@ -50,7 +50,7 @@ function splitLongWord(word: string, maxLength: number): string[] { return [word]; } - return word.match(new RegExp(`.{1,${maxLength}}`, 'g')) || []; + return word.match(new RegExp(`.{1,${maxLength}}`, 'g')) ?? []; } function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { From 44d0d7d1ab68a87b221a62bc6d347f1afe22dc59 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:01:32 +0200 Subject: [PATCH 06/14] memoize fontSize and infer it from textStyles --- .../InlineCodeBlock/WrappedText.tsx | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index b331ce902fcb..f8adb1cd25d4 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -1,4 +1,4 @@ -import React, {Fragment} from 'react'; +import React, {Fragment, useMemo} from 'react'; import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import {View} from 'react-native'; import Text from '@components/Text'; @@ -53,6 +53,21 @@ function splitLongWord(word: string, maxLength: number): string[] { return word.match(new RegExp(`.{1,${maxLength}}`, 'g')) ?? []; } +function getFontSizeFromStyles(textStyles: StyleProp): number { + if (Array.isArray(textStyles)) { + for (let style of textStyles) { + if (style && 'fontSize' in style && style.fontSize) { + return style.fontSize; + } + } + } else if (textStyles && 'fontSize' in textStyles && textStyles.fontSize) { + return textStyles.fontSize; + } + + // if we cannot infer fontSize from styles, a default value is returned + return variables.fontSizeLabel; +} + function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { const styles = useThemeStyles(); const {windowWidth} = useWindowDimensions(); @@ -61,10 +76,12 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { return null; } - const charWidth = variables.fontSizeLabel * variables.fontSizeToWidthRatio; - const charsPerLine = Math.floor(windowWidth / charWidth); + const textMatrix = useMemo(() => { + const fontSize = getFontSizeFromStyles(textStyles); + const charsPerLine = Math.floor(windowWidth / (fontSize * variables.fontSizeToWidthRatio)); - const textMatrix = getTextMatrix(children).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); + return getTextMatrix(children).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); + }, [textStyles]); return textMatrix.map((rowText, rowIndex) => ( Date: Wed, 11 Sep 2024 15:37:31 +0200 Subject: [PATCH 07/14] fix lint errors and refactor code --- src/components/InlineCodeBlock/WrappedText.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index f8adb1cd25d4..922262e01b8b 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -55,7 +55,7 @@ function splitLongWord(word: string, maxLength: number): string[] { function getFontSizeFromStyles(textStyles: StyleProp): number { if (Array.isArray(textStyles)) { - for (let style of textStyles) { + for (const style of textStyles) { if (style && 'fontSize' in style && style.fontSize) { return style.fontSize; } @@ -72,16 +72,17 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { const styles = useThemeStyles(); const {windowWidth} = useWindowDimensions(); - if (typeof children !== 'string') { - return null; - } - const textMatrix = useMemo(() => { const fontSize = getFontSizeFromStyles(textStyles); const charsPerLine = Math.floor(windowWidth / (fontSize * variables.fontSizeToWidthRatio)); - return getTextMatrix(children).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); - }, [textStyles]); + const childrenString = typeof children === 'string' ? children : ''; + return getTextMatrix(childrenString).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); + }, [textStyles, children, windowWidth]); + + if (typeof children !== 'string') { + return null; + } return textMatrix.map((rowText, rowIndex) => ( Date: Thu, 26 Sep 2024 16:36:45 +0200 Subject: [PATCH 08/14] remove manual memoization in favor of react-compiler --- src/components/InlineCodeBlock/WrappedText.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index 922262e01b8b..51f6b1ae09f2 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -72,13 +72,11 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { const styles = useThemeStyles(); const {windowWidth} = useWindowDimensions(); - const textMatrix = useMemo(() => { - const fontSize = getFontSizeFromStyles(textStyles); - const charsPerLine = Math.floor(windowWidth / (fontSize * variables.fontSizeToWidthRatio)); + const fontSize = useMemo(() => getFontSizeFromStyles(textStyles), [textStyles]); + const childrenString = typeof children === 'string' ? children : ''; + const charsPerLine = useMemo(() => Math.floor(windowWidth / (fontSize * variables.fontSizeToWidthRatio)), [windowWidth, fontSize]); - const childrenString = typeof children === 'string' ? children : ''; - return getTextMatrix(childrenString).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); - }, [textStyles, children, windowWidth]); + const textMatrix = getTextMatrix(childrenString).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); if (typeof children !== 'string') { return null; From 23e436b0988c544c8c37bd16e61c7aaefeb504a8 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 30 Oct 2024 23:50:15 +0100 Subject: [PATCH 09/14] add longer explaination comment --- src/components/InlineCodeBlock/WrappedText.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index db96ce957df5..df7a04bf10ec 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -43,7 +43,20 @@ function containsEmoji(text: string): boolean { } /** - * Splits long words into multiple strings + * Takes a long word and splits it into an array of sub-strings. + * + * The function tests whether the length of the provided word exceeds the provided maximum length. + * If the word's length is less than or equal to `maxLength`, it returns an array with the original word. + * If the word's length exceeds 'maxLength', it utilizes a regular expression to split the word into + * substrings with a specified 'maxLength' and returns them as an array of strings. + * + * @param {string} word - The original word to be split. + * @param {number} maxLength - The maximum length of each substring. + * @return {string[]} An array of substrings derived from the original word. + * + * @example + * splitLongWord('longteststring', 4); + * // Output: ['long', 'test', 'stri', 'ng'] */ function splitLongWord(word: string, maxLength: number): string[] { if (word.length <= maxLength) { From 66d9dc5ead2e8e847fb2266065d7e1ca0e7e775a Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:02:08 +0100 Subject: [PATCH 10/14] add unit test for splitLongWord --- .../InlineCodeBlock/WrappedText.tsx | 2 ++ tests/unit/splitLongWordTest.ts | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/unit/splitLongWordTest.ts diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index df7a04bf10ec..978b7894d486 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -133,3 +133,5 @@ function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { WrappedText.displayName = 'WrappedText'; export default WrappedText; + +export {splitLongWord}; \ No newline at end of file diff --git a/tests/unit/splitLongWordTest.ts b/tests/unit/splitLongWordTest.ts new file mode 100644 index 000000000000..6e7a6fa37357 --- /dev/null +++ b/tests/unit/splitLongWordTest.ts @@ -0,0 +1,32 @@ +import { splitLongWord } from "@components/InlineCodeBlock/WrappedText"; + +describe('splitLongWord', () => { + const testCases = [ + { + word: 'thissadasdasdsadsadasdadsadasdasdasdasdasdasdasdasdasdsadsadggggggggggggggggg', + maxLength: 4, + output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'sads', 'adsa', 'dggg', 'gggg', 'gggg', 'gggg', 'gggg'] + }, + { + word: 'https://www.google.com/search?q=google&oq=goog&gs_lcrp=EgZjaHJvbWUqEAgAEAAYgwEY4wIYsQMYgAQyEAgAEAAYgwEY4wIYsQMYgAQyEwgBEC4YgwEYxwEYsQMY0QMYgAQyDQgCEAAYgwEYsQMYgAQyBggDEEUYOzIGCAQQRRg8MgYIBRBFGDwyBggGEEUYPDIGCAcQBRhA0gEHNzM1ajBqN6gCALACAA&sourceid=chrome&ie=UTF-8', + maxLength: 20, + output: ['https://www.google.c', 'om/search?q=google', '&oq=goog&gs_lcrp', '=EgZjaHJvbWUqEAg', 'AEAAYgwEY4wIYsQM', 'YgAQyEAgAEAAYgwE', 'Y4wIYsQMYgAQyEw', 'gBEC4YgwEYxwEYs', 'QMY0QMYgAQyDQgc', 'EAAYgwEYsQMYgAQ', 'yBggDEEUYOzIGCA', 'QQRRg8MgYIBRBFG', 'DwyBggGEEUYPDIG', 'CAcQBRhA0gEHNzM', '1ajBqN6gCALACAA', '&sourceid=chrome&ie', '=UTF-8'] + }, + { + word: 'superkalifragilistischexpialigetisch', + maxLength: 5, + output: ['super', 'kali', 'fragi', 'listi', 'schex', 'piali', 'getis', 'ch'] + }, + { + word: 'Este es un ejemplo de texto en español para la prueba', + maxLength: 8, + output: ['Este es ', 'un ejemp', 'lo de te', 'xto en e', 'spañol p', 'ara la p', 'rueba'] + }, + ]; + + testCases.forEach(({ word, maxLength, output }) => { + test(`should split ${word} into ${output.join()} with maxLength of ${maxLength}`, () => { + expect(splitLongWord(word, maxLength)).toEqual(output); + }); + }); +}); \ No newline at end of file From e9c459b8b7e7f6aa2b2d4762d2138a2d2ef64c36 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:02:20 +0100 Subject: [PATCH 11/14] fix prettier --- .../InlineCodeBlock/WrappedText.tsx | 6 +-- tests/unit/splitLongWordTest.ts | 50 +++++++++++++------ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index 978b7894d486..de42e494dbd3 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -44,7 +44,7 @@ function containsEmoji(text: string): boolean { /** * Takes a long word and splits it into an array of sub-strings. - * + * * The function tests whether the length of the provided word exceeds the provided maximum length. * If the word's length is less than or equal to `maxLength`, it returns an array with the original word. * If the word's length exceeds 'maxLength', it utilizes a regular expression to split the word into @@ -53,7 +53,7 @@ function containsEmoji(text: string): boolean { * @param {string} word - The original word to be split. * @param {number} maxLength - The maximum length of each substring. * @return {string[]} An array of substrings derived from the original word. - * + * * @example * splitLongWord('longteststring', 4); * // Output: ['long', 'test', 'stri', 'ng'] @@ -134,4 +134,4 @@ WrappedText.displayName = 'WrappedText'; export default WrappedText; -export {splitLongWord}; \ No newline at end of file +export {splitLongWord}; diff --git a/tests/unit/splitLongWordTest.ts b/tests/unit/splitLongWordTest.ts index 6e7a6fa37357..7f30e9e6cb62 100644 --- a/tests/unit/splitLongWordTest.ts +++ b/tests/unit/splitLongWordTest.ts @@ -1,32 +1,50 @@ -import { splitLongWord } from "@components/InlineCodeBlock/WrappedText"; +import {splitLongWord} from '@components/InlineCodeBlock/WrappedText'; describe('splitLongWord', () => { const testCases = [ - { - word: 'thissadasdasdsadsadasdadsadasdasdasdasdasdasdasdasdasdsadsadggggggggggggggggg', - maxLength: 4, - output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'sads', 'adsa', 'dggg', 'gggg', 'gggg', 'gggg', 'gggg'] + { + word: 'thissadasdasdsadsadasdadsadasdasdasdasdasdasdasdasdasdsadsadggggggggggggggggg', + maxLength: 4, + output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'sads', 'adsa', 'dggg', 'gggg', 'gggg', 'gggg', 'gggg'], }, - { + { word: 'https://www.google.com/search?q=google&oq=goog&gs_lcrp=EgZjaHJvbWUqEAgAEAAYgwEY4wIYsQMYgAQyEAgAEAAYgwEY4wIYsQMYgAQyEwgBEC4YgwEYxwEYsQMY0QMYgAQyDQgCEAAYgwEYsQMYgAQyBggDEEUYOzIGCAQQRRg8MgYIBRBFGDwyBggGEEUYPDIGCAcQBRhA0gEHNzM1ajBqN6gCALACAA&sourceid=chrome&ie=UTF-8', - maxLength: 20, - output: ['https://www.google.c', 'om/search?q=google', '&oq=goog&gs_lcrp', '=EgZjaHJvbWUqEAg', 'AEAAYgwEY4wIYsQM', 'YgAQyEAgAEAAYgwE', 'Y4wIYsQMYgAQyEw', 'gBEC4YgwEYxwEYs', 'QMY0QMYgAQyDQgc', 'EAAYgwEYsQMYgAQ', 'yBggDEEUYOzIGCA', 'QQRRg8MgYIBRBFG', 'DwyBggGEEUYPDIG', 'CAcQBRhA0gEHNzM', '1ajBqN6gCALACAA', '&sourceid=chrome&ie', '=UTF-8'] + maxLength: 20, + output: [ + 'https://www.google.c', + 'om/search?q=google', + '&oq=goog&gs_lcrp', + '=EgZjaHJvbWUqEAg', + 'AEAAYgwEY4wIYsQM', + 'YgAQyEAgAEAAYgwE', + 'Y4wIYsQMYgAQyEw', + 'gBEC4YgwEYxwEYs', + 'QMY0QMYgAQyDQgc', + 'EAAYgwEYsQMYgAQ', + 'yBggDEEUYOzIGCA', + 'QQRRg8MgYIBRBFG', + 'DwyBggGEEUYPDIG', + 'CAcQBRhA0gEHNzM', + '1ajBqN6gCALACAA', + '&sourceid=chrome&ie', + '=UTF-8', + ], }, - { - word: 'superkalifragilistischexpialigetisch', - maxLength: 5, - output: ['super', 'kali', 'fragi', 'listi', 'schex', 'piali', 'getis', 'ch'] + { + word: 'superkalifragilistischexpialigetisch', + maxLength: 5, + output: ['super', 'kali', 'fragi', 'listi', 'schex', 'piali', 'getis', 'ch'], }, - { + { word: 'Este es un ejemplo de texto en español para la prueba', maxLength: 8, - output: ['Este es ', 'un ejemp', 'lo de te', 'xto en e', 'spañol p', 'ara la p', 'rueba'] + output: ['Este es ', 'un ejemp', 'lo de te', 'xto en e', 'spañol p', 'ara la p', 'rueba'], }, ]; - testCases.forEach(({ word, maxLength, output }) => { + testCases.forEach(({word, maxLength, output}) => { test(`should split ${word} into ${output.join()} with maxLength of ${maxLength}`, () => { expect(splitLongWord(word, maxLength)).toEqual(output); }); }); -}); \ No newline at end of file +}); From 5c666249ec08cce34e1570ae65228b66badad537 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:14:33 +0100 Subject: [PATCH 12/14] fix jsdoc lint errors --- src/components/InlineCodeBlock/WrappedText.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index de42e494dbd3..9e7c7291a9a6 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -50,9 +50,9 @@ function containsEmoji(text: string): boolean { * If the word's length exceeds 'maxLength', it utilizes a regular expression to split the word into * substrings with a specified 'maxLength' and returns them as an array of strings. * - * @param {string} word - The original word to be split. - * @param {number} maxLength - The maximum length of each substring. - * @return {string[]} An array of substrings derived from the original word. + * @param word The original word to be split. + * @param maxLength The maximum length of each substring. + * @return An array of substrings derived from the original word. * * @example * splitLongWord('longteststring', 4); From 32ea3fce7a38bf81b6241016668722552e607f32 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:24:49 +0100 Subject: [PATCH 13/14] fix unit test expected results --- tests/unit/splitLongWordTest.ts | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/tests/unit/splitLongWordTest.ts b/tests/unit/splitLongWordTest.ts index 7f30e9e6cb62..2c0a72f8f67c 100644 --- a/tests/unit/splitLongWordTest.ts +++ b/tests/unit/splitLongWordTest.ts @@ -5,35 +5,32 @@ describe('splitLongWord', () => { { word: 'thissadasdasdsadsadasdadsadasdasdasdasdasdasdasdasdasdsadsadggggggggggggggggg', maxLength: 4, - output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'sads', 'adsa', 'dggg', 'gggg', 'gggg', 'gggg', 'gggg'], + output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'asda', 'sdsa', 'dsad', 'gggg', 'gggg', 'gggg', 'gggg', 'gggg', 'g'], }, { word: 'https://www.google.com/search?q=google&oq=goog&gs_lcrp=EgZjaHJvbWUqEAgAEAAYgwEY4wIYsQMYgAQyEAgAEAAYgwEY4wIYsQMYgAQyEwgBEC4YgwEYxwEYsQMY0QMYgAQyDQgCEAAYgwEYsQMYgAQyBggDEEUYOzIGCAQQRRg8MgYIBRBFGDwyBggGEEUYPDIGCAcQBRhA0gEHNzM1ajBqN6gCALACAA&sourceid=chrome&ie=UTF-8', maxLength: 20, output: [ 'https://www.google.c', - 'om/search?q=google', - '&oq=goog&gs_lcrp', - '=EgZjaHJvbWUqEAg', - 'AEAAYgwEY4wIYsQM', - 'YgAQyEAgAEAAYgwE', - 'Y4wIYsQMYgAQyEw', - 'gBEC4YgwEYxwEYs', - 'QMY0QMYgAQyDQgc', - 'EAAYgwEYsQMYgAQ', - 'yBggDEEUYOzIGCA', - 'QQRRg8MgYIBRBFG', - 'DwyBggGEEUYPDIG', - 'CAcQBRhA0gEHNzM', - '1ajBqN6gCALACAA', - '&sourceid=chrome&ie', - '=UTF-8', + 'om/search?q=google&o', + 'q=goog&gs_lcrp=EgZja', + 'HJvbWUqEAgAEAAYgwEY4', + 'wIYsQMYgAQyEAgAEAAYg', + 'wEY4wIYsQMYgAQyEwgBE', + 'C4YgwEYxwEYsQMY0QMYg', + 'AQyDQgCEAAYgwEYsQMYg', + 'AQyBggDEEUYOzIGCAQQR', + 'Rg8MgYIBRBFGDwyBggGE', + 'EUYPDIGCAcQBRhA0gEHN', + 'zM1ajBqN6gCALACAA&so', + 'urceid=chrome&ie=UTF', + '-8', ], }, { word: 'superkalifragilistischexpialigetisch', maxLength: 5, - output: ['super', 'kali', 'fragi', 'listi', 'schex', 'piali', 'getis', 'ch'], + output: ['super', 'kalif', 'ragil', 'istis', 'chexp', 'ialig', 'etisc', 'h'], }, { word: 'Este es un ejemplo de texto en español para la prueba', From 8b76cc9e94c2ab82d830ed072f4e425ddf5a61b6 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:31:39 +0100 Subject: [PATCH 14/14] remove unexpected output substring from test --- tests/unit/splitLongWordTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/splitLongWordTest.ts b/tests/unit/splitLongWordTest.ts index 2c0a72f8f67c..19f8fc98e73f 100644 --- a/tests/unit/splitLongWordTest.ts +++ b/tests/unit/splitLongWordTest.ts @@ -5,7 +5,7 @@ describe('splitLongWord', () => { { word: 'thissadasdasdsadsadasdadsadasdasdasdasdasdasdasdasdasdsadsadggggggggggggggggg', maxLength: 4, - output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'asda', 'sdsa', 'dsad', 'gggg', 'gggg', 'gggg', 'gggg', 'gggg', 'g'], + output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'asda', 'sdsa', 'dsad', 'gggg', 'gggg', 'gggg', 'gggg', 'g'], }, { word: 'https://www.google.com/search?q=google&oq=goog&gs_lcrp=EgZjaHJvbWUqEAgAEAAYgwEY4wIYsQMYgAQyEAgAEAAYgwEY4wIYsQMYgAQyEwgBEC4YgwEYxwEYsQMY0QMYgAQyDQgCEAAYgwEYsQMYgAQyBggDEEUYOzIGCAQQRRg8MgYIBRBFGDwyBggGEEUYPDIGCAcQBRhA0gEHNzM1ajBqN6gCALACAA&sourceid=chrome&ie=UTF-8',