@weasel-js/bidi
v1.13.0
Published
The Unicode Bidirectional Algorithm (UAX #9) for weasel: embedding levels, reordering and mirroring. Plain data in, plain data out; no renderer and no scene graph.
Readme
@weasel-js/bidi
The Unicode Bidirectional Algorithm (UAX #9), as a standalone leaf: code points and a direction in, embedding levels and a visual order out.
No fonts, no glyphs, no canvas, no DOM, and no dependencies. Nothing else in weasel depends
on this package — a text layout that wants bidi is handed an implementation of BidiEngine,
and one that isn't lays out in logical order.
import { analyze, reorder } from '@weasel-js/bidi';
const codePoints = [...'שלום 25'].map((c) => c.codePointAt(0)!);
const paragraph = analyze(codePoints); // 'auto' — first-strong, so RTL here
const { order } = reorder(paragraph, 0, codePoints.length);
// `order` indexes codePoints in display order; the digits stay 2 then 5.Two calls because the algorithm splits at exactly one place. analyze is per paragraph;
reorder is per line, because L1 resets trailing whitespace against the end of a line
rather than the end of a paragraph. Wrap between them, and one analysis serves every line.
mirror(cp) is L4, applied at paint time against a character's resolved level — the same
code point mirrors in one run and not in another. baseLevel(paragraph) is the level the
paragraph reads at, which under 'auto' is what its first strong character decided.
Giving it to weasel's text
import { bidi } from '@weasel-js/bidi';
import { registerBidi } from '@weasel-js/core';
registerBidi(bidi); // once, at startupEvery text layout after that reorders right-to-left text: what a canvas paints, picks, and
places a caret in, and what measureTextBounds and textToPath report.
What this does not do
Ordering only. Arabic still renders unjoined: joining forms are OpenType GSUB
substitutions, not a reordering, and belong to a shaping engine. Hebrew, Divehi and the other
non-joining right-to-left scripts are complete with bidi alone.
Conformance
Verified against Unicode's own data, in full — all 91,707 cases of BidiCharacterTest.txt
and all 490,846 of BidiTest.txt. Character data is generated by npm run gen:bidi-tables;
the Unicode version it was built from is exported as UNICODE_VERSION.
