direction
direction is a zero-dependency JavaScript function and command-line program that classifies text as left-to-right, right-to-left, or neutral. It scans for the first character in hard-coded RTL and LTR Unicode ranges and returns `rtl`, `ltr`, or `neutral`. That is useful for choosing a container direction or alignment from content, but it is not an implementation of the Unicode Bidirectional Algorithm and does not reorder, shape, or safely render mixed-direction text.
Good when the requirement is exactly one first-strong direction label. Use `dir=auto` in browsers when possible, and use a real bidi implementation when mixed text, ordering, security, or editing behavior matters.
Use it if
- You need one small content-based hint for an HTML dir attribute or terminal alignment
- The first strongly directional character is the rule you actually want for mixed punctuation and text
- You want a typed ESM function with no runtime dependencies and a three-value return union
- A simple shell command for classifying short text is useful in scripts or editorial tooling
- You need correct mixed-script display or cursor behavior: this package returns one label and does not implement the Unicode Bidirectional Algorithm
- You consume CommonJS with require: version 2 is explicitly ESM-only, so a migration or dynamic import is required
- Your input starts with one direction but is dominated by another: the source regexes choose whichever recognized RTL or LTR character appears first
- You want actively evolving Unicode data: version 2.0.1 was published in November 2021, the repository's last push was October 2024, and the ranges are embedded directly in source
- The browser can own the behavior: HTML `dir=auto` already lets the user agent determine an element's base direction without shipping JavaScript
Setup reality
`npm install direction` adds no runtime dependencies, and TypeScript declarations ship in the package. Version 2.0.1 is ESM-only because package.json sets `type: module`; use `import {direction} from 'direction'`, not `require('direction')`. The function is deliberately shallow. It converts a truthy value to a string, scans fixed character ranges, and picks RTL or LTR according to the first recognized character; punctuation, digits, emoji, and empty text by themselves are neutral. The TypeScript signature accepts only string even though runtime JavaScript coerces values, so normalize input yourself instead of relying on `String(value || '')`, which treats 0 and false as empty. A single base-direction label does not handle embeddings, isolates, mirrored punctuation, number runs, spoofing, or text shaping. Set `dir` on an appropriate container and let the browser's Unicode bidi implementation render the contents. The included `direction` executable joins command arguments with spaces. With no arguments it listens to stdin and prints once for every incoming data chunk, not once for the complete stream, so a large or slowly produced pipe can yield multiple labels depending on chunk boundaries. There is no configuration, locale database, CommonJS build, callback API, or async work.
Patterns
Detect left-to-right textdetect-left-to-right
import {direction} from 'direction';
console.log(direction('English text'));
// 'ltr'The function returns a literal string union, so no separate boolean conversion is needed.
Detect right-to-left textdetect-right-to-left
import {direction} from 'direction';
console.log(direction('نص عربي'));
// 'rtl'This chooses a base-direction label only; it does not shape Arabic or reorder mixed content.
Handle punctuation and digitshandle-neutral-text
import {direction} from 'direction';
for (const value of ['', '@', '12345', '🙂']) {
console.log(value, direction(value));
}
// each result is 'neutral'Digits, punctuation, emoji, and empty strings do not fall into the package's LTR or RTL ranges.
Classify mixed-direction textunderstand-first-strong
import {direction} from 'direction';
console.log(direction('Invoice فاتورة')); // 'ltr'
console.log(direction('فاتورة Invoice')); // 'rtl'The first recognized directional character wins. This is not a measurement of which script dominates the whole string.
Apply the result to an HTML containerset-html-direction
import {direction} from 'direction';
const message = 'مرحبا بالعالم';
const element = document.createElement('p');
element.dir = direction(message);
element.textContent = message;Use textContent for untrusted text. If you do not need the value in JavaScript, setting dir='auto' is often simpler and lets the browser decide.
Map neutral text to a layout defaultchoose-neutral-fallback
import {direction} from 'direction';
function baseDirection(text) {
const detected = direction(text);
return detected === 'neutral' ? 'ltr' : detected;
}Pick the neutral fallback from product context or surrounding content; the package intentionally does not choose one.
Classify command-line argumentsrun-command-line
npx direction 'مرحبا بالعالم'
# rtl
npx direction '@'
# neutralArguments are joined with spaces before classification. Use -- before text that could be mistaken for -h or -v.
Read short text from stdinclassify-standard-input
printf '%s' 'English text' | npx direction
# ltrThe CLI prints for each stdin data chunk, not once after end-of-file. Keep this path to short inputs that arrive in one chunk.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| bidi-js | npm | You need a JavaScript implementation of Unicode bidirectional reordering rather than a base-direction hint |
| rtl-detect | npm | You want language and locale helpers for detecting whether a known locale is normally RTL |
| unicode-bidirectional | npm | You need detailed Unicode bidi processing and are prepared for a larger, lower-level API |