Skip to content

Commit

Permalink
Fix #18: Don't add space before indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr committed Jul 10, 2024
1 parent 61f7f42 commit 2098307
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- `text-clipper` has become a Deno-first library and is now available on [Jsr.io](https://jsr.io).
Instructions for installation on Node.js/Bun are still included.
- Fix #18: Don't include spaces before the indicator.

## 2.2.0

Expand Down
19 changes: 15 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,16 +518,22 @@ function clipHtml(string: string, maxLength: number, options: ClipHtmlOptions):
// of words, but given this seems highly unlikely and the alternative is
// doing another full parsing of the preceding text, this seems acceptable.
break;
} else if (charCode === NEWLINE_CHAR_CODE || charCode === TAG_OPEN_CHAR_CODE) {
} else if (
charCode === NEWLINE_CHAR_CODE ||
charCode === TAG_OPEN_CHAR_CODE ||
isWhiteSpace(charCode)
) {
i = j;
break;
} else if (isWhiteSpace(charCode)) {
i = j + (indicator ? 1 : 0);
break;
}
}
}

// Don't leave awkward whitespace before the ellipsis.
while (i > 0 && isWhiteSpace(string.charCodeAt(i - 1)!)) {
i--;
}

let result = string.slice(0, i);
if (!isLineBreak(string, i)) {
result += indicator;
Expand Down Expand Up @@ -596,6 +602,11 @@ function clipPlainText(string: string, maxLength: number, options: CommonClipOpt
}
}

// Don't leave awkward whitespace before the ellipsis.
while (i > 0 && isWhiteSpace(string.charCodeAt(i - 1)!)) {
i--;
}

return string.slice(0, i) + (nextChar === "\n" ? "" : indicator);
} else if (numLines > maxLines) {
return string.slice(0, i);
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/examples.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import clip from "../../src/index.ts";
Deno.test("examples: test examples from the README", () => {
assertEquals(clip("foo", 3), "foo");
assertEquals(clip("foo", 2), "f…");
assertEquals(clip("foo bar", 5), "foo …");
assertEquals(clip("foo bar", 5), "foo…");
assertEquals(clip("foo\nbar", 5), "foo");
});
33 changes: 15 additions & 18 deletions tests/unit/html.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ Deno.test("html: test basic HTML", () => {
assertEquals(clip("<p>Lorum ipsum</p>", 5, options), "<p>Loru\u2026</p>");
assertEquals(clip("<p><i>Lorum</i> <i>ipsum</i></p>", 5, options), "<p><i>Loru\u2026</i></p>");
assertEquals(clip("<p><i>Lorum</i> <i>ipsum</i></p>", 6, options), "<p><i>Lorum</i>\u2026</p>");
assertEquals(
clip("<p><i>Lorum</i> <i>ipsum</i></p>", 7, options),
"<p><i>Lorum</i> \u2026</p>",
);
assertEquals(clip("<p><i>Lorum</i> <i>ipsum</i></p>", 7, options), "<p><i>Lorum</i>\u2026</p>");
assertEquals(clip("<p><i>Lorum</i>\n<i>ipsum</i></p>", 5, options), "<p><i>Lorum</i></p>");
assertEquals(clip("<p><i>Lorum</i><br><i>ipsum</i></p>", 5, options), "<p><i>Lorum</i></p>");

Expand Down Expand Up @@ -44,7 +41,7 @@ Deno.test("html: test basic HTML", () => {

assertEquals(
clip('<a href="http://just-a-link.com">Just a link</a>', 8, options),
'<a href="http://just-a-link.com">Just a \u2026</a>',
'<a href="http://just-a-link.com">Just a\u2026</a>',
);

assertEquals(
Expand Down Expand Up @@ -150,10 +147,10 @@ Deno.test("html: test plain text", () => {

assertEquals(clip("Lorum ipsum", 5, options), "Loru\u2026");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 8, options), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 9, options), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 10, options), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 8, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 9, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 10, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 11, options), "Lorum ipsum");

assertEquals(clip("Lorum\nipsum", 10, options), "Lorum");
Expand All @@ -167,7 +164,7 @@ Deno.test("html: test word breaking", () => {

assertEquals(clip("Lorum ipsum", 5, options), "Loru\u2026");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 8, options), "Lorum i\u2026");
assertEquals(clip("Lorum ipsum", 9, options), "Lorum ip\u2026");
assertEquals(clip("Lorum ipsum", 10, options), "Lorum ips\u2026");
Expand All @@ -178,7 +175,7 @@ Deno.test("html: test word breaking without indicator", () => {
const options = { breakWords: true, html: true, indicator: "" };

assertEquals(clip("Lorum ipsum", 5, options), "Lorum");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum ");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum i");
assertEquals(clip("Lorum ipsum", 8, options), "Lorum ip");
assertEquals(clip("Lorum ipsum", 9, options), "Lorum ips");
Expand Down Expand Up @@ -251,7 +248,7 @@ Deno.test("html: test ampersand", () => {
assertEquals(clip("<p>&amp;</p>", 1, options), "");
assertEquals(clip("<p>&amp;</p>", 2, options), "<p>&amp;</p>");

assertEquals(clip("foo & bar", 5, options), "foo \u2026");
assertEquals(clip("foo & bar", 5, options), "foo\u2026");
assertEquals(clip("foo & bar", 9, options), "foo & bar");
assertEquals(clip("foo&<i>bar</i>", 5, options), "foo&\u2026");
assertEquals(clip("foo&<i>bar</i>", 7, options), "foo&<i>bar</i>");
Expand Down Expand Up @@ -421,13 +418,13 @@ Deno.test("html: test strip tags", () => {
);
assertEquals(
clip(htmlWithImage, 12, { html: true, stripTags: ["img"] }),
"<p>Image and \u2026</p>",
"<p>Image and\u2026</p>",
);
assertEquals(
clip(htmlWithImage, 12, { html: true, stripTags: ["img", "p"] }),
"Image and \u2026",
"Image and\u2026",
);
assertEquals(clip(htmlWithImage, 12, { html: true, stripTags: true }), "Image and \u2026");
assertEquals(clip(htmlWithImage, 12, { html: true, stripTags: true }), "Image and\u2026");
assertEquals(
clip(htmlWithImage, 15, { html: true, stripTags: ["img"] }),
"<p>Image and such</p>",
Expand Down Expand Up @@ -455,11 +452,11 @@ Deno.test("html: test strip tags", () => {
</tr>
</tbody>
</table> world`;
assertEquals(clip(htmlWithTable, 10, { html: true, stripTags: true }), "hello fb \u2026");
assertEquals(clip(htmlWithTable, 16, { html: true, stripTags: true }), "hello fb fbfbfb ");
assertEquals(clip(htmlWithTable, 10, { html: true, stripTags: true }), "hello fb\u2026");
assertEquals(clip(htmlWithTable, 16, { html: true, stripTags: true }), "hello fb fbfbfb\u2026");
assertEquals(
clip(htmlWithTable, 24, { html: true, stripTags: true }),
"hello fb fbfbfb google \u2026",
"hello fb fbfbfb google\u2026",
);

// SVG's `imageWeight` should not be counted when stripped:
Expand Down
12 changes: 6 additions & 6 deletions tests/unit/plain-text.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import clip from "../../src/index.ts";
Deno.test("plain-text: test basics", () => {
assertEquals(clip("Lorum ipsum", 5), "Loru\u2026");
assertEquals(clip("Lorum ipsum", 6), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 7), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 8), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 9), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 10), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 7), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 8), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 9), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 10), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 11), "Lorum ipsum");

assertEquals(clip("Lorum\nipsum", 10), "Lorum");
Expand All @@ -32,7 +32,7 @@ Deno.test("plain-text: test word breaking", () => {

assertEquals(clip("Lorum ipsum", 5, options), "Loru\u2026");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum \u2026");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum\u2026");
assertEquals(clip("Lorum ipsum", 8, options), "Lorum i\u2026");
assertEquals(clip("Lorum ipsum", 9, options), "Lorum ip\u2026");
assertEquals(clip("Lorum ipsum", 10, options), "Lorum ips\u2026");
Expand All @@ -43,7 +43,7 @@ Deno.test("plain-text: test word breaking without indicator", () => {
const options = { breakWords: true, indicator: "" };

assertEquals(clip("Lorum ipsum", 5, options), "Lorum");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum ");
assertEquals(clip("Lorum ipsum", 6, options), "Lorum");
assertEquals(clip("Lorum ipsum", 7, options), "Lorum i");
assertEquals(clip("Lorum ipsum", 8, options), "Lorum ip");
assertEquals(clip("Lorum ipsum", 9, options), "Lorum ips");
Expand Down

0 comments on commit 2098307

Please sign in to comment.