Skip to content

Commit 6c156f9

Browse files
authored
Merge pull request #21 from KnightNiwrem/copilot/fix-20
feat: Add entity consolidation to FormattedString.join method
2 parents 4a43257 + b77a0f2 commit 6c156f9

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

src/format.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,12 +332,18 @@ export class FormattedString
332332
}
333333

334334
const sep = separator ?? "";
335-
return items.reduce<FormattedString>((acc, item, index) => {
335+
const result = items.reduce<FormattedString>((acc, item, index) => {
336336
if (index === 0) {
337337
return fmt`${item}`;
338338
}
339339
return fmt`${acc}${sep}${item}`;
340340
}, new FormattedString(""));
341+
342+
// Consolidate adjacent/overlapping entities of the same type
343+
return new FormattedString(
344+
result.rawText,
345+
result.consolidateEntities(result.rawEntities),
346+
);
341347
}
342348

343349
// Instance formatting methods

test/format.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,75 @@ Deno.test("FormattedString - Static join method with separator", () => {
844844
assertEquals(result9.rawEntities[0]?.length, 2); // "->"
845845
});
846846

847+
Deno.test("FormattedString - Static join method entity behavior", () => {
848+
// Test entity behavior when joining FormattedStrings
849+
const boldText1 = FormattedString.bold("Hello");
850+
const boldText2 = FormattedString.bold("World");
851+
852+
const result = FormattedString.join([boldText1, boldText2], " ");
853+
854+
assertInstanceOf(result, FormattedString);
855+
assertEquals(result.rawText, "Hello World");
856+
857+
// Should have two separate bold entities because the space separator is not bold
858+
assertEquals(result.rawEntities.length, 2);
859+
assertEquals(result.rawEntities[0]?.type, "bold");
860+
assertEquals(result.rawEntities[0]?.offset, 0);
861+
assertEquals(result.rawEntities[0]?.length, 5); // "Hello"
862+
assertEquals(result.rawEntities[1]?.type, "bold");
863+
assertEquals(result.rawEntities[1]?.offset, 6);
864+
assertEquals(result.rawEntities[1]?.length, 5); // "World"
865+
866+
// Test without separator - should also consolidate
867+
const resultNoSep = FormattedString.join([boldText1, boldText2]);
868+
869+
assertInstanceOf(resultNoSep, FormattedString);
870+
assertEquals(resultNoSep.rawText, "HelloWorld");
871+
assertEquals(resultNoSep.rawEntities.length, 1);
872+
assertEquals(resultNoSep.rawEntities[0]?.type, "bold");
873+
assertEquals(resultNoSep.rawEntities[0]?.offset, 0);
874+
assertEquals(resultNoSep.rawEntities[0]?.length, 10); // "HelloWorld"
875+
876+
// Test with different entity types - should NOT consolidate
877+
const boldText = FormattedString.bold("Hello");
878+
const italicText = FormattedString.italic("World");
879+
880+
const mixedResult = FormattedString.join([boldText, italicText], " ");
881+
882+
assertInstanceOf(mixedResult, FormattedString);
883+
assertEquals(mixedResult.rawText, "Hello World");
884+
assertEquals(mixedResult.rawEntities.length, 2); // Should remain separate
885+
assertEquals(mixedResult.rawEntities[0]?.type, "bold");
886+
assertEquals(mixedResult.rawEntities[1]?.type, "italic");
887+
888+
// Test with FormattedString separator between same entity types
889+
const boldSeparator = FormattedString.bold(" | ");
890+
const resultWithBoldSep = FormattedString.join(
891+
[boldText1, boldText2],
892+
boldSeparator,
893+
);
894+
895+
assertInstanceOf(resultWithBoldSep, FormattedString);
896+
assertEquals(resultWithBoldSep.rawText, "Hello | World");
897+
assertEquals(resultWithBoldSep.rawEntities.length, 1); // All bold parts should be consolidated
898+
assertEquals(resultWithBoldSep.rawEntities[0]?.type, "bold");
899+
assertEquals(resultWithBoldSep.rawEntities[0]?.offset, 0);
900+
assertEquals(resultWithBoldSep.rawEntities[0]?.length, 13); // "Hello | World"
901+
902+
// Test that single item doesn't go through consolidation path
903+
const singleResult = FormattedString.join([boldText1]);
904+
assertInstanceOf(singleResult, FormattedString);
905+
assertEquals(singleResult.rawText, "Hello");
906+
assertEquals(singleResult.rawEntities.length, 1);
907+
assertEquals(singleResult.rawEntities[0]?.type, "bold");
908+
909+
// Test empty array
910+
const emptyResult = FormattedString.join([]);
911+
assertInstanceOf(emptyResult, FormattedString);
912+
assertEquals(emptyResult.rawText, "");
913+
assertEquals(emptyResult.rawEntities.length, 0);
914+
});
915+
847916
Deno.test("FormattedString - Instance slice method", () => {
848917
// Test the example from the problem statement
849918
const originalText = "hello bold and italic world";

0 commit comments

Comments
 (0)