From 4b4bc6dd8aa7deac2b2db9eb2935b54973c8c527 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Fri, 2 Feb 2024 17:19:43 +0100 Subject: [PATCH 1/4] Split text into chars correctly --- src/util/misc/textStyles.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/util/misc/textStyles.ts b/src/util/misc/textStyles.ts index e7cfeef5289..65a54ad1e2d 100644 --- a/src/util/misc/textStyles.ts +++ b/src/util/misc/textStyles.ts @@ -4,6 +4,7 @@ import type { TextStyleDeclaration, } from '../../shapes/Text/StyledText'; import { cloneDeep } from '../internals/cloneDeep'; +import { graphemeSplit } from '../lang_string'; export type TextStyleArray = { start: number; @@ -57,14 +58,15 @@ export const stylesToArray = ( //loop through each textLine for (let i = 0; i < textLines.length; i++) { + const chars = graphemeSplit(textLines[i]); if (!styles[i]) { //no styles exist for this line, so add the line's length to the charIndex total and reset prevStyle - charIndex += textLines[i].length; + charIndex += chars.length; prevStyle = {}; continue; } //loop through each character of the current line - for (let c = 0; c < textLines[i].length; c++) { + for (let c = 0; c < chars.length; c++) { charIndex++; const thisStyle = styles[i][c]; //check if style exists for this character @@ -108,8 +110,10 @@ export const stylesFromArray = ( styleIndex = 0; //loop through each textLine for (let i = 0; i < textLines.length; i++) { + const chars = graphemeSplit(textLines[i]); + //loop through each character of the current line - for (let c = 0; c < textLines[i].length; c++) { + for (let c = 0; c < chars.length; c++) { charIndex++; //check if there's a style collection that includes the current character if ( From b80ceb23df9df8659d4a1ca18aa50227f6187f09 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Fri, 2 Feb 2024 17:35:05 +0100 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb4de6ea696..e9d73e4fe10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- fix(textStyles): Split text into graphemes correctly [#9646](https://github.com/fabricjs/fabric.js/pull/9646) - fix(ActiveSelection): static default inheritance [#9635](https://github.com/fabricjs/fabric.js/pull/9635) - fix(StaticCanvas): StaticCanvas setDimensions typings [#9618](https://github.com/fabricjs/fabric.js/pull/9618) - refactor(): Align gradient with class registry usage, part of #9144 [#9627](https://github.com/fabricjs/fabric.js/pull/9627) From 3462cfe3442bc58badc3a7225c1a80d0e3cb64c1 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 4 Feb 2024 22:22:01 +0100 Subject: [PATCH 3/4] added test --- src/shapes/Text/StyledText.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/shapes/Text/StyledText.spec.ts b/src/shapes/Text/StyledText.spec.ts index c81f2043d20..ba88923a31f 100644 --- a/src/shapes/Text/StyledText.spec.ts +++ b/src/shapes/Text/StyledText.spec.ts @@ -35,3 +35,21 @@ describe('setSelectionStyles', () => { }); }); }); + +describe('toObject', () => { + it('Will serialize text with grpahemes in mind', () => { + const text = new FabricText('🤩🤩\nHello', { + styles: { + 1: { + 0: { + fontSize: 40, + }, + }, + }, + }); + const serializedStyles = text.toObject().styles; + expect(serializedStyles).toEqual([ + { start: 2, end: 3, style: { fontSize: 40 } }, + ]); + }); +}); From 7744e6dcf4be29f8f1bc461c19a277be9a372737 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 4 Feb 2024 22:44:47 +0100 Subject: [PATCH 4/4] more clear assertion --- src/shapes/Text/StyledText.spec.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shapes/Text/StyledText.spec.ts b/src/shapes/Text/StyledText.spec.ts index ba88923a31f..22b73cd2a95 100644 --- a/src/shapes/Text/StyledText.spec.ts +++ b/src/shapes/Text/StyledText.spec.ts @@ -1,4 +1,5 @@ import { FabricText } from './Text'; +import { graphemeSplit } from '../../util/lang_string'; describe('setSelectionStyles', () => { test('will set properties at the correct position', () => { @@ -37,7 +38,7 @@ describe('setSelectionStyles', () => { }); describe('toObject', () => { - it('Will serialize text with grpahemes in mind', () => { + it('Will serialize text with graphemes in mind', () => { const text = new FabricText('🤩🤩\nHello', { styles: { 1: { @@ -51,5 +52,8 @@ describe('toObject', () => { expect(serializedStyles).toEqual([ { start: 2, end: 3, style: { fontSize: 40 } }, ]); + expect(serializedStyles[0].start).toEqual( + graphemeSplit(text.textLines[0]).length + ); }); });