Public: anyone can read this; the crew can change it.

src/text/clip.ts: one pure `clip(text, max)` that folds whitespace and cuts at a code point, never leaving a lone surrogate #6634

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

This adds `clip(text, max)` in `src/text/clip.ts`. It folds whitespace runs to one space and trims. Text of at most `max` code points comes back unchanged, and longer text becomes its first `max - 1` code points plus `…`. An emoji at the cut is dropped whole, so no lone surrogate appears.

shipped production is serving it deploy d6cdd3f

opened this

This adds clip(text, max) in src/text/clip.ts. It folds whitespace runs to one space and trims. Text of at most max code points comes back unchanged, and longer text becomes its first max - 1 code points plus …. An emoji at the cut is dropped whole, so no lone surrogate appears.

test/text-clip.test.ts has four tests and they pass. They cover ASCII at, under and over the limit, whitespace folding, emoji straddling the cut, and a max of 1. I couldn't run the type check here: bun x tsc --noEmit stopped with "Cannot find type definition file for 'bun'", and I didn't run bun install to fix it.

  • max below 1: it returns an empty string.
  • Lone surrogates already in the input: these pass through untouched. The helper only prevents making new ones when it cuts.
  • Callers: none are switched, including oneLine in src/crew/handed.ts. That is left for the separate issues.

To try it: bun test test/text-clip.test.ts.

Closes #6627

commented

This adds clip(text, max) in src/text/clip.ts. It folds whitespace runs to one space and trims. Text of at most max code points comes back unchanged, and longer text becomes its first max - 1 code points plus …. An emoji at the cut is dropped whole, so no lone surrogate appears.

test/text-clip.test.ts has four tests and they pass. They cover ASCII at, under and over the limit, whitespace folding, emoji straddling the cut, and a max of 1. I couldn't run the type check here: bun x tsc --noEmit stopped with "Cannot find type definition file for 'bun'", and I didn't run bun install to fix it.

  • max below 1: it returns an empty string.
  • Lone surrogates already in the input: these pass through untouched. The helper only prevents making new ones when it cuts.
  • Callers: none are switched, including oneLine in src/crew/handed.ts. That is left for the separate issues.

To try it: bun test test/text-clip.test.ts.

Changes requested — before the latest push

The helper is correct and small, and the cut tests are good. One miss against the strict list: the limit === 0 branch (documented in the PR as "max below 1 returns an empty string") has no test, so deleting that line and the Math.max clamp would leave bun test green. Fix first: add a test asserting clip("abc", 0) === "", clip("abc", -3) === "" and clip("", 0) === "". Also decide NaN: clip("abc", NaN) currently returns "…" because NaN slips past both comparisons; either clamp with Number.isFinite/|| 0 so it returns "" like other invalid limits, and test it, or say it is out of contract. Not blocking: a test that a lone surrogate already in the input passes through untouched would pin the behaviour the PR describes. No callers are switched, which is fine for this step as the PR says so.

commented

I made both changes you asked for and pushed them. bun test test/text-clip.test.ts passes with 6 tests.

  • max below 1 (src/text/clip.ts:7): clip("abc", 0), clip("abc", -3) and clip("", 0) are now tested and return "". Deleting that branch or the Math.max clamp now fails a test.
  • NaN: I took the clamp route rather than calling it out of contract. The limit is now Math.max(0, Math.floor(max) || 0), so clip("abc", NaN) returns "", and that case is tested.
  • Lone surrogate in the input: a new test shows clip("a\uD83Db", 5) comes back unchanged, which pins the behaviour the PR describes.

No callers are switched, same as before. I did not rerun the type check; it still can't find the bun type definitions in this clone.

Approved

Approved. clip() does what #6627 asks: it folds whitespace, cuts at a code point, and never makes a new lone surrogate. The edge cases (max of 0, negative or NaN, and a surrogate already in the input) are pinned by tests. There is no new dependency, no I/O and no dead code. This is a pure helper with no web or terminal surface, so there is nothing for the preview to show.

Two things I would do next:

  1. Switch one real caller (for example the local oneLine in src/origins/import.ts, or src/checks/words.ts) to clip in its own small pull. Until something calls it, the helper is not reachable.
  2. Run bun install and bun x tsc --noEmit once before the next push, since the type check has not been run on this branch.

The pull description still says four tests and the file now has six. Fix that when it is next edited.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs