Skip to content

Commit

Permalink
fix(ui-truncate): truncate should not split words appart (#690)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Updated the truncation logic to focus on an 'ideal length' for string
truncation, simplifying how text is displayed.
  
- **Bug Fixes**
- Adjusted test cases to reflect the new expected output for truncated
strings, ensuring accuracy in displayed text.

- **Documentation**
- Enhanced clarity in the `Truncate` component's functionality by
refining parameter names and logic.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
aversini authored Sep 24, 2024
1 parent 70ba5f7 commit 67b1686
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 40 deletions.
2 changes: 1 addition & 1 deletion packages/ui-truncate/src/components/Truncate/Truncate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const Truncate = ({
}
const { string, isTruncated } = truncate({
string: children,
length,
idealLength: length,
});

const handleToggleExpanded = (e: { preventDefault: () => void }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe("Truncate Component", () => {
it('should render truncated text and "more..." button when children is a string and exceeds length', () => {
const text = "This is a long text that needs to be truncated.";
render(<Truncate length={20}>{text}</Truncate>);
expect(screen.getByText("This is")).toBeInTheDocument();
expect(screen.getByText("This is a long text that")).toBeInTheDocument();
expect(screen.getByText("more...")).toBeInTheDocument();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,36 @@
import { describe, expect, it } from "vitest";
import { truncate } from "../utilities.ts"; // Adjust the import path as needed
import { truncate } from "../utilities.ts";

describe("truncate", () => {
it("should return the original string if length is greater than or equal to string length", () => {
it("should truncate at the ideal length", () => {
const result = truncate({
string: "Hello, World!",
length: 20,
idealLength: 6,
});
expect(result).toEqual({ string: "Hello, World!", isTruncated: false });
});

it("should truncate the string if length is less than string length", () => {
const result = truncate({
string: "Hello, World!",
length: 5,
omission: "...",
});
expect(result).toEqual({ string: "He", isTruncated: true });
expect(result).toEqual({ string: "Hello,", isTruncated: true });
});

it("should return an empty string if length is less than omission length", () => {
it("should truncate at the next space found right after the ideal length", () => {
const result = truncate({
string: "Hello, World!",
length: 2,
omission: "...",
idealLength: 4,
});
expect(result).toEqual({ string: "", isTruncated: true });
expect(result).toEqual({ string: "Hello,", isTruncated: true });
});

it("should handle edge case where length equals omission length", () => {
it("should truncate at the next space found right after the ideal length", () => {
const result = truncate({
string: "Hello, World!",
length: 3,
omission: "...",
string: "Hello, World! This is your time to shine!",
idealLength: 8,
});
expect(result).toEqual({ string: "", isTruncated: true });
expect(result).toEqual({ string: "Hello, World!", isTruncated: true });
});

it("should handle edge case where omission is an empty string", () => {
it("should handle edge case where ideal length is more than string length", () => {
const result = truncate({
string: "Hello, World!",
length: 5,
omission: "",
idealLength: 20,
});
expect(result).toEqual({ string: "Hello", isTruncated: true });
expect(result).toEqual({ string: "Hello, World!", isTruncated: false });
});
});
31 changes: 19 additions & 12 deletions packages/ui-truncate/src/components/Truncate/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
export const DEFAULT_LENGTH = 200;
export const DEFAULT_OMISSION = "===+-av-+===";

type TruncateOptions = {
string: string;
length?: number;
omission?: string;
idealLength?: number;
};
type TruncateResult = {
string: string;
isTruncated: boolean;
};

/**
* This function will truncate the string at the last word boundary
* before the ideal length.
* - If ideal length ends up in the middle of a word, truncate at the next space.
* - If ideal length ends up on a space, truncate at the ideal length.
*/
export const truncate = ({
string,
length = DEFAULT_LENGTH,
omission = DEFAULT_OMISSION,
idealLength = DEFAULT_LENGTH,
}: TruncateOptions): TruncateResult => {
const strLength = string.length;
if (length >= strLength) {
return { string, isTruncated: false };
if (strLength <= idealLength) {
return { string: string, isTruncated: false };
}
const end = length - omission.length;
if (end < 1) {
return { string: "", isTruncated: true };

const originalTrunc = string.charAt(idealLength);
if (originalTrunc === " ") {
return { string: string.slice(0, idealLength), isTruncated: true };
}
const result = string.slice(0, end);

return { string: result, isTruncated: true };
const nextSpace = string.slice(idealLength).search(" ");
return {
string: string.slice(0, idealLength + nextSpace),
isTruncated: true,
};
};

0 comments on commit 67b1686

Please sign in to comment.