From fcc512d0df6fc057253c815dbeab5d0079254988 Mon Sep 17 00:00:00 2001 From: Bryan Valverde Date: Tue, 4 Aug 2026 11:45:42 -0600 Subject: [PATCH 1/2] Announce new lines inserted with Enter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0b3e8c6f-5223-4b6e-b959-5f8b209e5b10 --- demo/scripts/controlsV2/mainPane/MainPane.tsx | 1 + .../edit/inputSteps/handleEnterOnParagraph.ts | 5 ++++ .../inputSteps/handleEnterOnParagraphTest.ts | 14 +++++++++- .../lib/parameter/AnnounceData.ts | 10 ++++++- .../lib/editor/utils/eventConverter.ts | 1 + .../test/editor/utils/eventConverterTest.ts | 26 +++++++++++++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/demo/scripts/controlsV2/mainPane/MainPane.tsx b/demo/scripts/controlsV2/mainPane/MainPane.tsx index 67c141678721..fb52d926a6bd 100644 --- a/demo/scripts/controlsV2/mainPane/MainPane.tsx +++ b/demo/scripts/controlsV2/mainPane/MainPane.tsx @@ -627,6 +627,7 @@ const AnnounceStringMap: Record = { announceUnderlineOff: 'Underline Off', selected: '{0}, selected', unselected: '{0}, unselected', + newLineInserted: 'New line', }; function getAnnouncingString(key: KnownAnnounceStrings) { diff --git a/packages/roosterjs-content-model-plugins/lib/edit/inputSteps/handleEnterOnParagraph.ts b/packages/roosterjs-content-model-plugins/lib/edit/inputSteps/handleEnterOnParagraph.ts index be052bf1e2e4..9b56d93f7309 100644 --- a/packages/roosterjs-content-model-plugins/lib/edit/inputSteps/handleEnterOnParagraph.ts +++ b/packages/roosterjs-content-model-plugins/lib/edit/inputSteps/handleEnterOnParagraph.ts @@ -23,5 +23,10 @@ export const handleEnterOnParagraph: ( context.deleteResult = 'range'; context.lastParagraph = newPara; context.insertPoint.paragraph = newPara; + if (context.formatContext) { + context.formatContext.announceData = { + defaultStrings: 'newLineInserted', + }; + } } }; diff --git a/packages/roosterjs-content-model-plugins/test/edit/inputSteps/handleEnterOnParagraphTest.ts b/packages/roosterjs-content-model-plugins/test/edit/inputSteps/handleEnterOnParagraphTest.ts index a2952a391ef6..5cccad88730c 100644 --- a/packages/roosterjs-content-model-plugins/test/edit/inputSteps/handleEnterOnParagraphTest.ts +++ b/packages/roosterjs-content-model-plugins/test/edit/inputSteps/handleEnterOnParagraphTest.ts @@ -1,5 +1,8 @@ import { handleEnterOnParagraph } from '../../../lib/edit/inputSteps/handleEnterOnParagraph'; -import { ValidDeleteSelectionContext } from 'roosterjs-content-model-types'; +import { + FormatContentModelContext, + ValidDeleteSelectionContext, +} from 'roosterjs-content-model-types'; import { createContentModelDocument, createParagraph, @@ -43,6 +46,11 @@ describe('handleEnterOnParagraph', () => { const mockedCache = {} as any; const text1 = createText('test1'); const text2 = createText('test1'); + const formatContext: FormatContentModelContext = { + newEntities: [], + deletedEntities: [], + newImages: [], + }; para.segments.push(text1, marker, text2); doc.blocks.push(para); @@ -55,6 +63,7 @@ describe('handleEnterOnParagraph', () => { marker: marker, path: [doc], }, + formatContext, }; handleEnterOnParagraph([])(context); @@ -98,6 +107,9 @@ describe('handleEnterOnParagraph', () => { marker: marker, path: [doc], }); + expect(formatContext.announceData).toEqual({ + defaultStrings: 'newLineInserted', + }); }); it('Not deleted, split current paragraph with id', () => { diff --git a/packages/roosterjs-content-model-types/lib/parameter/AnnounceData.ts b/packages/roosterjs-content-model-types/lib/parameter/AnnounceData.ts index abf1af172d35..8cfdf9c31207 100644 --- a/packages/roosterjs-content-model-types/lib/parameter/AnnounceData.ts +++ b/packages/roosterjs-content-model-types/lib/parameter/AnnounceData.ts @@ -65,7 +65,15 @@ export type KnownAnnounceStrings = * @example * {0}, unselected */ - | 'unselected'; + | 'unselected' + + /** + * String announced when a new line is inserted in the editor. + * Used when Enter is pressed and a new line is inserted in the editor. + * @example + * New line inserted + */ + | 'newLineInserted'; /** * Represents data, that can be used to announce text to screen reader. diff --git a/packages/roosterjs-editor-adapter/lib/editor/utils/eventConverter.ts b/packages/roosterjs-editor-adapter/lib/editor/utils/eventConverter.ts index 052d4808813f..03e91006f24f 100644 --- a/packages/roosterjs-editor-adapter/lib/editor/utils/eventConverter.ts +++ b/packages/roosterjs-editor-adapter/lib/editor/utils/eventConverter.ts @@ -61,6 +61,7 @@ const KnownAnnounceStringsNewToOld: Record< announceUnderlineOff: undefined, selected: undefined, unselected: undefined, + newLineInserted: undefined, }; const EntityOperationOldToNew: Record = { diff --git a/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts b/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts index 816e66cee395..027f21ea47de 100644 --- a/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts +++ b/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts @@ -873,6 +873,32 @@ describe('newEventToOldEvent', () => { expect(result.additionalData!.getEntityState!()).toEqual(mockedEntityState); }); + it('ContentChanged with unsupported announce string', () => { + const result = runTest( + { + eventType: 'contentChanged', + eventDataCache: mockedDataCache, + announceData: { + defaultStrings: 'newLineInserted', + }, + }, + undefined, + { + eventType: PluginEventType.ContentChanged, + eventDataCache: mockedDataCache, + additionalData: { + formatApiName: undefined, + getAnnounceData: jasmine.anything() as any, + getEntityState: undefined, + }, + data: undefined, + source: undefined, + } + ) as ContentChangedEvent; + + expect(result.additionalData!.getAnnounceData!()).toBeUndefined(); + }); + it('ContextMenu', () => { const mockedItems = 'ITEMS' as any; From 1673eb1149c637c2f0c52ad8a8b13b09d9286923 Mon Sep 17 00:00:00 2001 From: Bryan Valverde Date: Tue, 4 Aug 2026 11:51:52 -0600 Subject: [PATCH 2/2] Fix content changed test fixture Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0b3e8c6f-5223-4b6e-b959-5f8b209e5b10 --- .../test/editor/utils/eventConverterTest.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts b/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts index 027f21ea47de..9b921bfcf1c2 100644 --- a/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts +++ b/packages/roosterjs-editor-adapter/test/editor/utils/eventConverterTest.ts @@ -874,10 +874,12 @@ describe('newEventToOldEvent', () => { }); it('ContentChanged with unsupported announce string', () => { + const mockedSource = 'SOURCE'; const result = runTest( { eventType: 'contentChanged', eventDataCache: mockedDataCache, + source: mockedSource, announceData: { defaultStrings: 'newLineInserted', }, @@ -892,7 +894,7 @@ describe('newEventToOldEvent', () => { getEntityState: undefined, }, data: undefined, - source: undefined, + source: mockedSource, } ) as ContentChangedEvent;