Skip to content

Instantly share code, notes, and snippets.

@assaf
Created December 11, 2020 01:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save assaf/9fd5b3b78068cd086f14fb01ac24a109 to your computer and use it in GitHub Desktop.
Save assaf/9fd5b3b78068cd086f14fb01ac24a109 to your computer and use it in GitHub Desktop.
Truncate long strings, but don't break in middle of a short word
import truncate from "./truncate";
describe("Truncate string", () => {
test("empty string returns self", () => expect(truncate("")).toBe(""));
test("short string returns self", () => {
expect(truncate("word", 8)).toBe("word");
expect(truncate("too long", 8)).toBe("too long");
});
test("long string truncated at specified length", () => {
expect(truncate("ETOOMANYCHARS", 6)).toBe("ETOOM…");
expect(truncate("ETOOMANYCHARS", 12)).toBe("ETOOMANYCHA…");
});
test("short word truncated by dropping", () => {
expect(truncate("one two three", 6)).toBe("one …");
expect(truncate("one two three", 7)).toBe("one …");
expect(truncate("one two three", 8)).toBe("one two…");
expect(truncate("one two three", 9)).toBe("one two …");
});
test("long words truncated with ellipsis", () => {
expect(truncate("one toolong", 9)).toBe("one …");
expect(truncate("one toolong", 10)).toBe("one toolo…");
});
});
const minWordLengthToBreak = 5;
const dropShortWord = RegExp(`\\s\\S{1,${minWordLengthToBreak - 1}}$`);
export default function truncate(text: string, maxChars = 280): string {
if (text.length <= maxChars || maxChars < minWordLengthToBreak) return text;
const truncated = text.slice(0, maxChars - 1);
const followedByWhitespace = /\s/.test(text[maxChars - 1]!);
if (followedByWhitespace) return `${truncated}…`;
return `${truncated.replace(dropShortWord, " ")}…`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment