<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Antonio Bonet</title>
    <description>The latest articles on DEV Community by Antonio Bonet (@tonyblu331).</description>
    <link>https://dev.to/tonyblu331</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3965262%2Fee8b6fc8-3b1b-4ac3-8831-5e0791978b82.png</url>
      <title>DEV Community: Antonio Bonet</title>
      <link>https://dev.to/tonyblu331</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tonyblu331"/>
    <language>en</language>
    <item>
      <title>CSS ellipsis is great. Until the string itself matters.</title>
      <dc:creator>Antonio Bonet</dc:creator>
      <pubDate>Tue, 02 Jun 2026 19:50:37 +0000</pubDate>
      <link>https://dev.to/tonyblu331/css-ellipsis-is-great-until-the-string-itself-matters-1ijl</link>
      <guid>https://dev.to/tonyblu331/css-ellipsis-is-great-until-the-string-itself-matters-1ijl</guid>
      <description>&lt;p&gt;CSS ellipsis is great.&lt;/p&gt;

&lt;p&gt;Until the string itself matters.&lt;/p&gt;

&lt;p&gt;It works when you only need to visually hide overflow.&lt;/p&gt;

&lt;p&gt;A long label.&lt;/p&gt;

&lt;p&gt;A table cell.&lt;/p&gt;

&lt;p&gt;A title inside a card.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;But sometimes your app needs more than a clipped box.&lt;/p&gt;

&lt;p&gt;Sometimes it needs the actual truncated string.&lt;/p&gt;

&lt;p&gt;Sometimes it needs to preserve a match.&lt;/p&gt;

&lt;p&gt;Sometimes it needs to cut from the middle.&lt;/p&gt;

&lt;p&gt;Sometimes it needs to prepare the text before the UI renders.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;Truncate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A small Pretext powered library for all those cases where CSS ellipsis is not enough.&lt;/p&gt;

&lt;p&gt;Even the weird ones.&lt;/p&gt;

&lt;p&gt;Try it here:&lt;/p&gt;

&lt;p&gt;Playground:&lt;br&gt;
&lt;a href="https://tonyblu331.github.io/truncate/" rel="noopener noreferrer"&gt;https://tonyblu331.github.io/truncate/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo:&lt;br&gt;
&lt;a href="https://github.com/tonyblu331/truncate" rel="noopener noreferrer"&gt;https://github.com/tonyblu331/truncate&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Most truncation starts here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And honestly, that is still the right answer for a lot of UI.&lt;/p&gt;

&lt;p&gt;CSS ellipsis does not fail.&lt;/p&gt;

&lt;p&gt;It does exactly what it is meant to do.&lt;/p&gt;

&lt;p&gt;It clips text visually.&lt;/p&gt;

&lt;p&gt;But it does not give you the final string.&lt;/p&gt;

&lt;p&gt;It does not know which part of the text matters.&lt;/p&gt;

&lt;p&gt;It does not know that a file extension should stay visible.&lt;/p&gt;

&lt;p&gt;It does not know that a search result should keep the match in view.&lt;/p&gt;

&lt;p&gt;It does not help when you need the output before rendering.&lt;/p&gt;

&lt;p&gt;It just clips.&lt;/p&gt;

&lt;p&gt;That is the gap Truncate is trying to cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Truncate does
&lt;/h2&gt;

&lt;p&gt;Truncate gives you small utilities for text truncation before it reaches the UI.&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;width based truncation&lt;/li&gt;
&lt;li&gt;multiline truncation&lt;/li&gt;
&lt;li&gt;middle cuts&lt;/li&gt;
&lt;li&gt;start cuts&lt;/li&gt;
&lt;li&gt;search aware truncation&lt;/li&gt;
&lt;li&gt;range aware truncation&lt;/li&gt;
&lt;li&gt;custom markers&lt;/li&gt;
&lt;li&gt;height aware truncation&lt;/li&gt;
&lt;li&gt;grapheme safe text&lt;/li&gt;
&lt;li&gt;DOM free usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is not to replace CSS.&lt;/p&gt;

&lt;p&gt;CSS is still the right tool when the browser only needs to hide overflow.&lt;/p&gt;

&lt;p&gt;Truncate is for the cases where your app needs to know what the final text should be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;truncate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonybonet/truncate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A very long string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;16px Inter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;But the useful part is when the case gets more specific.&lt;/p&gt;

&lt;h2&gt;
  
  
  Middle truncation
&lt;/h2&gt;

&lt;p&gt;Some strings should not only be cut from the end.&lt;/p&gt;

&lt;p&gt;Filenames.&lt;/p&gt;

&lt;p&gt;URLs.&lt;/p&gt;

&lt;p&gt;Emails.&lt;/p&gt;

&lt;p&gt;Hashes.&lt;/p&gt;

&lt;p&gt;IDs.&lt;/p&gt;

&lt;p&gt;Anything where the start and end both matter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;truncateMiddle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonybonet/truncate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;truncateMiddle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;really-long-file-name-final-final-v12.pdf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px Inter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;really-long-file-name...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is not always as useful as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;really-long...v12.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small detail.&lt;/p&gt;

&lt;p&gt;Big difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search aware truncation
&lt;/h2&gt;

&lt;p&gt;Search results should not blindly cut text and hope the useful part survives.&lt;/p&gt;

&lt;p&gt;If someone is searching inside logs, errors, docs, or long records, the preview should try to keep the match visible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;truncateAround&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonybonet/truncate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;truncateAround&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px Geist Mono&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot read properties of undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2026-06-03 14:22:10] production-api-worker...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is not as useful as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...TypeError: Cannot read properties of undefined...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That small difference makes search results, command palettes, logs, support tools, and debugging UIs feel much more intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Range aware truncation
&lt;/h2&gt;

&lt;p&gt;Sometimes you already know the exact part of the text that matters.&lt;/p&gt;

&lt;p&gt;Maybe it came from search.&lt;/p&gt;

&lt;p&gt;Maybe it came from a parser.&lt;/p&gt;

&lt;p&gt;Maybe it came from your own indexing layer.&lt;/p&gt;

&lt;p&gt;So you can preserve that range directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;truncateRange&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonybonet/truncate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;truncateRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;16px Inter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API does not only return the text.&lt;/p&gt;

&lt;p&gt;It also gives you metrics.&lt;/p&gt;

&lt;p&gt;So if the range was preserved, you know.&lt;/p&gt;

&lt;p&gt;If it could not fit, you know.&lt;/p&gt;

&lt;p&gt;No fake confidence.&lt;/p&gt;

&lt;p&gt;No silent weirdness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom markers
&lt;/h2&gt;

&lt;p&gt;You are not locked into &lt;code&gt;...&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes you want something more explicit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;truncateByWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;articleIntro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;16px Inter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;260&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; READ MORE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes you want something smaller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;truncateByWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mediaTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;16px Inter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, tiny detail.&lt;/p&gt;

&lt;p&gt;But UI is full of tiny details.&lt;/p&gt;

&lt;h2&gt;
  
  
  DOM free by default
&lt;/h2&gt;

&lt;p&gt;Truncate does not depend on reading layout from the page.&lt;/p&gt;

&lt;p&gt;At the core, it measures through Canvas2D.&lt;/p&gt;

&lt;p&gt;That makes it useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;browser apps&lt;/li&gt;
&lt;li&gt;OffscreenCanvas&lt;/li&gt;
&lt;li&gt;Node canvas polyfills&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;server side utilities&lt;/li&gt;
&lt;li&gt;pre rendered snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes you do not want to wait for the DOM to decide what the text should be.&lt;/p&gt;

&lt;p&gt;You want the string ready before it gets there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yes, it even supports GIFs
&lt;/h2&gt;

&lt;p&gt;Because every tiny UI utility eventually meets the weird case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add @tonybonet/truncate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @tonybonet/truncate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Playground:&lt;br&gt;
&lt;a href="https://tonyblu331.github.io/truncate/" rel="noopener noreferrer"&gt;https://tonyblu331.github.io/truncate/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docs:&lt;br&gt;
&lt;a href="https://github.com/tonyblu331/truncate?tab=readme-ov-file#api" rel="noopener noreferrer"&gt;https://github.com/tonyblu331/truncate?tab=readme-ov-file#api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo:&lt;br&gt;
&lt;a href="https://github.com/tonyblu331/truncate" rel="noopener noreferrer"&gt;https://github.com/tonyblu331/truncate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have a weird truncation case, send it my way.&lt;/p&gt;

&lt;p&gt;That is probably the best test for this.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
