zudo-doc
GitHub repository

Type to search...

to open search from anywhere

Smart Break Utility

Created Apr 23, 2026Updated Jul 15, 2026Takeshi Takatsudo

Inject <wbr> hints into long path-like strings so they wrap cleanly in narrow UI.

Long URLs and filesystem paths — for example packages/zudo-doc/src/smart-break/index.tsx — do not wrap at arbitrary character boundaries. In narrow UI (sidebar labels, breadcrumbs, inline code, search snippets) they overflow the container or push layout wider than it should be.

The package's smart-break utility solves this by injecting <wbr> (word-break opportunity) hints after each delimiter in strings that look path-like. The browser then decides where to break based on available width.

Automatic Behavior

Several zudo-doc surfaces already apply smart-break automatically — no configuration needed:

  • Sidebar tree labels — category and page labels

  • Breadcrumbs — current-page trail

  • MDX links — anchor text inside prose

  • MDX inline code — backtick spans inside prose

  • Search results — titles and snippets in the search dialog

  • Doc history — commit message rendering

You only need to invoke the utility yourself when building a custom component that renders user-provided path-like strings.

Manual Opt-In: SmartBreak Component

For Preact islands (or any .tsx component in the project) use the SmartBreak component. It stringifies its children and injects <wbr> where appropriate:

import { SmartBreak } from "@takazudo/zudo-doc/smart-break";

export function FileBadge({ path }: { path: string }) {
  return (
    <span class="font-mono text-caption">
      <SmartBreak>{path}</SmartBreak>
    </span>
  );
}

If path is not path-like (plain prose, and/or, state-of-the-art, etc.) it is returned unchanged — no stray wbrs are injected.

Manual Opt-In: smartBreakToHtml Helper

Any code path that renders an HTML string (for example dangerouslySetInnerHTML) cannot mount Preact VNodes directly. Use smartBreakToHtml instead — it returns an HTML-escaped string with literal <wbr> tags injected:

import { smartBreakToHtml } from "@takazudo/zudo-doc/smart-break";

export function PathLabel({ label }: { label: string }) {
  return <span dangerouslySetInnerHTML={{ __html: smartBreakToHtml(label) }} />;
}

The returned string is already HTML-escaped, so it is safe to pass to dangerouslySetInnerHTML.

How It Decides

Smart-break does two things: it classifies the input with an isPathLike heuristic, and — only when the heuristic says yes — it splits on a fixed delimiter set and re-joins with <wbr> between segments.

Delimiter Set

Breaks are inserted after each of these characters:

/  \  -  _  .  :  ?  #  &  =

These cover URL structure (://, ?query=value&other=1, #anchor), filesystem paths (/, \), and compound identifiers (snake_case, kebab-case, file.name.ext).

The isPathLike Heuristic

isPathLike returns true for strings that look like URLs, paths, or similar delimited structures:

  • Contains :// (any URL)

  • Starts with /, ./, or ../ (POSIX paths)

  • Starts with a Windows drive prefix like C:\ or C:/

  • Has at least two slashes between alphanumerics (nested paths)

  • Has a domain-like a.b pattern combined with a slash somewhere

It returns false for prose-y fragments that happen to contain delimiters: and/or, well-known, state-of-the-art, 1.2.3-beta.4, UI/UX. These pass through unmodified so normal prose wrapping still applies.

A Realistic Sample

For an input like:

packages/zudo-doc/src/smart-break/index.tsx

isPathLike returns true and smartBreakToHtml emits (conceptually):

packages<wbr>/zudo<wbr>-doc<wbr>/src<wbr>/smart<wbr>-break<wbr>/index<wbr>.tsx

The browser keeps the line intact when the container is wide enough, and breaks at the nearest <wbr> when it must — always between segments, never mid-segment.

When Not to Use It

  • Short labels (one or two words) — there is nothing to break.

  • Intentional single-token strings where any visual break is wrong (for example a version tag you must never wrap).

  • CJK prose — the utility targets Latin-alphabet path-like strings; CJK line-wrapping is handled by the CJK-friendly markdown plugin and native browser behavior.

Revision History

Takeshi TakatsudoCreated: 2026-04-23T22:38:59+09:00Updated: 2026-07-16T07:03:38+09:00

AI Assistant

Ask a question about the documentation.

Preview theme

Loading theme previews…