DEV Community

Tom
Tom

Posted on

Build a UTF-8 Note Preview Without Cutting Through a Code Point

An order note fits a character-count limit but exceeds a downstream byte budget. Cutting its encoded bytes at an arbitrary position can split a multibyte sequence. For a Shopify 3PL review screen, build an explicitly shortened preview while preserving the complete original instruction.

The TextEncoder encode() method returns UTF-8 bytes. The example below counts those bytes one Unicode code point at a time. It rejects ill-formed input using isWellFormed(), which detects lone surrogates.

Return the shortened state with the preview

This is a local display helper. It must not replace the original packing instruction or silently shorten an outbound message. It returns the full byte count and a flag so the interface can offer the complete text separately.

'use strict';
const assert = require('node:assert/strict');
const encoder = new TextEncoder();

function notePreview(text, maxBytes) {
  if (typeof text !== 'string' || !text.isWellFormed()) {
    throw new Error('Well-formed text required');
  }
  if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
    throw new Error('Nonnegative safe byte budget required');
  }
  let preview = '', used = 0;
  for (const point of text) {
    const size = encoder.encode(point).length;
    if (used + size > maxBytes) break;
    preview += point;
    used += size;
  }
  return { preview, shortened: preview !== text,
    fullBytes: encoder.encode(text).length };
}

const text = 'A📦中Z';
const expected = ['', 'A', 'A', 'A', 'A', 'A📦', 'A📦',
  'A📦', 'A📦中', text];
for (let budget = 0; budget <= 9; budget++) {
  const result = notePreview(text, budget);
  const bytes = encoder.encode(result.preview);
  assert.equal(result.preview, expected[budget]);
  assert.ok(bytes.length <= budget);
  assert.equal(new TextDecoder('utf-8', { fatal: true }).decode(bytes),
    result.preview);
  assert.equal(result.shortened, budget < 9);
  assert.equal(result.fullBytes, 9);
}
assert.equal(text, 'A📦中Z');
assert.deepEqual(notePreview('', 0),
  { preview: '', shortened: false, fullBytes: 0 });
for (const budget of [-1, 1.5, NaN, '4']) {
  assert.throws(() => notePreview(text, budget));
}
assert.throws(() => notePreview('\uD800', 4));
console.log('UTF-8 preview boundary checks passed');
Enter fullscreen mode Exit fullscreen mode

Save as note-preview.cjs and run node note-preview.cjs with Node.js 24. The checks exercise every byte boundary of ASCII, an emoji and a Chinese code point, plus invalid budgets and malformed input. No request is sent.

Preserve the operational text

A drop shipping review may show a supplier instruction, while a shopify fulfillment screen may show a seller-approved packing note. Keep the original value available and mark a shortened display clearly. If a real receiving API rejects an overlong field, resolve that error through its documented contract instead of sending this preview.

For China fulfillment, agree whether a limit counts bytes, code points or another unit. A China 3PL interface should also specify the encoding. This helper does not preserve whole grapheme clusters: combining marks and joined emoji can span multiple code points. It is unsuitable when those display boundaries must remain intact.

In a hypothetical brief named “International Fulfillment for Folligen,” document the actual field contract before using a display helper. I work with YX Fulfillment; its Shopify handover guide provides related business context. This executable example is not a deployed connector and does not establish a tested store integration.

Workstations with monitors and printers in a warehouse handling area

Warehouse workstations and equipment.

Top comments (1)

Collapse
 
elias_0549e0e2ef8cf6ad89a profile image
RAMO •

Keeping the shortened flag separate from the original packing instruction is the important bit here; a preview must never become the warehouse payload by accident. For a Hebrew/English hardware store on Next.js, I'd also include Hebrew with niqqud in the boundary tests, since valid UTF-8 can still leave a visually incomplete character. Your grapheme-cluster caveat is a useful distinction: byte-safe and display-safe aren't the same requirement.