{"id":15085,"library":"bidi-js","title":"bidi-js: Unicode Bidirectional Algorithm","description":"The `bidi-js` package provides a pure JavaScript implementation of the Unicode Bidirectional Algorithm (UAX #9) version 13.0.0. It aims for correctness, small bundle size, and performance, having passed all Unicode conformance tests. Currently at version 1.0.3, it offers a stable API for calculating embedding levels, reordering segments, and identifying mirrored characters in mixed-direction text. It ships as ES5 compatible and has no external dependencies, making it suitable for both browser and Node.js environments. The library differentiates itself by providing a factory function for module initialization, allowing for flexible deployment, such as within web workers, and ensuring a self-contained module without closure dependencies.","status":"active","version":"1.0.3","language":"javascript","source_language":"en","source_url":"https://github.com/lojjic/bidi-js","tags":["javascript"],"install":[{"cmd":"npm install bidi-js","lang":"bash","label":"npm"},{"cmd":"yarn add bidi-js","lang":"bash","label":"yarn"},{"cmd":"pnpm add bidi-js","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"'bidi-js' exclusively exports a single default factory function; there are no named exports.","wrong":"import { bidiFactory } from 'bidi-js'","symbol":"bidiFactory","correct":"import bidiFactory from 'bidi-js'"},{"note":"The default export is a factory function that *must* be invoked to return the actual bidi processing object. Assigning the factory directly will result in method invocation errors.","wrong":"const bidi = bidiFactory","symbol":"bidi object","correct":"const bidi = bidiFactory()"},{"note":"Methods like `getEmbeddingLevels`, `getReorderSegments`, and `getMirroredCharactersMap` are properties of the `bidi` object returned by the factory function, not global or named exports.","wrong":"getEmbeddingLevels(text, explicitDirection)","symbol":"getEmbeddingLevels","correct":"bidi.getEmbeddingLevels(text, explicitDirection)"}],"quickstart":{"code":"import bidiFactory from 'bidi-js';\n\n// In a Node.js environment or a browser with ESM support\nasync function runBidiExample() {\n  // 1. Initialize the bidi object by invoking the factory function\n  const bidi = bidiFactory();\n\n  // Example text with mixed directions (English and Hebrew)\n  const text = \"Hello אֲנִי World, this is a test.\"; // Hebrew for \"I\"\n  const explicitDirection = \"ltr\"; // Optional, if you want to force base direction\n\n  console.log(\"Original Text:\", text);\n\n  // 2. Calculate bidi embedding levels for each character\n  const embeddingLevels = bidi.getEmbeddingLevels(text, explicitDirection);\n  const { levels, paragraphs } = embeddingLevels;\n  console.log(\"Embedding Levels (Uint8Array):\");\n  console.log(levels.join(', '));\n  console.log(\"Paragraphs:\", paragraphs);\n\n  // 3. Calculate character reorderings (segments to reverse)\n  const flips = bidi.getReorderSegments(text, embeddingLevels);\n  console.log(\"Reorder Flips (ranges [start, end] to reverse):\", flips);\n\n  // 4. Apply reordering to get the visual order of characters\n  let reorderedTextArray = Array.from(text);\n  flips.forEach(range => {\n    const [start, end] = range;\n    // Reverse the segment in place\n    let segment = reorderedTextArray.slice(start, end + 1);\n    segment.reverse();\n    reorderedTextArray.splice(start, segment.length, ...segment);\n  });\n  console.log(\"Reordered Text (visual order):\n\", reorderedTextArray.join(''));\n\n  // 5. Identify characters that need to be mirrored (e.g., parentheses)\n  const mirroredCharactersMap = bidi.getMirroredCharactersMap(text, embeddingLevels);\n  console.log(\"Mirrored Characters Map (index -> replacement):\", Array.from(mirroredCharactersMap.entries()));\n}\n\nrunBidiExample();","lang":"javascript","description":"Demonstrates installation, factory initialization, and usage of core methods like `getEmbeddingLevels`, `getReorderSegments`, and `getMirroredCharactersMap` with a mixed-direction string to illustrate the Unicode Bidirectional Algorithm."},"warnings":[{"fix":"Always initialize the library by calling the default imported function: `const bidi = bidiFactory()`.","message":"The `bidi-js` package's only export is a factory function that *must* be invoked to obtain the bidi processing object. Forgetting to call `bidiFactory()` will lead to errors when attempting to access methods.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Iterate through the `flips` array using `forEach` and apply the reversal for each range from `start` to `end` inclusive, in the given order.","message":"When applying character reorderings from `getReorderSegments`, the returned array of `flips` contains ranges that *must* be applied sequentially in the order they are provided to ensure correct visual representation.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"When processing multi-line or segmented text, call `bidi.getReorderSegments(text, embeddingLevels, lineStart, lineEnd)` for each segment.","message":"For line-wrapped text, `getReorderSegments` should be called for each individual line by providing the `start` and `end` parameters corresponding to that line. This handles special cases for trailing whitespace within line segments.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Periodically check the `bidi-js` repository for updates that might align with newer Unicode Bidi Algorithm versions if strict adherence to the latest spec is critical for your application.","message":"While the library ensures conformance to Unicode Bidirectional Algorithm version 13.0.0, future Unicode standard updates (new versions of UAX #9) may introduce changes. The library's current implementation adheres strictly to the specified version.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure you call the factory function to get the bidi object: `const bidiFactory = require('bidi-js'); const bidi = bidiFactory();` or `import bidiFactory from 'bidi-js'; const bidi = bidiFactory();`","cause":"Attempting to use the default import `bidiFactory` directly as an object or calling a method on it without first invoking it as a function.","error":"TypeError: bidi-js is not a function"},{"fix":"Verify that `bidiFactory()` has been correctly invoked and its return value assigned to the `bidi` variable: `const bidi = bidiFactory()`.","cause":"This error occurs when `bidi` is not the object returned by the factory function, meaning `bidiFactory()` was likely not called, or `bidi` was incorrectly assigned.","error":"TypeError: bidi.getEmbeddingLevels is not a function"}],"ecosystem":"npm"}