Skip to content

Commit 8cae9fc

Browse files
authored
[Hot fix] Bump Rooster api, plugins and types package (#3218)
Bump Rooster api, plugins and types package to 9.43.0
1 parent 8a71701 commit 8cae9fc

File tree

8 files changed

+226
-22
lines changed

8 files changed

+226
-22
lines changed

packages/roosterjs-content-model-api/lib/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export { setModelListStartNumber } from './modelApi/list/setModelListStartNumber
5959
export { findListItemsInSameThread } from './modelApi/list/findListItemsInSameThread';
6060
export { setModelIndentation } from './modelApi/block/setModelIndentation';
6161
export { matchLink } from './modelApi/link/matchLink';
62-
export { promoteLink } from './modelApi/link/promoteLink';
62+
export { promoteLink, getPromoteLink } from './modelApi/link/promoteLink';
6363
export { getListAnnounceData } from './modelApi/list/getListAnnounceData';
6464
export { queryContentModelBlocks } from './modelApi/common/queryContentModelBlocks';
6565
export { adjustWordSelection } from './modelApi/selection/adjustWordSelection';

packages/roosterjs-content-model-api/lib/modelApi/link/getLinkUrl.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ const MAILTO_REGEX = `(M|m)ailto:${COMMON_REGEX}`;
1010
*/
1111
export function getLinkUrl(text: string, autoLinkOptions?: AutoLinkOptions): string | undefined {
1212
const { autoLink, autoMailto, autoTel } = autoLinkOptions ?? {};
13+
const mailtoMatch = matchMailTo(text);
14+
if (mailtoMatch && !autoMailto) {
15+
return undefined;
16+
}
1317
const linkMatch = autoLink ? matchLink(text)?.normalizedUrl : undefined;
1418
const telMatch = autoTel ? matchTel(text) : undefined;
15-
const mailtoMatch = autoMailto ? matchMailTo(text) : undefined;
1619

1720
return linkMatch || telMatch || mailtoMatch;
1821
}

packages/roosterjs-content-model-api/lib/modelApi/link/promoteLink.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { splitTextSegment } from '../../publicApi/segment/splitTextSegment';
33
import type {
44
AutoLinkOptions,
55
ContentModelText,
6+
PromotedLink,
67
ShallowMutableContentModelParagraph,
78
} from 'roosterjs-content-model-types';
89

@@ -25,20 +26,19 @@ export function promoteLink(
2526
if (segment.link) {
2627
return null;
2728
}
28-
const link = segment.text.split(' ').pop();
29-
const url = link?.trim();
30-
let linkUrl: string | undefined = undefined;
3129

32-
if (url && link && (linkUrl = getLinkUrl(url, autoLinkOptions))) {
30+
const promotedLink = getPromoteLink(segment, autoLinkOptions);
31+
32+
if (promotedLink) {
3333
const linkSegment = splitTextSegment(
3434
segment,
3535
paragraph,
36-
segment.text.length - link.trimLeft().length,
36+
segment.text.length - promotedLink.label.trimLeft().length,
3737
segment.text.trimRight().length
3838
);
3939
linkSegment.link = {
4040
format: {
41-
href: linkUrl,
41+
href: promotedLink.href,
4242
underline: true,
4343
},
4444
dataset: {},
@@ -49,3 +49,25 @@ export function promoteLink(
4949

5050
return null;
5151
}
52+
53+
/**
54+
* Verify if the link can be promoted
55+
* @param segment The text segment to search link text from
56+
* @param options Options of auto link
57+
* @returns if a link can be promoted
58+
*/
59+
export function getPromoteLink(
60+
segment: ContentModelText,
61+
autoLinkOptions: AutoLinkOptions
62+
): PromotedLink | undefined {
63+
const link = segment.text.split(' ').pop();
64+
const url = link?.trim();
65+
let linkUrl: string | undefined = undefined;
66+
if (url && link && (linkUrl = getLinkUrl(url, autoLinkOptions))) {
67+
return {
68+
label: link,
69+
href: linkUrl,
70+
};
71+
}
72+
return undefined;
73+
}

packages/roosterjs-content-model-api/test/modelApi/link/promoteLinkTest.ts

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { formatTextSegmentBeforeSelectionMarker } from 'roosterjs-content-model-api';
2-
import { promoteLink } from '../../../lib/modelApi/link/promoteLink';
2+
import { getPromoteLink, promoteLink } from '../../../lib/modelApi/link/promoteLink';
33
import {
4+
AutoLinkOptions,
45
ContentModelDocument,
56
ContentModelParagraph,
67
ContentModelText,
8+
PromotedLink,
79
} from 'roosterjs-content-model-types';
810

911
describe('promoteLink', () => {
@@ -897,3 +899,152 @@ describe('formatTextSegmentBeforeSelectionMarker - createLinkAfterSpace', () =>
897899
runTest(input, expected, false);
898900
});
899901
});
902+
903+
describe('getPromoteLink', () => {
904+
function runTest(
905+
text: string,
906+
autoLinkOptions: AutoLinkOptions,
907+
expectedResult: PromotedLink | undefined
908+
) {
909+
const segment: ContentModelText = {
910+
segmentType: 'Text',
911+
text: text,
912+
format: {},
913+
};
914+
915+
const result = getPromoteLink(segment, autoLinkOptions);
916+
expect(result).toEqual(expectedResult);
917+
}
918+
919+
it('with http link', () => {
920+
runTest(
921+
'test http://bing.com',
922+
{ autoLink: true, autoMailto: true, autoTel: true },
923+
{ label: 'http://bing.com', href: 'http://bing.com' }
924+
);
925+
});
926+
927+
it('with https link', () => {
928+
runTest(
929+
'test https://bing.com',
930+
{ autoLink: true, autoMailto: true, autoTel: true },
931+
{ label: 'https://bing.com', href: 'https://bing.com' }
932+
);
933+
});
934+
935+
it('with www link', () => {
936+
runTest(
937+
'test www.bing.com',
938+
{ autoLink: true, autoMailto: true, autoTel: true },
939+
{ label: 'www.bing.com', href: 'http://www.bing.com' }
940+
);
941+
});
942+
943+
it('with mailto link', () => {
944+
runTest(
945+
'test mailto:[email protected]',
946+
{ autoLink: true, autoMailto: true, autoTel: true },
947+
{ label: 'mailto:[email protected]', href: 'mailto:[email protected]' }
948+
);
949+
});
950+
951+
it('with tel link', () => {
952+
runTest(
953+
'test tel:123-456-7890',
954+
{ autoLink: true, autoMailto: true, autoTel: true },
955+
{ label: 'tel:123-456-7890', href: 'tel:123-456-7890' }
956+
);
957+
});
958+
959+
it('with Tel link (uppercase)', () => {
960+
runTest(
961+
'test Tel:123-456-7890',
962+
{ autoLink: true, autoMailto: true, autoTel: true },
963+
{ label: 'Tel:123-456-7890', href: 'tel:123-456-7890' }
964+
);
965+
});
966+
967+
it('with Mailto link (uppercase)', () => {
968+
runTest(
969+
'test Mailto:[email protected]',
970+
{ autoLink: true, autoMailto: true, autoTel: true },
971+
{ label: 'Mailto:[email protected]', href: 'Mailto:[email protected]' }
972+
);
973+
});
974+
975+
it('no link in text', () => {
976+
runTest('just plain text', { autoLink: true, autoMailto: true, autoTel: true }, undefined);
977+
});
978+
979+
it('link in middle of text', () => {
980+
runTest(
981+
'http://bing.com followed by text',
982+
{ autoLink: true, autoMailto: true, autoTel: true },
983+
undefined
984+
);
985+
});
986+
987+
it('only link text', () => {
988+
runTest(
989+
'http://bing.com',
990+
{ autoLink: true, autoMailto: true, autoTel: true },
991+
{ label: 'http://bing.com', href: 'http://bing.com' }
992+
);
993+
});
994+
995+
it('autoLink disabled', () => {
996+
runTest(
997+
'test http://bing.com',
998+
{ autoLink: false, autoMailto: true, autoTel: true },
999+
undefined
1000+
);
1001+
});
1002+
1003+
it('autoMailto disabled', () => {
1004+
runTest(
1005+
'test mailto:[email protected]',
1006+
{ autoLink: true, autoMailto: false, autoTel: true },
1007+
undefined
1008+
);
1009+
});
1010+
1011+
it('autoTel disabled', () => {
1012+
runTest(
1013+
'test tel:123-456-7890',
1014+
{ autoLink: true, autoMailto: true, autoTel: false },
1015+
undefined
1016+
);
1017+
});
1018+
1019+
it('empty text', () => {
1020+
runTest('', { autoLink: true, autoMailto: true, autoTel: true }, undefined);
1021+
});
1022+
1023+
it('only spaces', () => {
1024+
runTest(' ', { autoLink: true, autoMailto: true, autoTel: true }, undefined);
1025+
});
1026+
1027+
it('tel with space (should not match)', () => {
1028+
runTest(
1029+
'test tel: 123-456-7890',
1030+
{ autoLink: true, autoMailto: true, autoTel: true },
1031+
undefined
1032+
);
1033+
});
1034+
1035+
it('mailto with space (should not match)', () => {
1036+
runTest(
1037+
'test mailto: [email protected]',
1038+
{ autoLink: true, autoMailto: true, autoTel: true },
1039+
undefined
1040+
);
1041+
});
1042+
1043+
it('invalid tel format', () => {
1044+
runTest(
1045+
'test tels:123-456-7890',
1046+
{ autoLink: true, autoMailto: true, autoTel: true },
1047+
undefined
1048+
);
1049+
});
1050+
});

packages/roosterjs-content-model-plugins/lib/autoFormat/AutoFormatPlugin.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { ChangeSource } from 'roosterjs-content-model-dom';
22
import { checkAndInsertHorizontalLine } from './horizontalLine/checkAndInsertHorizontalLine';
33
import { createLink } from './link/createLink';
4-
import { formatTextSegmentBeforeSelectionMarker, promoteLink } from 'roosterjs-content-model-api';
54
import { getListTypeStyle } from './list/getListTypeStyle';
65
import { keyboardListTrigger } from './list/keyboardListTrigger';
76
import { transformFraction } from './numbers/transformFraction';
87
import { transformHyphen } from './hyphen/transformHyphen';
98
import { transformOrdinals } from './numbers/transformOrdinals';
109
import { unlink } from './link/unlink';
10+
import {
11+
formatTextSegmentBeforeSelectionMarker,
12+
promoteLink,
13+
getPromoteLink,
14+
} from 'roosterjs-content-model-api';
1115
import type { AutoFormatOptions } from './interface/AutoFormatOptions';
1216
import type {
1317
ContentChangedEvent,
@@ -112,17 +116,22 @@ export class AutoFormatPlugin implements EditorPlugin {
112116
selection.range.collapsed &&
113117
rawEvent.data == ' '
114118
) {
115-
formatTextSegmentBeforeSelectionMarker(editor, (model, previousSegment, paragraph) => {
116-
const { autoLink, autoTel, autoMailto, autoBullet, autoNumbering } = this.options;
117-
const list = getListTypeStyle(model, autoBullet, autoNumbering);
118-
const link = promoteLink(previousSegment, paragraph, {
119-
autoLink,
120-
autoTel,
121-
autoMailto,
122-
});
123-
shouldHandle = !!link || !!list;
124-
return false;
125-
});
119+
const { autoLink, autoTel, autoMailto, autoBullet, autoNumbering } = this.options;
120+
121+
formatTextSegmentBeforeSelectionMarker(
122+
editor,
123+
(model, previousSegment, _paragraph, _markerFormat) => {
124+
const list = getListTypeStyle(model, autoBullet, autoNumbering);
125+
const promotedLink = getPromoteLink(previousSegment, {
126+
autoLink,
127+
autoTel,
128+
autoMailto,
129+
});
130+
shouldHandle = !!promotedLink || !!list;
131+
132+
return false;
133+
}
134+
);
126135
}
127136
return shouldHandle;
128137
}
@@ -251,6 +260,7 @@ export class AutoFormatPlugin implements EditorPlugin {
251260
paragraph,
252261
context
253262
);
263+
254264
if (result) {
255265
if (typeof result !== 'boolean') {
256266
formatOptions.getChangeData = () => result;

packages/roosterjs-content-model-types/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ export {
459459
export { ConflictFormatSolution } from './parameter/ConflictFormatSolution';
460460
export { ParagraphMap, ParagraphIndexer } from './parameter/ParagraphMap';
461461
export { TextAndHtmlContentForCopy } from './parameter/TextAndHtmlContentForCopy';
462+
export { PromotedLink } from './parameter/PromotedLink';
462463

463464
export { BasePluginEvent, BasePluginDomEvent } from './event/BasePluginEvent';
464465
export { BeforeAddUndoSnapshotEvent } from './event/BeforeAddUndoSnapshotEvent';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* The link label and href for promoted link
3+
*/
4+
export interface PromotedLink {
5+
/**
6+
* The label for the promoted link
7+
*/
8+
label: string;
9+
/**
10+
* The href for the promoted link
11+
*/
12+
href: string;
13+
}

versions.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,9 @@
22
"react": "9.0.3",
33
"main": "9.42.0",
44
"legacyAdapter": "8.65.2",
5-
"overrides": {}
5+
"overrides": {
6+
"roosterjs-content-model-api": "9.43.0",
7+
"roosterjs-content-model-plugins": "9.43.0",
8+
"roosterjs-content-model-types": "9.43.0"
9+
}
610
}

0 commit comments

Comments
 (0)