diff --git a/.changeset/complete-unicode-paragraphs.md b/.changeset/complete-unicode-paragraphs.md new file mode 100644 index 0000000..bd44f6c --- /dev/null +++ b/.changeset/complete-unicode-paragraphs.md @@ -0,0 +1,8 @@ +--- +'@bidilens/core': patch +'@bidilens/react': patch +'@bidilens/cli': patch +--- + +Treat every Unicode 17 `Bidi_Class=Paragraph_Separator` character as a default +batch and streaming boundary, with matching React, Android, and Rust behavior. diff --git a/.changeset/finite-option-guards.md b/.changeset/finite-option-guards.md new file mode 100644 index 0000000..c5aa28d --- /dev/null +++ b/.changeset/finite-option-guards.md @@ -0,0 +1,7 @@ +--- +'@bidilens/core': patch +'@bidilens/markdown': patch +--- + +Reject non-finite detection and stream options instead of allowing NaN to +silently disable direction decisions or stream locking. diff --git a/.changeset/healthy-geese-compare.md b/.changeset/healthy-geese-compare.md new file mode 100644 index 0000000..6ba3617 --- /dev/null +++ b/.changeset/healthy-geese-compare.md @@ -0,0 +1,14 @@ +--- +'@bidilens/markdown': patch +--- + +Expand the optional Markdown-It peer range to cover 13.x, 14.x, and the current +15.x host line without exposing any parser's types through the public API. The +adapter now uses a version-neutral structural runtime boundary instead of +private `markdown-it/lib/*` declarations, and its own source build runs against +Markdown-It 15. A packed strict TypeScript/peer consumer gate runs all 932 +canonical cases plus host-structure fixtures through all three parser lines. +Markdown-It 13 and 14 require identical full reports; Markdown-It 15's upstream +linkifier is allowed its documented HTML difference while BidiLens block, +security, and isolation reports remain identical. Each host also passes the +adapter's finalized batch/stream-equivalence check. diff --git a/.changeset/quiet-marks-detect.md b/.changeset/quiet-marks-detect.md new file mode 100644 index 0000000..108f85f --- /dev/null +++ b/.changeset/quiet-marks-detect.md @@ -0,0 +1,7 @@ +--- +'@bidilens/core': patch +--- + +Keep Unicode combining marks attached at isolation boundaries and recognize +compact technical labels such as `CN X`, `CN IX`, and `HR/BP` without changing +ordinary natural-language evidence. diff --git a/.changeset/secure-paragraph-boundaries.md b/.changeset/secure-paragraph-boundaries.md new file mode 100644 index 0000000..9e68cc8 --- /dev/null +++ b/.changeset/secure-paragraph-boundaries.md @@ -0,0 +1,6 @@ +--- +'@bidilens/core': patch +--- + +Scope bidi-control balancing to Unicode paragraph boundaries so a PDF or PDI +cannot close an embedding or isolate opened in an earlier paragraph. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1044e71..88d3ff5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -35,8 +35,9 @@ updates: - version-update:semver-major # markdown-it 15 changes its TypeScript surface: the constructor no # longer serves as the instance type and renderer callbacks lose the - # contextual types used by our adapter. Adopt that major only alongside - # a deliberate compatibility patch and consumer/type-layout validation. + # contextual types used by older adapters. BidiLens now uses a + # version-neutral structural boundary; keep future major updates paired + # with the source-build and packed consumer compatibility gates. - dependency-name: "markdown-it" update-types: - version-update:semver-major @@ -46,6 +47,13 @@ updates: schedule: interval: weekly open-pull-requests-limit: 3 + groups: + # CodeQL init and analyze must move together. Keeping them in separate + # PRs can create a transient configuration mismatch where one action + # runs a newer CodeQL version against the other action's older config. + codeql-action: + patterns: + - "github/codeql-action/*" - package-ecosystem: gradle directory: /android diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50d4187..a8ccd57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,6 +97,33 @@ jobs: - run: pnpm run packages:types - run: pnpm run release:check + markdown-it-compat: + name: Markdown-It 13, 14, and 15 compatibility + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 + with: + version: 10.27.0 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 22.12.0 + cache: pnpm + cache-dependency-path: pnpm-lock.yaml + - run: pnpm install --frozen-lockfile + - run: pnpm run markdown-it:compat + env: + BIDILENS_MARKDOWN_IT_REPORT_DIR: markdown-it-compat-reports + - if: ${{ failure() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: markdown-it-compat-reports + path: markdown-it-compat-reports + if-no-files-found: error + retention-days: 7 + android: name: Android libraries and sample runs-on: ubuntu-latest diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6f992f1..0b6d649 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -31,13 +31,13 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: languages: ${{ matrix.language }} build-mode: none queries: security-extended - name: Analyze - uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: category: /language:${{ matrix.language }} @@ -58,7 +58,7 @@ jobs: android/**/*.gradle.kts android/gradle/wrapper/gradle-wrapper.properties - name: Initialize CodeQL - uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: languages: java-kotlin build-mode: manual @@ -73,7 +73,7 @@ jobs: :sample:compileDebugKotlin --no-daemon --stacktrace --console=plain - name: Analyze - uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: category: /language:java-kotlin @@ -86,7 +86,7 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: languages: swift build-mode: manual @@ -101,6 +101,6 @@ jobs: CODE_SIGNING_ALLOWED=NO \ build - name: Analyze - uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: category: /language:swift diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5cfa273..47b0cf6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,6 +30,7 @@ jobs: - run: pnpm exec playwright install --with-deps chromium firefox webkit - run: pnpm run test:visual - run: pnpm run packages:types + - run: pnpm run markdown-it:compat - run: pnpm run deps:audit - run: pnpm run release:check - run: pnpm run sbom diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 83332ca..24770be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -84,6 +84,7 @@ Changesets entry for a public API or behavior change. Before a release run: pnpm run check pnpm run test:visual pnpm run packages:types +pnpm run markdown-it:compat pnpm run deps:audit pnpm run release:check pnpm run sbom diff --git a/IMPACT.md b/IMPACT.md index 53b0f06..bf3705f 100644 --- a/IMPACT.md +++ b/IMPACT.md @@ -7,19 +7,21 @@ - 932 schema-validated direction fixtures with numbered logical words; - 0 fixtures currently certified by a native-language reviewer; - property-based stream/source/range checks; -- 396 unit/property/action tests with 94.80% overall and 95.81% core line coverage, - including multilingual strict-security false-positive regressions; -- 24 browser/visual checks spanning Chromium, Firefox, and WebKit, including +- 437 unit/property/action tests with 92.22% statements, 86.26% branches, + 94.85% functions, and 95.02% lines overall (96.28% core lines), including + paragraph-boundary security, isolate balancing, and non-finite-option + regressions; +- 30 Playwright browser/visual tests spanning Chromium, Firefox, and WebKit, including structured Markdown, real Chromium clipboard verification, and no-build standalone Web Component loading, plus the full offline bilingual playground controls, corpus, copy invariant, theme, and export flow; -- a self-contained 196,766-byte Node 24 GitHub Action bundle with source tests +- a self-contained 199,943-byte Node 24 GitHub Action bundle with source tests and built-artifact safe/strict-failure probes; - reproducible Unicode 17.0.0 source and generated tables; - clean tarball installation, strict consumer type-check, runtime imports, and execution of the exact examples extracted from all 12 tarballs; - no known dependency vulnerabilities at the recorded audit; -- a validated CycloneDX 1.7 SBOM with 585 components and 599 dependency +- a validated CycloneDX 1.7 SBOM with 577 components and 591 dependency relationships; - all 12 tarballs installed and exercised in a strict isolated consumer. @@ -28,9 +30,12 @@ the [build report](docs/V1_BUILD_REPORT.md). ## Not yet measured -There are no claimed users, downloads, stars, external contributors, merged -upstream patches, production deployments, accessibility lab results, security -audit, grants, or sponsorships. Those outcomes require real external evidence. +There are no claimed users, downloads, stars, external contributors, production +deployments, accessibility lab results, independent security audit, grants, or +sponsorships. One focused native implementation based on the BidiLens policy +merged upstream in Streamdown; that is integration evidence, not proof of +BidiLens dependency adoption or continued production use. All other outcomes +require real external evidence. ## Intended impact diff --git a/README.md b/README.md index f5c076e..aa07d5d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,10 @@ the immutable logical source, and isolates the technical identifier. |---|---| | ![The flagship sentence rendered with the incorrect automatic LTR base](tests/visual/__screenshots__/chromium/flagship-auto.png) | ![The same logical sentence rendered with the correct RTL base and isolated React token](tests/visual/__screenshots__/chromium/flagship-toolkit.png) | +The medical Markdown, abbreviation, combining-mark, quote, list, and table +cases transcribed from mixed AI output are documented in the +[screenshot regression cases](docs/SCREENSHOT_CASES.md). + ## Why this is more than an RTL stylesheet | Common approach | Limitation | BidiLens behavior | @@ -146,7 +150,7 @@ reordering and shaping; BidiLens supplies the application structure they need. | `@bidilens/core` | Analysis, evidence, isolation, streaming, and security | | `@bidilens/dom` | DOM annotation, restoration, CSS policy, and observation | | `@bidilens/html` | XSS-safe semantic HTML serialization | -| `@bidilens/markdown` | unified/remark/rehype and Markdown-It plugins plus rich Markdown-It streaming | +| `@bidilens/markdown` | unified/remark/rehype and Markdown-It 13/14/15 plugins plus rich Markdown-It streaming | | `@bidilens/playwright` | Rendering, isolation, selection, clipboard, and geometry assertions | | `@bidilens/react` | SSR-safe components and streaming hooks | | `@bidilens/spec` | Versioned cross-language JSON Schemas and schema registry | @@ -289,7 +293,8 @@ cargo clippy --manifest-path rust/Cargo.toml --all-targets --all-features -- -D ``` `verify:production` runs the complete quality, three-browser visual, package -type, dependency-audit, SBOM, and clean-release sequence. `release:check` +type, packed Markdown-It 13/14/15 compatibility, dependency-audit, SBOM, and +clean-release sequence. `release:check` builds and packs every public package, inspects tarball contents, installs all tarballs into a temporary consumer, compiles with `skipLibCheck: false`, and executes adapter/runtime assertions—including the pure-LTR non-interference diff --git a/action/dist/index.cjs b/action/dist/index.cjs index f4c43bc..310585c 100644 --- a/action/dist/index.cjs +++ b/action/dist/index.cjs @@ -6047,6 +6047,18 @@ function classifyCharacter(character) { return isInRanges(codePoint, NATURAL_LETTER_RANGES) ? classifyBidiStrongCharacter(character) : "neutral"; } +// packages/core/src/options.ts +function boundedNumberOption(name, value, defaultValue, minimum, maximum) { + const resolved = value ?? defaultValue; + if (!Number.isFinite(resolved)) { + throw new RangeError(`${name} must be a finite number.`); + } + return Math.min(maximum, Math.max(minimum, resolved)); +} + +// packages/core/src/paragraph.ts +var DEFAULT_PARAGRAPH_SEPARATOR_SOURCE = "\\r\\n|\\n|\\r|\\u0085|[\\u001C-\\u001E]|\\u2029"; + // packages/core/src/detect.ts var DEFAULT_OPTIONS = { strategy: "content-majority", @@ -6127,8 +6139,20 @@ function normalizeOptions(options = {}) { strategy, fallback: options.fallback ?? options.inheritedDirection ?? DEFAULT_OPTIONS.fallback, inheritedDirection: options.inheritedDirection ?? DEFAULT_OPTIONS.inheritedDirection, - minimumStrongCharacters: Math.max(1, options.minimumStrongCharacters ?? DEFAULT_OPTIONS.minimumStrongCharacters), - majorityThreshold: Math.min(1, Math.max(0.5, options.majorityThreshold ?? DEFAULT_OPTIONS.majorityThreshold)), + minimumStrongCharacters: boundedNumberOption( + "minimumStrongCharacters", + options.minimumStrongCharacters, + DEFAULT_OPTIONS.minimumStrongCharacters, + 1, + Number.POSITIVE_INFINITY + ), + majorityThreshold: boundedNumberOption( + "majorityThreshold", + options.majorityThreshold, + DEFAULT_OPTIONS.majorityThreshold, + 0.5, + 1 + ), // Compatibility/strict first-strong modes must see the real first strong // character (including a leading technical identifier), like dir="auto". excludeTechnicalTokens: options.excludeTechnicalTokens ?? majorityStrategy, @@ -6403,6 +6427,9 @@ function findTechnicalTokenRanges(text, technicalIdentifiers = []) { addMatches(text, ranges, /\bv?\d+(?:\.\d+){1,}\b/gu, "version"); addMatches(text, ranges, /\b[0-9a-f]{7,40}\b/giu, "hash"); addMatches(text, ranges, /(?))/gu, "identifier"); const words = /\b[A-Za-z][A-Za-z0-9_.-]*\b/gu; const customIdentifiers = customTechnicalIdentifiers(technicalIdentifiers); const uppercaseProse = usesUppercaseProse(text); @@ -6478,7 +6505,7 @@ function firstBidiStrongCharacter(text) { } function splitParagraphs(text) { const paragraphs = []; - const separator = /\r\n|\n|\r|\u2029/gu; + const separator = new RegExp(DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, "gu"); let start = 0; let match; while ((match = separator.exec(text)) !== null) { @@ -6550,6 +6577,10 @@ function analyzeText(text, options = {}) { } // packages/core/src/security.ts +var UAX9_PARAGRAPH_SEPARATOR = new RegExp( + `\\r\\n|\\n|\\r|\\u0085|[${String.fromCodePoint(28)}-${String.fromCodePoint(30)}]|\\u2029`, + "gu" +); var CONTROL_METADATA = /* @__PURE__ */ new Map([ [1564, { name: "ARABIC LETTER MARK", risk: "low", category: "mark" }], [8206, { name: "LEFT-TO-RIGHT MARK", risk: "low", category: "mark" }], @@ -6638,7 +6669,7 @@ function lastFrameIndex(stack, kind) { } return -1; } -function balanceFindings(controls) { +function balanceParagraph(controls, boundary) { const findings = []; const stack = []; for (const control of controls) { @@ -6699,7 +6730,7 @@ function balanceFindings(controls) { findings.push({ code: frame.kind === "isolate" ? "BIDI_UNCLOSED_ISOLATE" : "BIDI_UNCLOSED_EMBEDDING", severity: "high", - message: `${frame.control.name} is not terminated before the end of the text.`, + message: `${frame.control.name} is not terminated before ${boundary === "paragraph" ? "the paragraph boundary" : "the end of the text"}.`, sourceRange: rangeFor(frame.control), remediation: frame.kind === "isolate" ? "Add the matching PDI or remove the isolate opener." : "Add the matching PDF or remove the embedding/override opener.", control: frame.control @@ -6707,6 +6738,20 @@ function balanceFindings(controls) { } return findings; } +function balanceFindings(text, controls) { + const findings = []; + let controlIndex = 0; + for (const match of text.matchAll(UAX9_PARAGRAPH_SEPARATOR)) { + const paragraphControls = []; + while (controlIndex < controls.length && controls[controlIndex].index < match.index) { + paragraphControls.push(controls[controlIndex]); + controlIndex += 1; + } + findings.push(...balanceParagraph(paragraphControls, "paragraph")); + } + findings.push(...balanceParagraph(controls.slice(controlIndex), "text")); + return findings; +} function isAsciiIdentifierCharacter(value) { return value !== void 0 && /^[A-Za-z0-9_$]$/u.test(value); } @@ -6767,7 +6812,7 @@ function scanBidiSecurity(text, options = {}) { const controls = findBidiControls(text); const findings = [ ...controls.map(controlFinding), - ...balanceFindings(controls), + ...balanceFindings(text, controls), ...invisibleCharacterFindings(text) ].sort((a, b) => a.sourceRange.utf16.start - b.sourceRange.utf16.start || a.code.localeCompare(b.code)); const hasHigh = findings.some((finding) => finding.severity === "high"); @@ -6904,12 +6949,12 @@ function mergeAdjacent(runs) { function trimNeutralBoundaries(text, start, end) { while (start < end) { const character = text.slice(start).match(/^./su)?.[0]; - if (!character || classifyCharacter(character) !== "neutral") break; + if (!character || classifyCharacter(character) !== "neutral" || new RegExp("^\\p{M}$", "u").test(character)) break; start += character.length; } while (end > start) { const character = text.slice(0, end).match(/.$/su)?.[0]; - if (!character || classifyCharacter(character) !== "neutral") break; + if (!character || classifyCharacter(character) !== "neutral" || new RegExp("^\\p{M}$", "u").test(character)) break; end -= character.length; } return { start, end }; @@ -7437,7 +7482,7 @@ function highestFindingRisk(findings) { function sourcePosition(text, utf16Offset) { let lineNumber = 1; let lineStart = 0; - const newline = /\r\n|\n|\r/gu; + const newline = new RegExp(`${DEFAULT_PARAGRAPH_SEPARATOR_SOURCE}|\\u2028`, "gu"); let match; while ((match = newline.exec(text)) !== null && match.index < utf16Offset) { lineNumber += 1; diff --git a/action/dist/index.cjs.map b/action/dist/index.cjs.map index 9abbd67..62443fc 100644 --- a/action/dist/index.cjs.map +++ b/action/dist/index.cjs.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../src/main.ts", "../src/index.ts", "../../packages/cli/src/index.ts", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/argument.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/command.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/help.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/option.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/suggestSimilar.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/index.js", "../../packages/core/src/generated/bidi-ranges.ts", "../../packages/core/src/classify.ts", "../../packages/core/src/detect.ts", "../../packages/core/src/security.ts", "../../packages/core/src/intervention.ts", "../../packages/core/src/segments.ts", "../../packages/html/src/index.ts", "../../packages/cli/package.json"], - "sourcesContent": ["import process from 'node:process';\nimport { runAction, workflowError } from './index.js';\n\nasync function main(): Promise {\n try {\n const result = await runAction();\n process.exitCode = result.exitCode;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${workflowError(message)}\\n`);\n process.exitCode = 1;\n }\n}\n\nvoid main();\n", "import { appendFile, mkdir, writeFile } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport process from 'node:process';\nimport { runCli } from '../../packages/cli/src/index.js';\n\nexport type ActionCommand = 'audit' | 'test';\nexport type ActionFormat = 'human' | 'json' | 'sarif';\nexport type ActionMode = 'off' | 'audit' | 'warn' | 'strict';\nexport type ActionRisk = 'low' | 'medium' | 'high';\n\nexport interface ActionInputs {\n command: ActionCommand;\n paths: string[];\n corpus: string;\n mode: ActionMode;\n failOn: ActionRisk;\n format: ActionFormat;\n sarifFile: string;\n}\n\nexport interface ActionContext {\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n log?: (value: string) => void;\n error?: (value: string) => void;\n}\n\nexport interface ActionResult {\n exitCode: number;\n report: string;\n stdout: string;\n stderr: string;\n}\n\nfunction input(env: NodeJS.ProcessEnv, name: string): string {\n return env[`INPUT_${name.toUpperCase()}`]?.trim() ?? '';\n}\n\nfunction choice(\n name: string,\n value: string,\n fallback: Value,\n allowed: readonly Value[]\n): Value {\n const candidate = value || fallback;\n if (!allowed.includes(candidate as Value)) {\n throw new Error(`${name} must be one of ${allowed.join(', ')}; received ${JSON.stringify(candidate)}.`);\n }\n return candidate as Value;\n}\n\nexport function readActionInputs(env: NodeJS.ProcessEnv = process.env): ActionInputs {\n return {\n command: choice('command', input(env, 'COMMAND'), 'audit', ['audit', 'test']),\n paths: (input(env, 'PATHS') || '.').split(/\\r?\\n/u).map((path) => path.trim()).filter(Boolean),\n corpus: input(env, 'CORPUS'),\n mode: choice('mode', input(env, 'MODE'), 'audit', ['off', 'audit', 'warn', 'strict']),\n failOn: choice('fail-on', input(env, 'FAIL-ON'), 'high', ['low', 'medium', 'high']),\n format: choice('format', input(env, 'FORMAT'), 'human', ['human', 'json', 'sarif']),\n sarifFile: input(env, 'SARIF-FILE') || 'bidilens.sarif'\n };\n}\n\nexport function buildCliArguments(inputs: ActionInputs, env: NodeJS.ProcessEnv = process.env): string[] {\n if (inputs.command === 'test') {\n if (inputs.format === 'sarif') throw new Error('SARIF output is available only for the audit command.');\n const actionPath = env.GITHUB_ACTION_PATH\n ? resolve(env.GITHUB_ACTION_PATH)\n : resolve(env.GITHUB_WORKSPACE ?? process.cwd(), 'action');\n const corpus = inputs.corpus || resolve(actionPath, '..', 'corpus', 'cases.json');\n return ['node', 'bidilens', 'test', '--corpus', corpus, ...(inputs.format === 'json' ? ['--json'] : [])];\n }\n\n const format = inputs.format === 'json' ? ['--json'] : inputs.format === 'sarif' ? ['--sarif'] : [];\n return [\n 'node', 'bidilens', 'audit', ...inputs.paths,\n '--mode', inputs.mode,\n '--fail-on', inputs.failOn,\n ...format\n ];\n}\n\nfunction workspaceFile(cwd: string, requested: string): { absolute: string; relative: string } {\n const absolute = resolve(cwd, requested);\n const local = relative(cwd, absolute);\n if (!local || local.startsWith('..') || isAbsolute(local)) {\n throw new Error('sarif-file must resolve to a file inside GITHUB_WORKSPACE.');\n }\n return { absolute, relative: local.replaceAll('\\\\', '/') };\n}\n\nasync function setOutput(path: string | undefined, name: string, value: string): Promise {\n if (!path) return;\n const delimiter = `bidilens_${randomUUID()}`;\n await appendFile(path, `${name}<<${delimiter}\\n${value}\\n${delimiter}\\n`, 'utf8');\n}\n\n/** Executes the bundled CLI without a shell and propagates its real exit code. */\nexport async function runAction(context: ActionContext = {}): Promise {\n const env = context.env ?? process.env;\n const cwd = resolve(context.cwd ?? env.GITHUB_WORKSPACE ?? process.cwd());\n const log = context.log ?? console.log;\n const error = context.error ?? console.error;\n const inputs = readActionInputs(env);\n const stdout: string[] = [];\n const stderr: string[] = [];\n const exitCode = await runCli(buildCliArguments(inputs, env), {\n cwd,\n stdout: (value) => stdout.push(value),\n stderr: (value) => stderr.push(value)\n });\n const stdoutText = stdout.join('');\n const stderrText = stderr.join('');\n let report = '';\n\n if (inputs.format === 'sarif') {\n const target = workspaceFile(cwd, inputs.sarifFile);\n await mkdir(dirname(target.absolute), { recursive: true });\n await writeFile(target.absolute, stdoutText, 'utf8');\n report = target.relative;\n log(`BidiLens SARIF report written to ${report}.`);\n } else if (stdoutText) {\n log(stdoutText.trimEnd());\n }\n if (stderrText) error(stderrText.trimEnd());\n\n await setOutput(env.GITHUB_OUTPUT, 'exit-code', String(exitCode));\n await setOutput(env.GITHUB_OUTPUT, 'report', report);\n if (exitCode !== 0) error(`BidiLens ${inputs.command} failed with exit code ${exitCode}.`);\n return { exitCode, report, stdout: stdoutText, stderr: stderrText };\n}\n\nexport function workflowError(message: string): string {\n const escaped = message\n .replaceAll('%', '%25')\n .replaceAll('\\r', '%0D')\n .replaceAll('\\n', '%0A');\n return `::error title=BidiLens::${escaped}`;\n}\n", "#!/usr/bin/env node\nimport { lstat, readFile, readdir, writeFile } from 'node:fs/promises';\nimport { basename, extname, isAbsolute, relative, resolve } from 'node:path';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport { Command, CommanderError } from 'commander';\nimport { renderBidiHtml } from '@bidilens/html';\nimport packageManifest from '../package.json' with { type: 'json' };\nimport {\n analyzeText,\n findBidiControls,\n sanitizeBidiControls,\n scanBidiSecurity,\n visibleBidiControls,\n type BidiControlRisk,\n type BidiInterventionMode,\n type BidiSecurityFinding,\n type BidiSecurityMode\n} from '@bidilens/core';\n\nconst SUPPORTED_EXTENSIONS = new Set([\n '.md', '.mdx', '.txt', '.html', '.htm', '.json', '.yaml', '.yml',\n '.js', '.jsx', '.ts', '.tsx', '.css', '.scss', '.py', '.go', '.rs',\n '.java', '.kt', '.swift', '.c', '.cc', '.cpp', '.h', '.hpp', '.toml',\n '.vue', '.svelte', '.astro', '.dart', '.xml', '.svg', '.sh', '.bash',\n '.zsh', '.fish', '.cs', '.fs', '.fsx', '.vb', '.rb', '.php', '.sql',\n '.ini', '.conf', '.properties', '.gradle', '.groovy', '.lua', '.pl', '.r',\n '.ex', '.exs', '.erl', '.hrl'\n]);\n\nconst SUPPORTED_BASENAMES = new Set([\n 'dockerfile', 'makefile', 'gemfile', 'podfile', 'rakefile', 'cmakelists.txt',\n 'build', 'workspace', '.env'\n]);\n\nconst IGNORED_DIRECTORIES = new Set([\n 'node_modules', '.git', 'dist', 'build', 'coverage', 'test-results',\n 'playwright-report', '.vite', '.next', '.nuxt', '.svelte-kit', '.output'\n]);\n\nconst RISK_ORDER: Record = { low: 1, medium: 2, high: 3 };\nconst CLI_VERSION = packageManifest.version;\n\ninterface CorpusCase {\n id: string;\n text: string;\n expected: 'ltr' | 'rtl' | 'neutral';\n}\n\nexport interface CliRuntime {\n cwd?: string;\n stdout?: (value: string) => void;\n stderr?: (value: string) => void;\n}\n\ninterface RuntimeState {\n cwd: string;\n stdout: (value: string) => void;\n stderr: (value: string) => void;\n exitCode: number;\n}\n\nfunction createRuntime(runtime: CliRuntime): RuntimeState {\n return {\n cwd: resolve(runtime.cwd ?? process.cwd()),\n stdout: runtime.stdout ?? ((value) => process.stdout.write(value)),\n stderr: runtime.stderr ?? ((value) => process.stderr.write(value)),\n exitCode: 0\n };\n}\n\nfunction line(writer: (value: string) => void, value = ''): void {\n writer(`${value}\\n`);\n}\n\nasync function collectFiles(inputs: string[], cwd: string): Promise {\n const files: string[] = [];\n async function visitPath(input: string, explicitlyNamed: boolean): Promise {\n const absolute = resolve(cwd, input);\n const info = await lstat(absolute);\n if (info.isSymbolicLink()) return;\n if (info.isDirectory()) {\n const entries = await readdir(absolute, { withFileTypes: true });\n entries.sort((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n if (IGNORED_DIRECTORIES.has(entry.name.toLowerCase())) continue;\n if (entry.isSymbolicLink()) continue;\n await visitPath(resolve(absolute, entry.name), false);\n }\n return;\n }\n const name = basename(absolute).toLowerCase();\n const supportedName = SUPPORTED_BASENAMES.has(name) || name.startsWith('.env.');\n if (info.isFile() && (explicitlyNamed || supportedName || SUPPORTED_EXTENSIONS.has(extname(absolute).toLowerCase()))) {\n files.push(absolute);\n }\n }\n for (const input of inputs) await visitPath(input, true);\n return files.sort((a, b) => a.localeCompare(b));\n}\n\nfunction parseCorpus(source: string, location: string): CorpusCase[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(source);\n } catch (error) {\n throw new Error(`${location} is not valid JSON. ${String(error)}`, { cause: error });\n }\n if (!Array.isArray(parsed)) throw new Error(`${location} must contain a JSON array.`);\n const ids = new Set();\n return parsed.map((item: unknown, index) => {\n if (typeof item !== 'object' || item === null) {\n throw new Error(`${location}: case ${index + 1} must be an object.`);\n }\n const candidate = item as Record;\n if (typeof candidate.id !== 'string' || candidate.id.length === 0) {\n throw new Error(`${location}: case ${index + 1} must have a non-empty string id.`);\n }\n if (ids.has(candidate.id)) throw new Error(`${location}: duplicate case id \"${candidate.id}\".`);\n ids.add(candidate.id);\n if (typeof candidate.text !== 'string') {\n throw new Error(`${location}: case \"${candidate.id}\" must have string text.`);\n }\n if (candidate.expected !== 'ltr' && candidate.expected !== 'rtl' && candidate.expected !== 'neutral') {\n throw new Error(`${location}: case \"${candidate.id}\" has invalid expected direction.`);\n }\n return { id: candidate.id, text: candidate.text, expected: candidate.expected };\n });\n}\n\nasync function readCorpus(cwd: string, explicitPath?: string): Promise {\n if (explicitPath !== undefined) {\n const location = resolve(cwd, explicitPath);\n return parseCorpus(await readFile(location, 'utf8'), location);\n }\n const candidates: Array = [\n resolve(cwd, 'corpus/cases.json'),\n new URL('../corpus/cases.json', import.meta.url),\n new URL('../../../corpus/cases.json', import.meta.url)\n ];\n let lastError: unknown;\n for (const candidate of candidates) {\n let source: string;\n try {\n source = await readFile(candidate, 'utf8');\n } catch (error) {\n lastError = error;\n continue;\n }\n // An existing, malformed higher-priority corpus is a configuration error,\n // not a reason to silently fall back to a different data set.\n return parseCorpus(source, String(candidate));\n }\n throw new Error(`Unable to locate corpus/cases.json. Pass --corpus . ${String(lastError)}`);\n}\n\nfunction parseRisk(value: string): BidiControlRisk {\n if (value === 'low' || value === 'medium' || value === 'high') return value;\n throw new Error(`Invalid risk level: ${value}`);\n}\n\nfunction parseSecurityMode(value: string): BidiSecurityMode {\n if (value === 'off' || value === 'audit' || value === 'warn' || value === 'strict') return value;\n throw new Error(`Invalid security mode: ${value}`);\n}\n\nfunction parseIntervention(value: string): BidiInterventionMode {\n if (value === 'auto' || value === 'always') return value;\n throw new Error(`Invalid intervention mode: ${value}`);\n}\n\nfunction riskForFinding(finding: BidiSecurityFinding): BidiControlRisk {\n if (finding.severity === 'high') return 'high';\n if (finding.severity === 'warning') return 'medium';\n return 'low';\n}\n\nfunction highestFindingRisk(findings: readonly BidiSecurityFinding[]): BidiControlRisk | null {\n if (findings.some((finding) => finding.severity === 'high')) return 'high';\n if (findings.some((finding) => finding.severity === 'warning')) return 'medium';\n if (findings.length) return 'low';\n return null;\n}\n\nfunction sourcePosition(text: string, utf16Offset: number): { line: number; column: number } {\n let lineNumber = 1;\n let lineStart = 0;\n const newline = /\\r\\n|\\n|\\r/gu;\n let match: RegExpExecArray | null;\n while ((match = newline.exec(text)) !== null && match.index < utf16Offset) {\n lineNumber += 1;\n lineStart = match.index + match[0].length;\n }\n return { line: lineNumber, column: utf16Offset - lineStart + 1 };\n}\n\nfunction artifactUri(file: string, cwd: string): string {\n const local = relative(cwd, file);\n if (local && !local.startsWith('..') && !isAbsolute(local)) return local.replaceAll('\\\\', '/');\n return pathToFileURL(file).href;\n}\n\ninterface SecurityFileReport {\n file: string;\n text: string;\n findings: BidiSecurityFinding[];\n highestRisk: BidiControlRisk | null;\n}\n\nasync function readTextInput(\n options: { text?: string; file?: string },\n cwd: string\n): Promise {\n if (options.text === undefined && options.file === undefined) {\n throw new Error('Provide --text or --file.');\n }\n if (options.text !== undefined && options.file !== undefined) {\n throw new Error('Choose either --text or --file, not both.');\n }\n return options.file !== undefined\n ? readFile(resolve(cwd, options.file), 'utf8')\n : options.text!;\n}\n\nfunction sarifForReports(reports: readonly SecurityFileReport[], cwd: string): object {\n return {\n version: '2.1.0',\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n runs: [{\n columnKind: 'utf16CodeUnits',\n tool: { driver: { name: 'BidiLens', semanticVersion: CLI_VERSION } },\n results: reports.flatMap((report) => report.findings.map((finding) => {\n const start = sourcePosition(report.text, finding.sourceRange.utf16.start);\n const end = sourcePosition(report.text, finding.sourceRange.utf16.end);\n return {\n ruleId: finding.code,\n level: finding.severity === 'high' ? 'error' : finding.severity === 'warning' ? 'warning' : 'note',\n message: { text: `${finding.message} ${finding.remediation}` },\n locations: [{\n physicalLocation: {\n artifactLocation: { uri: artifactUri(report.file, cwd) },\n region: {\n startLine: start.line,\n startColumn: start.column,\n endLine: end.line,\n endColumn: end.column\n }\n }\n }]\n };\n }))\n }]\n };\n}\n\nfunction createCliProgram(state: RuntimeState): Command {\n const program = new Command();\n program\n .name('bidilens')\n .description('Inspect and secure mixed bidirectional text')\n .version(CLI_VERSION)\n .exitOverride()\n .configureOutput({ writeOut: state.stdout, writeErr: state.stderr });\n\n program.command('inspect')\n .description('Analyze a string or file')\n .option('-t, --text ', 'text to inspect')\n .option('-f, --file ', 'file to inspect')\n .option('--json', 'emit JSON')\n .action(async (options: { text?: string; file?: string; json?: boolean }) => {\n const text = await readTextInput(options, state.cwd);\n const analysis = analyzeText(text, { strategy: 'content-majority', fallback: 'neutral' });\n const controls = findBidiControls(text);\n const report = { analysis, controls, visible: controls.length ? visibleBidiControls(text) : text };\n if (options.json) line(state.stdout, JSON.stringify(report, null, 2));\n else {\n line(state.stdout, `Direction: ${analysis.direction}`);\n line(state.stdout, `Confidence: ${analysis.confidence}`);\n line(state.stdout, `Strong characters: RTL ${analysis.counts.rtl}, LTR ${analysis.counts.ltr}`);\n line(state.stdout, `Paragraphs: ${analysis.paragraphs.length}`);\n line(state.stdout, `Bidi controls: ${controls.length}`);\n if (controls.length) line(state.stdout, report.visible);\n }\n });\n\n program.command('render')\n .description('Render plain text as escaped, semantic direction-aware HTML')\n .option('-t, --text ', 'text to render')\n .option('-f, --file ', 'file to render')\n .option('--intervention ', 'auto or always', parseIntervention, 'auto')\n .option('--json', 'emit analysis and HTML as JSON')\n .action(async (options: {\n text?: string;\n file?: string;\n intervention: BidiInterventionMode;\n json?: boolean;\n }) => {\n const text = await readTextInput(options, state.cwd);\n const result = renderBidiHtml(text, { intervention: options.intervention });\n line(state.stdout, options.json\n ? JSON.stringify({ analysis: result.analysis, html: result.html }, null, 2)\n : result.html);\n });\n\n program.command('audit')\n .aliases(['security-scan', 'lint'])\n .description('Audit files for hidden and unbalanced bidi controls')\n .argument('', 'files or directories')\n .option('--json', 'emit JSON')\n .option('--sarif', 'emit SARIF 2.1.0')\n .option('--mode ', 'off, audit, warn, or strict', parseSecurityMode, 'audit')\n .option('--fail-on ', 'minimum risk that exits non-zero', parseRisk, 'high')\n .action(async (paths: string[], options: {\n json?: boolean;\n sarif?: boolean;\n mode: BidiSecurityMode;\n failOn: BidiControlRisk;\n }) => {\n if (options.json && options.sarif) throw new Error('Choose either --json or --sarif, not both.');\n const files = await collectFiles(paths, state.cwd);\n const reports: SecurityFileReport[] = [];\n let shouldFail = false;\n\n for (const file of files) {\n const text = await readFile(file, 'utf8');\n const security = scanBidiSecurity(text, { mode: options.mode });\n if (!security.findings.length) continue;\n const highestRisk = highestFindingRisk(security.findings);\n reports.push({ file, text, findings: security.findings, highestRisk });\n if (security.shouldBlock || (highestRisk && RISK_ORDER[highestRisk] >= RISK_ORDER[options.failOn])) shouldFail = true;\n }\n\n if (options.sarif) line(state.stdout, JSON.stringify(sarifForReports(reports, state.cwd), null, 2));\n else if (options.json) {\n line(state.stdout, JSON.stringify({\n scanned: files.length,\n reports: reports.map((report) => ({\n file: report.file,\n findings: report.findings,\n highestRisk: report.highestRisk\n }))\n }, null, 2));\n } else if (!reports.length) line(state.stdout, `No bidi security findings in ${files.length} files.`);\n else {\n for (const report of reports) {\n line(state.stdout, `\\n${report.file} (${report.highestRisk ?? 'unknown'})`);\n for (const finding of report.findings) {\n const position = sourcePosition(report.text, finding.sourceRange.utf16.start);\n line(state.stdout, ` ${finding.code} at ${position.line}:${position.column} [${riskForFinding(finding)}] ${finding.message}`);\n }\n }\n }\n if (shouldFail) state.exitCode = Math.max(state.exitCode, 2);\n });\n\n program.command('test')\n .description('Run the direction conformance corpus')\n .option('--json', 'emit failures as JSON')\n .option('--corpus ', 'corpus JSON path; defaults to the bundled corpus or repository corpus')\n .action(async (options: { json?: boolean; corpus?: string }) => {\n const corpus = await readCorpus(state.cwd, options.corpus);\n const failures = corpus.flatMap((item) => {\n const actual = analyzeText(item.text, { strategy: 'content-majority', fallback: 'neutral' }).direction;\n return actual === item.expected ? [] : [{ id: item.id, expected: item.expected, actual }];\n });\n if (options.json) line(state.stdout, JSON.stringify({ total: corpus.length, failures }, null, 2));\n else line(state.stdout, `Corpus: ${corpus.length - failures.length}/${corpus.length} passed`);\n if (failures.length) state.exitCode = Math.max(state.exitCode, 1);\n });\n\n program.command('sanitize')\n .description('Remove bidi controls from one file')\n .argument('', 'input file')\n .option('-o, --output ', 'output path; defaults to stdout')\n .option('--keep-low', 'preserve low-risk ALM/LRM/RLM marks')\n .action(async (file: string, options: { output?: string; keepLow?: boolean }) => {\n const text = await readFile(resolve(state.cwd, file), 'utf8');\n const remove: BidiControlRisk[] = options.keepLow ? ['high', 'medium'] : ['high', 'medium', 'low'];\n const result = sanitizeBidiControls(text, { remove });\n if (options.output) {\n const output = resolve(state.cwd, options.output);\n await writeFile(output, result.text, 'utf8');\n line(state.stderr, `Removed ${result.removed.length} controls and wrote ${output}.`);\n } else {\n state.stdout(result.text);\n }\n });\n\n return program;\n}\n\nexport async function runCli(argv: readonly string[] = process.argv, runtime: CliRuntime = {}): Promise {\n const state = createRuntime(runtime);\n const program = createCliProgram(state);\n try {\n await program.parseAsync([...argv], { from: 'node' });\n } catch (error) {\n if (error instanceof CommanderError) return Math.max(state.exitCode, error.exitCode);\n const message = error instanceof Error ? error.message : String(error);\n line(state.stderr, `bidilens: ${message}`);\n return Math.max(state.exitCode, 1);\n }\n return state.exitCode;\n}\n", "/**\n * CommanderError class\n */\nexport class CommanderError extends Error {\n /**\n * Constructs the CommanderError class\n * @param {number} exitCode suggested exit code which could be used with process.exit\n * @param {string} code an id string representing the error\n * @param {string} message human-readable description of the error\n */\n constructor(exitCode, code, message) {\n super(message);\n // properly capture stack trace in Node.js\n Error.captureStackTrace(this, this.constructor);\n this.name = this.constructor.name;\n this.code = code;\n this.exitCode = exitCode;\n this.nestedError = undefined;\n }\n}\n\n/**\n * InvalidArgumentError class\n */\nexport class InvalidArgumentError extends CommanderError {\n /**\n * Constructs the InvalidArgumentError class\n * @param {string} [message] explanation of why argument is invalid\n */\n constructor(message) {\n super(1, 'commander.invalidArgument', message);\n // properly capture stack trace in Node.js\n Error.captureStackTrace(this, this.constructor);\n this.name = this.constructor.name;\n }\n}\n", "import { InvalidArgumentError } from './error.js';\n\nexport class Argument {\n /**\n * Initialize a new command argument with the given name and description.\n * The default is that the argument is required, and you can explicitly\n * indicate this with <> around the name. Put [] around the name for an optional argument.\n *\n * @param {string} name\n * @param {string} [description]\n */\n\n constructor(name, description) {\n this.description = description || '';\n this.variadic = false;\n this.parseArg = undefined;\n this.defaultValue = undefined;\n this.defaultValueDescription = undefined;\n this.argChoices = undefined;\n\n switch (name[0]) {\n case '<': // e.g. \n this.required = true;\n this._name = name.slice(1, -1);\n break;\n case '[': // e.g. [optional]\n this.required = false;\n this._name = name.slice(1, -1);\n break;\n default:\n this.required = true;\n this._name = name;\n break;\n }\n\n if (this._name.endsWith('...')) {\n this.variadic = true;\n this._name = this._name.slice(0, -3);\n }\n }\n\n /**\n * Return argument name.\n *\n * @return {string}\n */\n\n name() {\n return this._name;\n }\n\n /**\n * @package\n */\n\n _collectValue(value, previous) {\n if (previous === this.defaultValue || !Array.isArray(previous)) {\n return [value];\n }\n\n previous.push(value);\n return previous;\n }\n\n /**\n * Set the default value, and optionally supply the description to be displayed in the help.\n *\n * @param {*} value\n * @param {string} [description]\n * @return {Argument}\n */\n\n default(value, description) {\n this.defaultValue = value;\n this.defaultValueDescription = description;\n return this;\n }\n\n /**\n * Set the custom handler for processing CLI command arguments into argument values.\n *\n * @param {Function} [fn]\n * @return {Argument}\n */\n\n argParser(fn) {\n this.parseArg = fn;\n return this;\n }\n\n /**\n * Only allow argument value to be one of choices.\n *\n * @param {string[]} values\n * @return {Argument}\n */\n\n choices(values) {\n this.argChoices = values.slice();\n this.parseArg = (arg, previous) => {\n if (!this.argChoices.includes(arg)) {\n throw new InvalidArgumentError(\n `Allowed choices are ${this.argChoices.join(', ')}.`,\n );\n }\n if (this.variadic) {\n return this._collectValue(arg, previous);\n }\n return arg;\n };\n return this;\n }\n\n /**\n * Make argument required.\n *\n * @returns {Argument}\n */\n argRequired() {\n this.required = true;\n return this;\n }\n\n /**\n * Make argument optional.\n *\n * @returns {Argument}\n */\n argOptional() {\n this.required = false;\n return this;\n }\n}\n\n/**\n * Takes an argument and returns its human readable equivalent for help usage.\n *\n * @param {Argument} arg\n * @return {string}\n * @private\n */\n\nexport function humanReadableArgName(arg) {\n const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');\n\n return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']';\n}\n", "import { EventEmitter } from 'node:events';\nimport childProcess from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport process from 'node:process';\nimport { stripVTControlCharacters } from 'node:util';\n\nimport { Argument, humanReadableArgName } from './argument.js';\nimport { CommanderError } from './error.js';\nimport { Help } from './help.js';\nimport { Option, DualOptions } from './option.js';\nimport { suggestSimilar } from './suggestSimilar.js';\n\nexport class Command extends EventEmitter {\n /**\n * Initialize a new `Command`.\n *\n * @param {string} [name]\n */\n\n constructor(name) {\n super();\n /** @type {Command[]} */\n this.commands = [];\n /** @type {Option[]} */\n this.options = [];\n this.parent = null;\n this._allowUnknownOption = false;\n this._allowExcessArguments = false;\n /** @type {Argument[]} */\n this.registeredArguments = [];\n this._args = this.registeredArguments; // deprecated old name\n /** @type {string[]} */\n this.args = []; // cli args with options removed\n this.rawArgs = [];\n this.processedArgs = []; // like .args but after custom processing and collecting variadic\n this._scriptPath = null;\n this._name = name || '';\n this._optionValues = {};\n this._optionValueSources = {}; // default, env, cli etc\n this._storeOptionsAsProperties = false;\n this._actionHandler = null;\n this._executableHandler = false;\n this._executableFile = null; // custom name for executable\n this._executableDir = null; // custom search directory for subcommands\n this._defaultCommandName = null;\n this._exitCallback = null;\n this._aliases = [];\n this._combineFlagAndOptionalValue = true;\n this._description = '';\n this._summary = '';\n this._argsDescription = undefined; // legacy\n this._enablePositionalOptions = false;\n this._passThroughOptions = false;\n this._lifeCycleHooks = {}; // a hash of arrays\n /** @type {(boolean | string)} */\n this._showHelpAfterError = false;\n this._showSuggestionAfterError = true;\n this._savedState = null; // used in save/restoreStateBeforeParse\n\n // see configureOutput() for docs\n this._outputConfiguration = {\n writeOut: (str) => process.stdout.write(str),\n writeErr: (str) => process.stderr.write(str),\n outputError: (str, write) => write(str),\n getOutHelpWidth: () =>\n process.stdout.isTTY ? process.stdout.columns : undefined,\n getErrHelpWidth: () =>\n process.stderr.isTTY ? process.stderr.columns : undefined,\n getOutHasColors: () =>\n useColor() ?? (process.stdout.isTTY && process.stdout.hasColors?.()),\n getErrHasColors: () =>\n useColor() ?? (process.stderr.isTTY && process.stderr.hasColors?.()),\n stripColor: (str) => stripVTControlCharacters(str),\n };\n\n this._hidden = false;\n /** @type {(Option | null | undefined)} */\n this._helpOption = undefined; // Lazy created on demand. May be null if help option is disabled.\n this._addImplicitHelpCommand = undefined; // undecided whether true or false yet, not inherited\n /** @type {Command} */\n this._helpCommand = undefined; // lazy initialised, inherited\n this._helpConfiguration = {};\n /** @type {string | undefined} */\n this._helpGroupHeading = undefined; // soft initialised when added to parent\n /** @type {string | undefined} */\n this._defaultCommandGroup = undefined;\n /** @type {string | undefined} */\n this._defaultOptionGroup = undefined;\n }\n\n /**\n * Copy settings that are useful to have in common across root command and subcommands.\n *\n * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.)\n *\n * @param {Command} sourceCommand\n * @return {Command} `this` command for chaining\n */\n copyInheritedSettings(sourceCommand) {\n this._outputConfiguration = sourceCommand._outputConfiguration;\n this._helpOption = sourceCommand._helpOption;\n this._helpCommand = sourceCommand._helpCommand;\n this._helpConfiguration = sourceCommand._helpConfiguration;\n this._exitCallback = sourceCommand._exitCallback;\n this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;\n this._combineFlagAndOptionalValue =\n sourceCommand._combineFlagAndOptionalValue;\n this._allowExcessArguments = sourceCommand._allowExcessArguments;\n this._enablePositionalOptions = sourceCommand._enablePositionalOptions;\n this._showHelpAfterError = sourceCommand._showHelpAfterError;\n this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;\n\n return this;\n }\n\n /**\n * @returns {Command[]}\n * @private\n */\n\n _getCommandAndAncestors() {\n const result = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n for (let command = this; command; command = command.parent) {\n result.push(command);\n }\n return result;\n }\n\n /**\n * Define a command.\n *\n * There are two styles of command: pay attention to where to put the description.\n *\n * @example\n * // Command implemented using action handler (description is supplied separately to `.command`)\n * program\n * .command('clone [destination]')\n * .description('clone a repository into a newly created directory')\n * .action((source, destination) => {\n * console.log('clone command called');\n * });\n *\n * // Command implemented using separate executable file (description is second parameter to `.command`)\n * program\n * .command('start ', 'start named service')\n * .command('stop [service]', 'stop named service, or all if no name supplied');\n *\n * @param {string} nameAndArgs - command name and arguments, args are `` or `[optional]` and last may also be `variadic...`\n * @param {(object | string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)\n * @param {object} [execOpts] - configuration options (for executable)\n * @return {Command} returns new command for action handler, or `this` for executable command\n */\n\n command(nameAndArgs, actionOptsOrExecDesc, execOpts) {\n let desc = actionOptsOrExecDesc;\n let opts = execOpts;\n if (typeof desc === 'object' && desc !== null) {\n opts = desc;\n desc = null;\n }\n opts = opts || {};\n const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);\n\n const cmd = this.createCommand(name);\n if (desc) {\n cmd.description(desc);\n cmd._executableHandler = true;\n }\n if (opts.isDefault) this._defaultCommandName = cmd._name;\n cmd._hidden = !!(opts.noHelp || opts.hidden); // noHelp is deprecated old name for hidden\n cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor\n if (args) cmd.arguments(args);\n this._registerCommand(cmd);\n cmd.parent = this;\n cmd.copyInheritedSettings(this);\n\n if (desc) return this;\n return cmd;\n }\n\n /**\n * Factory routine to create a new unattached command.\n *\n * See .command() for creating an attached subcommand, which uses this routine to\n * create the command. You can override createCommand to customise subcommands.\n *\n * @param {string} [name]\n * @return {Command} new command\n */\n\n createCommand(name) {\n return new Command(name);\n }\n\n /**\n * You can customise the help with a subclass of Help by overriding createHelp,\n * or by overriding Help properties using configureHelp().\n *\n * @return {Help}\n */\n\n createHelp() {\n return Object.assign(new Help(), this.configureHelp());\n }\n\n /**\n * You can customise the help by overriding Help properties using configureHelp(),\n * or with a subclass of Help by overriding createHelp().\n *\n * @param {object} [configuration] - configuration options\n * @return {(Command | object)} `this` command for chaining, or stored configuration\n */\n\n configureHelp(configuration) {\n if (configuration === undefined) return this._helpConfiguration;\n\n this._helpConfiguration = configuration;\n return this;\n }\n\n /**\n * The default output goes to stdout and stderr. You can customise this for special\n * applications. You can also customise the display of errors by overriding outputError.\n *\n * The configuration properties are all functions:\n *\n * // change how output being written, defaults to stdout and stderr\n * writeOut(str)\n * writeErr(str)\n * // change how output being written for errors, defaults to writeErr\n * outputError(str, write) // used for displaying errors and not used for displaying help\n * // specify width for wrapping help\n * getOutHelpWidth()\n * getErrHelpWidth()\n * // color support, currently only used with Help\n * getOutHasColors()\n * getErrHasColors()\n * stripColor() // used to remove ANSI escape codes if output does not have colors\n *\n * @param {object} [configuration] - configuration options\n * @return {(Command | object)} `this` command for chaining, or stored configuration\n */\n\n configureOutput(configuration) {\n if (configuration === undefined) return this._outputConfiguration;\n\n this._outputConfiguration = {\n ...this._outputConfiguration,\n ...configuration,\n };\n return this;\n }\n\n /**\n * Display the help or a custom message after an error occurs.\n *\n * @param {(boolean|string)} [displayHelp]\n * @return {Command} `this` command for chaining\n */\n showHelpAfterError(displayHelp = true) {\n if (typeof displayHelp !== 'string') displayHelp = !!displayHelp;\n this._showHelpAfterError = displayHelp;\n return this;\n }\n\n /**\n * Display suggestion of similar commands for unknown commands, or options for unknown options.\n *\n * @param {boolean} [displaySuggestion]\n * @return {Command} `this` command for chaining\n */\n showSuggestionAfterError(displaySuggestion = true) {\n this._showSuggestionAfterError = !!displaySuggestion;\n return this;\n }\n\n /**\n * Add a prepared subcommand.\n *\n * See .command() for creating an attached subcommand which inherits settings from its parent.\n *\n * @param {Command} cmd - new subcommand\n * @param {object} [opts] - configuration options\n * @return {Command} `this` command for chaining\n */\n\n addCommand(cmd, opts) {\n if (!cmd._name) {\n throw new Error(`Command passed to .addCommand() must have a name\n- specify the name in Command constructor or using .name()`);\n }\n\n opts = opts || {};\n if (opts.isDefault) this._defaultCommandName = cmd._name;\n if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation\n\n this._registerCommand(cmd);\n cmd.parent = this;\n cmd._checkForBrokenPassThrough();\n\n return this;\n }\n\n /**\n * Factory routine to create a new unattached argument.\n *\n * See .argument() for creating an attached argument, which uses this routine to\n * create the argument. You can override createArgument to return a custom argument.\n *\n * @param {string} name\n * @param {string} [description]\n * @return {Argument} new argument\n */\n\n createArgument(name, description) {\n return new Argument(name, description);\n }\n\n /**\n * Define argument syntax for command.\n *\n * The default is that the argument is required, and you can explicitly\n * indicate this with <> around the name. Put [] around the name for an optional argument.\n *\n * @example\n * program.argument('');\n * program.argument('[output-file]');\n *\n * @param {string} name\n * @param {string} [description]\n * @param {(Function|*)} [parseArg] - custom argument processing function or default value\n * @param {*} [defaultValue]\n * @return {Command} `this` command for chaining\n */\n argument(name, description, parseArg, defaultValue) {\n const argument = this.createArgument(name, description);\n if (typeof parseArg === 'function') {\n argument.default(defaultValue).argParser(parseArg);\n } else {\n argument.default(parseArg);\n }\n this.addArgument(argument);\n return this;\n }\n\n /**\n * Define argument syntax for command, adding multiple at once (without descriptions).\n *\n * See also .argument().\n *\n * @example\n * program.arguments(' [env]');\n *\n * @param {string} names\n * @return {Command} `this` command for chaining\n */\n\n arguments(names) {\n names\n .trim()\n .split(/ +/)\n .forEach((detail) => {\n this.argument(detail);\n });\n return this;\n }\n\n /**\n * Define argument syntax for command, adding a prepared argument.\n *\n * @param {Argument} argument\n * @return {Command} `this` command for chaining\n */\n addArgument(argument) {\n const previousArgument = this.registeredArguments.slice(-1)[0];\n if (previousArgument?.variadic) {\n throw new Error(\n `only the last argument can be variadic '${previousArgument.name()}'`,\n );\n }\n if (\n argument.required &&\n argument.defaultValue !== undefined &&\n argument.parseArg === undefined\n ) {\n throw new Error(\n `a default value for a required argument is never used: '${argument.name()}'`,\n );\n }\n this.registeredArguments.push(argument);\n return this;\n }\n\n /**\n * Customise or override default help command. By default a help command is automatically added if your command has subcommands.\n *\n * @example\n * program.helpCommand('help [cmd]');\n * program.helpCommand('help [cmd]', 'show help');\n * program.helpCommand(false); // suppress default help command\n * program.helpCommand(true); // add help command even if no subcommands\n *\n * @param {string|boolean} enableOrNameAndArgs - enable with custom name and/or arguments, or boolean to override whether added\n * @param {string} [description] - custom description\n * @return {Command} `this` command for chaining\n */\n\n helpCommand(enableOrNameAndArgs, description) {\n if (typeof enableOrNameAndArgs === 'boolean') {\n this._addImplicitHelpCommand = enableOrNameAndArgs;\n if (enableOrNameAndArgs && this._defaultCommandGroup) {\n // make the command to store the group\n this._initCommandGroup(this._getHelpCommand());\n }\n return this;\n }\n\n const nameAndArgs = enableOrNameAndArgs ?? 'help [command]';\n const [, helpName, helpArgs] = nameAndArgs.match(/([^ ]+) *(.*)/);\n const helpDescription = description ?? 'display help for command';\n\n const helpCommand = this.createCommand(helpName);\n helpCommand.helpOption(false);\n if (helpArgs) helpCommand.arguments(helpArgs);\n if (helpDescription) helpCommand.description(helpDescription);\n\n this._addImplicitHelpCommand = true;\n this._helpCommand = helpCommand;\n // init group unless lazy create\n if (enableOrNameAndArgs || description) this._initCommandGroup(helpCommand);\n\n return this;\n }\n\n /**\n * Add prepared custom help command.\n *\n * @param {(Command|string|boolean)} helpCommand - custom help command, or deprecated enableOrNameAndArgs as for `.helpCommand()`\n * @param {string} [deprecatedDescription] - deprecated custom description used with custom name only\n * @return {Command} `this` command for chaining\n */\n addHelpCommand(helpCommand, deprecatedDescription) {\n // If not passed an object, call through to helpCommand for backwards compatibility,\n // as addHelpCommand was originally used like helpCommand is now.\n if (typeof helpCommand !== 'object') {\n this.helpCommand(helpCommand, deprecatedDescription);\n return this;\n }\n\n this._addImplicitHelpCommand = true;\n this._helpCommand = helpCommand;\n this._initCommandGroup(helpCommand);\n return this;\n }\n\n /**\n * Lazy create help command.\n *\n * @return {(Command|null)}\n * @package\n */\n _getHelpCommand() {\n const hasImplicitHelpCommand =\n this._addImplicitHelpCommand ??\n (this.commands.length &&\n !this._actionHandler &&\n !this._findCommand('help'));\n\n if (hasImplicitHelpCommand) {\n if (this._helpCommand === undefined) {\n this.helpCommand(undefined, undefined); // use default name and description\n }\n return this._helpCommand;\n }\n return null;\n }\n\n /**\n * Add hook for life cycle event.\n *\n * @param {string} event\n * @param {Function} listener\n * @return {Command} `this` command for chaining\n */\n\n hook(event, listener) {\n const allowedValues = ['preSubcommand', 'preAction', 'postAction'];\n if (!allowedValues.includes(event)) {\n throw new Error(`Unexpected value for event passed to hook : '${event}'.\nExpecting one of '${allowedValues.join(\"', '\")}'`);\n }\n if (this._lifeCycleHooks[event]) {\n this._lifeCycleHooks[event].push(listener);\n } else {\n this._lifeCycleHooks[event] = [listener];\n }\n return this;\n }\n\n /**\n * Register callback to use as replacement for calling process.exit.\n *\n * @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing\n * @return {Command} `this` command for chaining\n */\n\n exitOverride(fn) {\n if (fn) {\n this._exitCallback = fn;\n } else {\n this._exitCallback = (err) => {\n if (err.code !== 'commander.executeSubCommandAsync') {\n throw err;\n } else {\n // Async callback from spawn events, not useful to throw.\n }\n };\n }\n return this;\n }\n\n /**\n * Call process.exit, and _exitCallback if defined.\n *\n * @param {number} exitCode exit code for using with process.exit\n * @param {string} code an id string representing the error\n * @param {string} message human-readable description of the error\n * @return never\n * @private\n */\n\n _exit(exitCode, code, message) {\n if (this._exitCallback) {\n this._exitCallback(new CommanderError(exitCode, code, message));\n // Expecting this line is not reached.\n }\n process.exit(exitCode);\n }\n\n /**\n * Register callback `fn` for the command.\n *\n * @example\n * program\n * .command('serve')\n * .description('start service')\n * .action(function() {\n * // do work here\n * });\n *\n * @param {Function} fn\n * @return {Command} `this` command for chaining\n */\n\n action(fn) {\n const listener = (args) => {\n // The .action callback takes an extra parameter which is the command or options.\n const expectedArgsCount = this.registeredArguments.length;\n const actionArgs = args.slice(0, expectedArgsCount);\n if (this._storeOptionsAsProperties) {\n actionArgs[expectedArgsCount] = this; // backwards compatible \"options\"\n } else {\n actionArgs[expectedArgsCount] = this.opts();\n }\n actionArgs.push(this);\n\n return fn.apply(this, actionArgs);\n };\n this._actionHandler = listener;\n return this;\n }\n\n /**\n * Factory routine to create a new unattached option.\n *\n * See .option() for creating an attached option, which uses this routine to\n * create the option. You can override createOption to return a custom option.\n *\n * @param {string} flags\n * @param {string} [description]\n * @return {Option} new option\n */\n\n createOption(flags, description) {\n return new Option(flags, description);\n }\n\n /**\n * Wrap parseArgs to catch 'commander.invalidArgument'.\n *\n * @param {(Option | Argument)} target\n * @param {string} value\n * @param {*} previous\n * @param {string} invalidArgumentMessage\n * @private\n */\n\n _callParseArg(target, value, previous, invalidArgumentMessage) {\n try {\n return target.parseArg(value, previous);\n } catch (err) {\n if (err.code === 'commander.invalidArgument') {\n const message = `${invalidArgumentMessage} ${err.message}`;\n this.error(message, { exitCode: err.exitCode, code: err.code });\n }\n throw err;\n }\n }\n\n /**\n * Check for option flag conflicts.\n * Register option if no conflicts found, or throw on conflict.\n *\n * @param {Option} option\n * @private\n */\n\n _registerOption(option) {\n const matchingOption =\n (option.short && this._findOption(option.short)) ||\n (option.long && this._findOption(option.long));\n if (matchingOption) {\n const matchingFlag =\n option.long && this._findOption(option.long)\n ? option.long\n : option.short;\n throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'\n- already used by option '${matchingOption.flags}'`);\n }\n\n this._initOptionGroup(option);\n this.options.push(option);\n }\n\n /**\n * Check for command name and alias conflicts with existing commands.\n * Register command if no conflicts found, or throw on conflict.\n *\n * @param {Command} command\n * @private\n */\n\n _registerCommand(command) {\n const knownBy = (cmd) => {\n return [cmd.name()].concat(cmd.aliases());\n };\n\n const alreadyUsed = knownBy(command).find((name) =>\n this._findCommand(name),\n );\n if (alreadyUsed) {\n const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');\n const newCmd = knownBy(command).join('|');\n throw new Error(\n `cannot add command '${newCmd}' as already have command '${existingCmd}'`,\n );\n }\n\n this._initCommandGroup(command);\n this.commands.push(command);\n }\n\n /**\n * Add an option.\n *\n * @param {Option} option\n * @return {Command} `this` command for chaining\n */\n addOption(option) {\n this._registerOption(option);\n\n const oname = option.name();\n const name = option.attributeName();\n\n // store default value\n if (option.defaultValue !== undefined) {\n this.setOptionValueWithSource(name, option.defaultValue, 'default');\n }\n\n // handler for cli and env supplied values\n const handleOptionValue = (val, invalidValueMessage, valueSource) => {\n // val is null for optional option used without an optional-argument.\n // val is undefined for boolean and negated option.\n if (val == null && option.presetArg !== undefined) {\n val = option.presetArg;\n }\n\n // custom processing\n const oldValue = this.getOptionValue(name);\n if (val !== null && option.parseArg) {\n val = this._callParseArg(option, val, oldValue, invalidValueMessage);\n } else if (val !== null && option.variadic) {\n val = option._collectValue(val, oldValue);\n }\n\n // Fill-in appropriate missing values. Long winded but easy to follow.\n if (val == null) {\n if (option.negate) {\n val = false;\n } else if (option.isBoolean() || option.optional) {\n val = true;\n } else {\n val = ''; // not normal, parseArg might have failed or be a mock function for testing\n }\n }\n this.setOptionValueWithSource(name, val, valueSource);\n };\n\n this.on('option:' + oname, (val) => {\n const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;\n handleOptionValue(val, invalidValueMessage, 'cli');\n });\n\n if (option.envVar) {\n this.on('optionEnv:' + oname, (val) => {\n const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;\n handleOptionValue(val, invalidValueMessage, 'env');\n });\n }\n\n return this;\n }\n\n /**\n * Internal implementation shared by .option() and .requiredOption()\n *\n * @return {Command} `this` command for chaining\n * @private\n */\n _optionEx(config, flags, description, fn, defaultValue) {\n if (typeof flags === 'object' && flags instanceof Option) {\n throw new Error(\n 'To add an Option object use addOption() instead of option() or requiredOption()',\n );\n }\n const option = this.createOption(flags, description);\n option.makeOptionMandatory(!!config.mandatory);\n if (typeof fn === 'function') {\n option.default(defaultValue).argParser(fn);\n } else if (fn instanceof RegExp) {\n // deprecated\n const regex = fn;\n fn = (val, def) => {\n const m = regex.exec(val);\n return m ? m[0] : def;\n };\n option.default(defaultValue).argParser(fn);\n } else {\n option.default(fn);\n }\n\n return this.addOption(option);\n }\n\n /**\n * Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.\n *\n * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required\n * option-argument is indicated by `<>` and an optional option-argument by `[]`.\n *\n * See the README for more details, and see also addOption() and requiredOption().\n *\n * @example\n * program\n * .option('-p, --pepper', 'add pepper')\n * .option('--pt, --pizza-type ', 'type of pizza') // required option-argument\n * .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default\n * .option('-t, --tip ', 'add tip to purchase cost', parseFloat) // custom parse function\n *\n * @param {string} flags\n * @param {string} [description]\n * @param {(Function|*)} [parseArg] - custom option processing function or default value\n * @param {*} [defaultValue]\n * @return {Command} `this` command for chaining\n */\n\n option(flags, description, parseArg, defaultValue) {\n return this._optionEx({}, flags, description, parseArg, defaultValue);\n }\n\n /**\n * Add a required option which must have a value after parsing. This usually means\n * the option must be specified on the command line. (Otherwise the same as .option().)\n *\n * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.\n *\n * @param {string} flags\n * @param {string} [description]\n * @param {(Function|*)} [parseArg] - custom option processing function or default value\n * @param {*} [defaultValue]\n * @return {Command} `this` command for chaining\n */\n\n requiredOption(flags, description, parseArg, defaultValue) {\n return this._optionEx(\n { mandatory: true },\n flags,\n description,\n parseArg,\n defaultValue,\n );\n }\n\n /**\n * Alter parsing of short flags with optional values.\n *\n * @example\n * // for `.option('-f,--flag [value]'):\n * program.combineFlagAndOptionalValue(true); // `-f80` is treated like `--flag=80`, this is the default behaviour\n * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`\n *\n * @param {boolean} [combine] - if `true` or omitted, an optional value can be specified directly after the flag.\n * @return {Command} `this` command for chaining\n */\n combineFlagAndOptionalValue(combine = true) {\n this._combineFlagAndOptionalValue = !!combine;\n return this;\n }\n\n /**\n * Allow unknown options on the command line.\n *\n * @param {boolean} [allowUnknown] - if `true` or omitted, no error will be thrown for unknown options.\n * @return {Command} `this` command for chaining\n */\n allowUnknownOption(allowUnknown = true) {\n this._allowUnknownOption = !!allowUnknown;\n return this;\n }\n\n /**\n * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.\n *\n * @param {boolean} [allowExcess] - if `true` or omitted, no error will be thrown for excess arguments.\n * @return {Command} `this` command for chaining\n */\n allowExcessArguments(allowExcess = true) {\n this._allowExcessArguments = !!allowExcess;\n return this;\n }\n\n /**\n * Enable positional options. Positional means global options are specified before subcommands which lets\n * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.\n * The default behaviour is non-positional and global options may appear anywhere on the command line.\n *\n * @param {boolean} [positional]\n * @return {Command} `this` command for chaining\n */\n enablePositionalOptions(positional = true) {\n this._enablePositionalOptions = !!positional;\n return this;\n }\n\n /**\n * Pass through options that come after command-arguments rather than treat them as command-options,\n * so actual command-options come before command-arguments. Turning this on for a subcommand requires\n * positional options to have been enabled on the program (parent commands).\n * The default behaviour is non-positional and options may appear before or after command-arguments.\n *\n * @param {boolean} [passThrough] for unknown options.\n * @return {Command} `this` command for chaining\n */\n passThroughOptions(passThrough = true) {\n this._passThroughOptions = !!passThrough;\n this._checkForBrokenPassThrough();\n return this;\n }\n\n /**\n * @private\n */\n\n _checkForBrokenPassThrough() {\n if (\n this.parent &&\n this._passThroughOptions &&\n !this.parent._enablePositionalOptions\n ) {\n throw new Error(\n `passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`,\n );\n }\n }\n\n /**\n * Whether to store option values as properties on command object,\n * or store separately (specify false). In both cases the option values can be accessed using .opts().\n *\n * @param {boolean} [storeAsProperties=true]\n * @return {Command} `this` command for chaining\n */\n\n storeOptionsAsProperties(storeAsProperties = true) {\n if (this.options.length) {\n throw new Error('call .storeOptionsAsProperties() before adding options');\n }\n if (Object.keys(this._optionValues).length) {\n throw new Error(\n 'call .storeOptionsAsProperties() before setting option values',\n );\n }\n this._storeOptionsAsProperties = !!storeAsProperties;\n return this;\n }\n\n /**\n * Retrieve option value.\n *\n * @param {string} key\n * @return {object} value\n */\n\n getOptionValue(key) {\n if (this._storeOptionsAsProperties) {\n return this[key];\n }\n return this._optionValues[key];\n }\n\n /**\n * Store option value.\n *\n * @param {string} key\n * @param {object} value\n * @return {Command} `this` command for chaining\n */\n\n setOptionValue(key, value) {\n return this.setOptionValueWithSource(key, value, undefined);\n }\n\n /**\n * Store option value and where the value came from.\n *\n * @param {string} key\n * @param {object} value\n * @param {string} source - expected values are default/config/env/cli/implied\n * @return {Command} `this` command for chaining\n */\n\n setOptionValueWithSource(key, value, source) {\n if (this._storeOptionsAsProperties) {\n this[key] = value;\n } else {\n this._optionValues[key] = value;\n }\n this._optionValueSources[key] = source;\n return this;\n }\n\n /**\n * Get source of option value.\n * Expected values are default | config | env | cli | implied\n *\n * @param {string} key\n * @return {string}\n */\n\n getOptionValueSource(key) {\n return this._optionValueSources[key];\n }\n\n /**\n * Get source of option value. See also .optsWithGlobals().\n * Expected values are default | config | env | cli | implied\n *\n * @param {string} key\n * @return {string}\n */\n\n getOptionValueSourceWithGlobals(key) {\n // global overwrites local, like optsWithGlobals\n let source;\n this._getCommandAndAncestors().forEach((cmd) => {\n if (cmd.getOptionValueSource(key) !== undefined) {\n source = cmd.getOptionValueSource(key);\n }\n });\n return source;\n }\n\n /**\n * Get user arguments from implied or explicit arguments.\n * Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.\n *\n * @private\n */\n\n _prepareUserArgs(argv, parseOptions) {\n if (argv !== undefined && !Array.isArray(argv)) {\n throw new Error('first parameter to parse must be array or undefined');\n }\n parseOptions = parseOptions || {};\n\n // auto-detect argument conventions if nothing supplied\n if (argv === undefined && parseOptions.from === undefined) {\n if (process.versions?.electron) {\n parseOptions.from = 'electron';\n }\n // check node specific options for scenarios where user CLI args follow executable without scriptname\n const execArgv = process.execArgv ?? [];\n if (\n execArgv.includes('-e') ||\n execArgv.includes('--eval') ||\n execArgv.includes('-p') ||\n execArgv.includes('--print')\n ) {\n parseOptions.from = 'eval'; // internal usage, not documented\n }\n }\n\n // default to using process.argv\n if (argv === undefined) {\n argv = process.argv;\n }\n this.rawArgs = argv.slice();\n\n // extract the user args and scriptPath\n let userArgs;\n switch (parseOptions.from) {\n case undefined:\n case 'node':\n this._scriptPath = argv[1];\n userArgs = argv.slice(2);\n break;\n case 'electron':\n // @ts-ignore: because defaultApp is an unknown property\n if (process.defaultApp) {\n this._scriptPath = argv[1];\n userArgs = argv.slice(2);\n } else {\n userArgs = argv.slice(1);\n }\n break;\n case 'user':\n userArgs = argv.slice(0);\n break;\n case 'eval':\n userArgs = argv.slice(1);\n break;\n default:\n throw new Error(\n `unexpected parse option { from: '${parseOptions.from}' }`,\n );\n }\n\n // Find default name for program from arguments.\n if (!this._name && this._scriptPath)\n this.nameFromFilename(this._scriptPath);\n this._name = this._name || 'program';\n\n return userArgs;\n }\n\n /**\n * Parse `argv`, setting options and invoking commands when defined.\n *\n * Use parseAsync instead of parse if any of your action handlers are async.\n *\n * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n *\n * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n * - `'user'`: just user arguments\n *\n * @example\n * program.parse(); // parse process.argv and auto-detect electron and special node flags\n * program.parse(process.argv); // assume argv[0] is app and argv[1] is script\n * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n *\n * @param {string[]} [argv] - optional, defaults to process.argv\n * @param {object} [parseOptions] - optionally specify style of options with from: node/user/electron\n * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron'\n * @return {Command} `this` command for chaining\n */\n\n parse(argv, parseOptions) {\n this._prepareForParse();\n const userArgs = this._prepareUserArgs(argv, parseOptions);\n this._parseCommand([], userArgs);\n\n return this;\n }\n\n /**\n * Parse `argv`, setting options and invoking commands when defined.\n *\n * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n *\n * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n * - `'user'`: just user arguments\n *\n * @example\n * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags\n * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script\n * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n *\n * @param {string[]} [argv]\n * @param {object} [parseOptions]\n * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron'\n * @return {Promise}\n */\n\n async parseAsync(argv, parseOptions) {\n this._prepareForParse();\n const userArgs = this._prepareUserArgs(argv, parseOptions);\n await this._parseCommand([], userArgs);\n\n return this;\n }\n\n _prepareForParse() {\n // Save the state the first time, then restore the state before each subsequent parse.\n if (this._savedState === null) {\n // Do the special default of lone negated option to true, now that we have all the options.\n // Filter for negated options that have not been processed already.\n this.options\n .filter(\n (option) =>\n option.negate &&\n option.defaultValue === undefined &&\n this.getOptionValue(option.attributeName()) === undefined,\n )\n .forEach((option) => {\n // check for lone negated option: --no-foo without a --foo option\n const positiveLongFlag = option.long.replace(/^--no-/, '--');\n if (!this._findOption(positiveLongFlag)) {\n this.setOptionValueWithSource(\n option.attributeName(),\n true,\n 'default',\n );\n }\n });\n\n this.saveStateBeforeParse();\n } else {\n this.restoreStateBeforeParse();\n }\n }\n\n /**\n * Called the first time parse is called to save state and allow a restore before subsequent calls to parse.\n * Not usually called directly, but available for subclasses to save their custom state.\n *\n * This is called in a lazy way. Only commands used in parsing chain will have state saved.\n */\n saveStateBeforeParse() {\n this._savedState = {\n // name is stable if supplied by author, but may be unspecified for root command and deduced during parsing\n _name: this._name,\n // option values before parse have default values (including false for negated options)\n // shallow clones\n _optionValues: { ...this._optionValues },\n _optionValueSources: { ...this._optionValueSources },\n };\n }\n\n /**\n * Restore state before parse for calls after the first.\n * Not usually called directly, but available for subclasses to save their custom state.\n *\n * This is called in a lazy way. Only commands used in parsing chain will have state restored.\n */\n restoreStateBeforeParse() {\n if (this._storeOptionsAsProperties)\n throw new Error(`Can not call parse again when storeOptionsAsProperties is true.\n- either make a new Command for each call to parse, or stop storing options as properties`);\n\n // clear state from _prepareUserArgs\n this._name = this._savedState._name;\n this._scriptPath = null;\n this.rawArgs = [];\n // clear state from setOptionValueWithSource\n this._optionValues = { ...this._savedState._optionValues };\n this._optionValueSources = { ...this._savedState._optionValueSources };\n // clear state from _parseCommand\n this.args = [];\n // clear state from _processArguments\n this.processedArgs = [];\n }\n\n /**\n * Throw if expected executable is missing. Add lots of help for author.\n *\n * @param {string} executableFile\n * @param {string} executableDir\n * @param {string} subcommandName\n */\n _checkForMissingExecutable(executableFile, executableDir, subcommandName) {\n if (fs.existsSync(executableFile)) return;\n\n const executableDirMessage = executableDir\n ? `searched for local subcommand relative to directory '${executableDir}'`\n : 'no directory for search for local subcommand, use .executableDir() to supply a custom directory';\n const executableMissing = `'${executableFile}' does not exist\n - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead\n - if the default executable name is not suitable, use the executableFile option to supply a custom name or path\n - ${executableDirMessage}`;\n throw new Error(executableMissing);\n }\n\n /**\n * Execute a sub-command executable.\n *\n * @private\n */\n\n _executeSubCommand(subcommand, args) {\n args = args.slice();\n const sourceExt = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];\n\n function findFile(baseDir, baseName) {\n // Look for specified file\n const localBin = path.resolve(baseDir, baseName);\n if (fs.existsSync(localBin)) return localBin;\n\n // Stop looking if candidate already has an expected extension.\n if (sourceExt.includes(path.extname(baseName))) return undefined;\n\n // Try all the extensions.\n const foundExt = sourceExt.find((ext) =>\n fs.existsSync(`${localBin}${ext}`),\n );\n if (foundExt) return `${localBin}${foundExt}`;\n\n return undefined;\n }\n\n // Not checking for help first. Unlikely to have mandatory and executable, and can't robustly test for help flags in external command.\n this._checkForMissingMandatoryOptions();\n this._checkForConflictingOptions();\n\n // executableFile and executableDir might be full path, or just a name\n let executableFile =\n subcommand._executableFile || `${this._name}-${subcommand._name}`;\n let executableDir = this._executableDir || '';\n if (this._scriptPath) {\n let resolvedScriptPath; // resolve possible symlink for installed npm binary\n try {\n resolvedScriptPath = fs.realpathSync(this._scriptPath);\n } catch {\n resolvedScriptPath = this._scriptPath;\n }\n executableDir = path.resolve(\n path.dirname(resolvedScriptPath),\n executableDir,\n );\n }\n\n // Look for a local file in preference to a command in PATH.\n if (executableDir) {\n let localFile = findFile(executableDir, executableFile);\n\n // Legacy search using prefix of script name instead of command name\n if (!localFile && !subcommand._executableFile && this._scriptPath) {\n const legacyName = path.basename(\n this._scriptPath,\n path.extname(this._scriptPath),\n );\n if (legacyName !== this._name) {\n localFile = findFile(\n executableDir,\n `${legacyName}-${subcommand._name}`,\n );\n }\n }\n executableFile = localFile || executableFile;\n }\n\n const launchWithNode = sourceExt.includes(path.extname(executableFile));\n\n let proc;\n if (process.platform !== 'win32') {\n if (launchWithNode) {\n args.unshift(executableFile);\n // add executable arguments to spawn\n args = incrementNodeInspectorPort(process.execArgv).concat(args);\n\n proc = childProcess.spawn(process.argv[0], args, { stdio: 'inherit' });\n } else {\n proc = childProcess.spawn(executableFile, args, { stdio: 'inherit' });\n }\n } else {\n this._checkForMissingExecutable(\n executableFile,\n executableDir,\n subcommand._name,\n );\n args.unshift(executableFile);\n // add executable arguments to spawn\n args = incrementNodeInspectorPort(process.execArgv).concat(args);\n proc = childProcess.spawn(process.execPath, args, { stdio: 'inherit' });\n }\n\n if (!proc.killed) {\n // testing mainly to avoid leak warnings during unit tests with mocked spawn\n const signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];\n signals.forEach((signal) => {\n process.on(signal, () => {\n if (proc.killed === false && proc.exitCode === null) {\n // @ts-ignore because signals not typed to known strings\n proc.kill(signal);\n }\n });\n });\n }\n\n // By default terminate process when spawned process terminates.\n const exitCallback = this._exitCallback;\n proc.on('close', (code) => {\n code = code ?? 1; // code is null if spawned process terminated due to a signal\n if (!exitCallback) {\n process.exit(code);\n } else {\n exitCallback(\n new CommanderError(\n code,\n 'commander.executeSubCommandAsync',\n '(close)',\n ),\n );\n }\n });\n proc.on('error', (err) => {\n // @ts-ignore: because err.code is an unknown property\n if (err.code === 'ENOENT') {\n this._checkForMissingExecutable(\n executableFile,\n executableDir,\n subcommand._name,\n );\n // @ts-ignore: because err.code is an unknown property\n } else if (err.code === 'EACCES') {\n throw new Error(`'${executableFile}' not executable`);\n }\n if (!exitCallback) {\n process.exit(1);\n } else {\n const wrappedError = new CommanderError(\n 1,\n 'commander.executeSubCommandAsync',\n '(error)',\n );\n wrappedError.nestedError = err;\n exitCallback(wrappedError);\n }\n });\n\n // Store the reference to the child process\n this.runningCommand = proc;\n }\n\n /**\n * @private\n */\n\n _dispatchSubcommand(commandName, operands, unknown) {\n const subCommand = this._findCommand(commandName);\n if (!subCommand) this.help({ error: true });\n\n subCommand._prepareForParse();\n let promiseChain;\n promiseChain = this._chainOrCallSubCommandHook(\n promiseChain,\n subCommand,\n 'preSubcommand',\n );\n promiseChain = this._chainOrCall(promiseChain, () => {\n if (subCommand._executableHandler) {\n this._executeSubCommand(subCommand, operands.concat(unknown));\n } else {\n return subCommand._parseCommand(operands, unknown);\n }\n });\n return promiseChain;\n }\n\n /**\n * Invoke help directly if possible, or dispatch if necessary.\n * e.g. help foo\n *\n * @private\n */\n\n _dispatchHelpCommand(subcommandName) {\n if (!subcommandName) {\n this.help();\n }\n const subCommand = this._findCommand(subcommandName);\n if (subCommand && !subCommand._executableHandler) {\n subCommand.help();\n }\n\n // Fallback to parsing the help flag to invoke the help.\n return this._dispatchSubcommand(\n subcommandName,\n [],\n [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? '--help'],\n );\n }\n\n /**\n * Check this.args against expected this.registeredArguments.\n *\n * @private\n */\n\n _checkNumberOfArguments() {\n // too few\n this.registeredArguments.forEach((arg, i) => {\n if (arg.required && this.args[i] == null) {\n this.missingArgument(arg.name());\n }\n });\n // too many\n if (\n this.registeredArguments.length > 0 &&\n this.registeredArguments[this.registeredArguments.length - 1].variadic\n ) {\n return;\n }\n if (this.args.length > this.registeredArguments.length) {\n this._excessArguments(this.args);\n }\n }\n\n /**\n * Process this.args using this.registeredArguments and save as this.processedArgs!\n *\n * @private\n */\n\n _processArguments() {\n const myParseArg = (argument, value, previous) => {\n // Extra processing for nice error message on parsing failure.\n let parsedValue = value;\n if (value !== null && argument.parseArg) {\n const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;\n parsedValue = this._callParseArg(\n argument,\n value,\n previous,\n invalidValueMessage,\n );\n }\n return parsedValue;\n };\n\n this._checkNumberOfArguments();\n\n const processedArgs = [];\n this.registeredArguments.forEach((declaredArg, index) => {\n let value = declaredArg.defaultValue;\n if (declaredArg.variadic) {\n // Collect together remaining arguments for passing together as an array.\n if (index < this.args.length) {\n value = this.args.slice(index);\n if (declaredArg.parseArg) {\n value = value.reduce((processed, v) => {\n return myParseArg(declaredArg, v, processed);\n }, declaredArg.defaultValue);\n }\n } else if (value === undefined) {\n value = [];\n }\n } else if (index < this.args.length) {\n value = this.args[index];\n if (declaredArg.parseArg) {\n value = myParseArg(declaredArg, value, declaredArg.defaultValue);\n }\n }\n processedArgs[index] = value;\n });\n this.processedArgs = processedArgs;\n }\n\n /**\n * Once we have a promise we chain, but call synchronously until then.\n *\n * @param {(Promise|undefined)} promise\n * @param {Function} fn\n * @return {(Promise|undefined)}\n * @private\n */\n\n _chainOrCall(promise, fn) {\n // thenable\n if (promise?.then && typeof promise.then === 'function') {\n // already have a promise, chain callback\n return promise.then(() => fn());\n }\n // callback might return a promise\n return fn();\n }\n\n /**\n *\n * @param {(Promise|undefined)} promise\n * @param {string} event\n * @return {(Promise|undefined)}\n * @private\n */\n\n _chainOrCallHooks(promise, event) {\n let result = promise;\n const hooks = [];\n this._getCommandAndAncestors()\n .reverse()\n .filter((cmd) => cmd._lifeCycleHooks[event] !== undefined)\n .forEach((hookedCommand) => {\n hookedCommand._lifeCycleHooks[event].forEach((callback) => {\n hooks.push({ hookedCommand, callback });\n });\n });\n if (event === 'postAction') {\n hooks.reverse();\n }\n\n hooks.forEach((hookDetail) => {\n result = this._chainOrCall(result, () => {\n return hookDetail.callback(hookDetail.hookedCommand, this);\n });\n });\n return result;\n }\n\n /**\n *\n * @param {(Promise|undefined)} promise\n * @param {Command} subCommand\n * @param {string} event\n * @return {(Promise|undefined)}\n * @private\n */\n\n _chainOrCallSubCommandHook(promise, subCommand, event) {\n let result = promise;\n if (this._lifeCycleHooks[event] !== undefined) {\n this._lifeCycleHooks[event].forEach((hook) => {\n result = this._chainOrCall(result, () => {\n return hook(this, subCommand);\n });\n });\n }\n return result;\n }\n\n /**\n * Process arguments in context of this command.\n * Returns action result, in case it is a promise.\n *\n * @private\n */\n\n _parseCommand(operands, unknown) {\n const parsed = this.parseOptions(unknown);\n this._parseOptionsEnv(); // after cli, so parseArg not called on both cli and env\n this._parseOptionsImplied();\n operands = operands.concat(parsed.operands);\n unknown = parsed.unknown;\n this.args = operands.concat(unknown);\n\n if (operands && this._findCommand(operands[0])) {\n return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);\n }\n if (\n this._getHelpCommand() &&\n operands[0] === this._getHelpCommand().name()\n ) {\n return this._dispatchHelpCommand(operands[1]);\n }\n if (this._defaultCommandName) {\n this._outputHelpIfRequested(unknown); // Run the help for default command from parent rather than passing to default command\n return this._dispatchSubcommand(\n this._defaultCommandName,\n operands,\n unknown,\n );\n }\n if (\n this.commands.length &&\n this.args.length === 0 &&\n !this._actionHandler &&\n !this._defaultCommandName\n ) {\n // probably missing subcommand and no handler, user needs help (and exit)\n this.help({ error: true });\n }\n\n this._outputHelpIfRequested(parsed.unknown);\n this._checkForMissingMandatoryOptions();\n this._checkForConflictingOptions();\n\n // We do not always call this check to avoid masking a \"better\" error, like unknown command.\n const checkForUnknownOptions = () => {\n if (parsed.unknown.length > 0) {\n this.unknownOption(parsed.unknown[0]);\n }\n };\n\n const commandEvent = `command:${this.name()}`;\n if (this._actionHandler) {\n checkForUnknownOptions();\n this._processArguments();\n\n let promiseChain;\n promiseChain = this._chainOrCallHooks(promiseChain, 'preAction');\n promiseChain = this._chainOrCall(promiseChain, () =>\n this._actionHandler(this.processedArgs),\n );\n if (this.parent) {\n promiseChain = this._chainOrCall(promiseChain, () => {\n this.parent.emit(commandEvent, operands, unknown); // legacy\n });\n }\n promiseChain = this._chainOrCallHooks(promiseChain, 'postAction');\n return promiseChain;\n }\n if (this.parent?.listenerCount(commandEvent)) {\n checkForUnknownOptions();\n this._processArguments();\n this.parent.emit(commandEvent, operands, unknown); // legacy\n } else if (operands.length) {\n if (this._findCommand('*')) {\n // legacy default command\n return this._dispatchSubcommand('*', operands, unknown);\n }\n if (this.listenerCount('command:*')) {\n // skip option check, emit event for possible misspelling suggestion\n this.emit('command:*', operands, unknown);\n } else if (this.commands.length) {\n this.unknownCommand();\n } else {\n checkForUnknownOptions();\n this._processArguments();\n }\n } else if (this.commands.length) {\n checkForUnknownOptions();\n // This command has subcommands and nothing hooked up at this level, so display help (and exit).\n this.help({ error: true });\n } else {\n checkForUnknownOptions();\n this._processArguments();\n // fall through for caller to handle after calling .parse()\n }\n }\n\n /**\n * Find matching command.\n *\n * @private\n * @return {Command | undefined}\n */\n _findCommand(name) {\n if (!name) return undefined;\n return this.commands.find(\n (cmd) => cmd._name === name || cmd._aliases.includes(name),\n );\n }\n\n /**\n * Return an option matching `arg` if any.\n *\n * @param {string} arg\n * @return {Option}\n * @package\n */\n\n _findOption(arg) {\n return this.options.find((option) => option.is(arg));\n }\n\n /**\n * Display an error message if a mandatory option does not have a value.\n * Called after checking for help flags in leaf subcommand.\n *\n * @private\n */\n\n _checkForMissingMandatoryOptions() {\n // Walk up hierarchy so can call in subcommand after checking for displaying help.\n this._getCommandAndAncestors().forEach((cmd) => {\n cmd.options.forEach((anOption) => {\n if (\n anOption.mandatory &&\n cmd.getOptionValue(anOption.attributeName()) === undefined\n ) {\n cmd.missingMandatoryOptionValue(anOption);\n }\n });\n });\n }\n\n /**\n * Display an error message if conflicting options are used together in this.\n *\n * @private\n */\n _checkForConflictingLocalOptions() {\n const definedNonDefaultOptions = this.options.filter((option) => {\n const optionKey = option.attributeName();\n if (this.getOptionValue(optionKey) === undefined) {\n return false;\n }\n return this.getOptionValueSource(optionKey) !== 'default';\n });\n\n const optionsWithConflicting = definedNonDefaultOptions.filter(\n (option) => option.conflictsWith.length > 0,\n );\n\n optionsWithConflicting.forEach((option) => {\n const conflictingAndDefined = definedNonDefaultOptions.find((defined) =>\n option.conflictsWith.includes(defined.attributeName()),\n );\n if (conflictingAndDefined) {\n this._conflictingOption(option, conflictingAndDefined);\n }\n });\n }\n\n /**\n * Display an error message if conflicting options are used together.\n * Called after checking for help flags in leaf subcommand.\n *\n * @private\n */\n _checkForConflictingOptions() {\n // Walk up hierarchy so can call in subcommand after checking for displaying help.\n this._getCommandAndAncestors().forEach((cmd) => {\n cmd._checkForConflictingLocalOptions();\n });\n }\n\n /**\n * Parse options from `argv` removing known options,\n * and return argv split into operands and unknown arguments.\n *\n * Side effects: modifies command by storing options. Does not reset state if called again.\n *\n * Examples:\n *\n * argv => operands, unknown\n * --known kkk op => [op], []\n * op --known kkk => [op], []\n * sub --unknown uuu op => [sub], [--unknown uuu op]\n * sub -- --unknown uuu op => [sub --unknown uuu op], []\n *\n * @param {string[]} args\n * @return {{operands: string[], unknown: string[]}}\n */\n\n parseOptions(args) {\n const operands = []; // operands, not options or values\n const unknown = []; // first unknown option and remaining unknown args\n let dest = operands;\n\n function maybeOption(arg) {\n return arg.length > 1 && arg[0] === '-';\n }\n\n const negativeNumberArg = (arg) => {\n // return false if not a negative number\n if (!/^-(\\d+|\\d*\\.\\d+)(e[+-]?\\d+)?$/.test(arg)) return false;\n // negative number is ok unless digit used as an option in command hierarchy\n return !this._getCommandAndAncestors().some((cmd) =>\n cmd.options\n .map((opt) => opt.short)\n .some((short) => /^-\\d$/.test(short)),\n );\n };\n\n // parse options\n let activeVariadicOption = null;\n let activeGroup = null; // working through group of short options, like -abc\n let i = 0;\n while (i < args.length || activeGroup) {\n const arg = activeGroup ?? args[i++];\n activeGroup = null;\n\n // literal\n if (arg === '--') {\n if (dest === unknown) dest.push(arg);\n dest.push(...args.slice(i));\n break;\n }\n\n if (\n activeVariadicOption &&\n (!maybeOption(arg) || negativeNumberArg(arg))\n ) {\n this.emit(`option:${activeVariadicOption.name()}`, arg);\n continue;\n }\n activeVariadicOption = null;\n\n if (maybeOption(arg)) {\n const option = this._findOption(arg);\n // recognised option, call listener to assign value with possible custom processing\n if (option) {\n if (option.required) {\n const value = args[i++];\n if (value === undefined) this.optionMissingArgument(option);\n this.emit(`option:${option.name()}`, value);\n } else if (option.optional) {\n let value = null;\n // historical behaviour is optional value is following arg unless an option\n if (\n i < args.length &&\n (!maybeOption(args[i]) || negativeNumberArg(args[i]))\n ) {\n value = args[i++];\n }\n this.emit(`option:${option.name()}`, value);\n } else {\n // boolean flag\n this.emit(`option:${option.name()}`);\n }\n activeVariadicOption = option.variadic ? option : null;\n continue;\n }\n }\n\n // Look for combo options following single dash, eat first one if known.\n if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {\n const option = this._findOption(`-${arg[1]}`);\n if (option) {\n if (\n option.required ||\n (option.optional && this._combineFlagAndOptionalValue)\n ) {\n // option with value following in same argument\n this.emit(`option:${option.name()}`, arg.slice(2));\n } else {\n // boolean option\n this.emit(`option:${option.name()}`);\n // remove the processed option and keep processing group\n activeGroup = `-${arg.slice(2)}`;\n }\n continue;\n }\n }\n\n // Look for known long flag with value, like --foo=bar\n if (/^--[^=]+=/.test(arg)) {\n const index = arg.indexOf('=');\n const option = this._findOption(arg.slice(0, index));\n if (option && (option.required || option.optional)) {\n this.emit(`option:${option.name()}`, arg.slice(index + 1));\n continue;\n }\n }\n\n // Not a recognised option by this command.\n // Might be a command-argument, or subcommand option, or unknown option, or help command or option.\n\n // An unknown option means further arguments also classified as unknown so can be reprocessed by subcommands.\n // A negative number in a leaf command is not an unknown option.\n if (\n dest === operands &&\n maybeOption(arg) &&\n !(this.commands.length === 0 && negativeNumberArg(arg))\n ) {\n dest = unknown;\n }\n\n // If using positionalOptions, stop processing our options at subcommand.\n if (\n (this._enablePositionalOptions || this._passThroughOptions) &&\n operands.length === 0 &&\n unknown.length === 0\n ) {\n if (this._findCommand(arg)) {\n operands.push(arg);\n unknown.push(...args.slice(i));\n break;\n } else if (\n this._getHelpCommand() &&\n arg === this._getHelpCommand().name()\n ) {\n operands.push(arg, ...args.slice(i));\n break;\n } else if (this._defaultCommandName) {\n unknown.push(arg, ...args.slice(i));\n break;\n }\n }\n\n // If using passThroughOptions, stop processing options at first command-argument.\n if (this._passThroughOptions) {\n dest.push(arg, ...args.slice(i));\n break;\n }\n\n // add arg\n dest.push(arg);\n }\n\n return { operands, unknown };\n }\n\n /**\n * Return an object containing local option values as key-value pairs.\n *\n * @return {object}\n */\n opts() {\n if (this._storeOptionsAsProperties) {\n // Preserve original behaviour so backwards compatible when still using properties\n const result = {};\n const len = this.options.length;\n\n for (let i = 0; i < len; i++) {\n const key = this.options[i].attributeName();\n result[key] =\n key === this._versionOptionName ? this._version : this[key];\n }\n return result;\n }\n\n return this._optionValues;\n }\n\n /**\n * Return an object containing merged local and global option values as key-value pairs.\n *\n * @return {object}\n */\n optsWithGlobals() {\n // globals overwrite locals\n return this._getCommandAndAncestors().reduce(\n (combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()),\n {},\n );\n }\n\n /**\n * Display error message and exit (or call exitOverride).\n *\n * @param {string} message\n * @param {object} [errorOptions]\n * @param {string} [errorOptions.code] - an id string representing the error\n * @param {number} [errorOptions.exitCode] - used with process.exit\n */\n error(message, errorOptions) {\n // output handling\n this._outputConfiguration.outputError(\n `${message}\\n`,\n this._outputConfiguration.writeErr,\n );\n if (typeof this._showHelpAfterError === 'string') {\n this._outputConfiguration.writeErr(`${this._showHelpAfterError}\\n`);\n } else if (this._showHelpAfterError) {\n this._outputConfiguration.writeErr('\\n');\n this.outputHelp({ error: true });\n }\n\n // exit handling\n const config = errorOptions || {};\n const exitCode = config.exitCode || 1;\n const code = config.code || 'commander.error';\n this._exit(exitCode, code, message);\n }\n\n /**\n * Apply any option related environment variables, if option does\n * not have a value from cli or client code.\n *\n * @private\n */\n _parseOptionsEnv() {\n this.options.forEach((option) => {\n if (option.envVar && option.envVar in process.env) {\n const optionKey = option.attributeName();\n // Priority check. Do not overwrite cli or options from unknown source (client-code).\n if (\n this.getOptionValue(optionKey) === undefined ||\n ['default', 'config', 'env'].includes(\n this.getOptionValueSource(optionKey),\n )\n ) {\n if (option.required || option.optional) {\n // option can take a value\n // keep very simple, optional always takes value\n this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);\n } else {\n // boolean\n // keep very simple, only care that envVar defined and not the value\n this.emit(`optionEnv:${option.name()}`);\n }\n }\n }\n });\n }\n\n /**\n * Apply any implied option values, if option is undefined or default value.\n *\n * @private\n */\n _parseOptionsImplied() {\n const dualHelper = new DualOptions(this.options);\n const hasCustomOptionValue = (optionKey) => {\n return (\n this.getOptionValue(optionKey) !== undefined &&\n !['default', 'implied'].includes(this.getOptionValueSource(optionKey))\n );\n };\n this.options\n .filter(\n (option) =>\n option.implied !== undefined &&\n hasCustomOptionValue(option.attributeName()) &&\n dualHelper.valueFromOption(\n this.getOptionValue(option.attributeName()),\n option,\n ),\n )\n .forEach((option) => {\n Object.keys(option.implied)\n .filter((impliedKey) => !hasCustomOptionValue(impliedKey))\n .forEach((impliedKey) => {\n this.setOptionValueWithSource(\n impliedKey,\n option.implied[impliedKey],\n 'implied',\n );\n });\n });\n }\n\n /**\n * Argument `name` is missing.\n *\n * @param {string} name\n * @private\n */\n\n missingArgument(name) {\n const message = `error: missing required argument '${name}'`;\n this.error(message, { code: 'commander.missingArgument' });\n }\n\n /**\n * `Option` is missing an argument.\n *\n * @param {Option} option\n * @private\n */\n\n optionMissingArgument(option) {\n const message = `error: option '${option.flags}' argument missing`;\n this.error(message, { code: 'commander.optionMissingArgument' });\n }\n\n /**\n * `Option` does not have a value, and is a mandatory option.\n *\n * @param {Option} option\n * @private\n */\n\n missingMandatoryOptionValue(option) {\n const message = `error: required option '${option.flags}' not specified`;\n this.error(message, { code: 'commander.missingMandatoryOptionValue' });\n }\n\n /**\n * `Option` conflicts with another option.\n *\n * @param {Option} option\n * @param {Option} conflictingOption\n * @private\n */\n _conflictingOption(option, conflictingOption) {\n // The calling code does not know whether a negated option is the source of the\n // value, so do some work to take an educated guess.\n const findBestOptionFromValue = (option) => {\n const optionKey = option.attributeName();\n const optionValue = this.getOptionValue(optionKey);\n const negativeOption = this.options.find(\n (target) => target.negate && optionKey === target.attributeName(),\n );\n const positiveOption = this.options.find(\n (target) => !target.negate && optionKey === target.attributeName(),\n );\n if (\n negativeOption &&\n ((negativeOption.presetArg === undefined && optionValue === false) ||\n (negativeOption.presetArg !== undefined &&\n optionValue === negativeOption.presetArg))\n ) {\n return negativeOption;\n }\n return positiveOption || option;\n };\n\n const getErrorMessage = (option) => {\n const bestOption = findBestOptionFromValue(option);\n const optionKey = bestOption.attributeName();\n const source = this.getOptionValueSource(optionKey);\n if (source === 'env') {\n return `environment variable '${bestOption.envVar}'`;\n }\n return `option '${bestOption.flags}'`;\n };\n\n const message = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;\n this.error(message, { code: 'commander.conflictingOption' });\n }\n\n /**\n * Unknown option `flag`.\n *\n * @param {string} flag\n * @private\n */\n\n unknownOption(flag) {\n if (this._allowUnknownOption) return;\n let suggestion = '';\n\n if (flag.startsWith('--') && this._showSuggestionAfterError) {\n // Looping to pick up the global options too\n let candidateFlags = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let command = this;\n do {\n const moreFlags = command\n .createHelp()\n .visibleOptions(command)\n .filter((option) => option.long)\n .map((option) => option.long);\n candidateFlags = candidateFlags.concat(moreFlags);\n command = command.parent;\n } while (command && !command._enablePositionalOptions);\n suggestion = suggestSimilar(flag, candidateFlags);\n }\n\n const message = `error: unknown option '${flag}'${suggestion}`;\n this.error(message, { code: 'commander.unknownOption' });\n }\n\n /**\n * Excess arguments, more than expected.\n *\n * @param {string[]} receivedArgs\n * @private\n */\n\n _excessArguments(receivedArgs) {\n if (this._allowExcessArguments) return;\n\n const expected = this.registeredArguments.length;\n const s = expected === 1 ? '' : 's';\n const received = receivedArgs.length;\n const forSubcommand = this.parent ? ` for '${this.name()}'` : '';\n const details = receivedArgs.join(', ');\n const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${received}: ${details}.`;\n this.error(message, { code: 'commander.excessArguments' });\n }\n\n /**\n * Unknown command.\n *\n * @private\n */\n\n unknownCommand() {\n const unknownName = this.args[0];\n let suggestion = '';\n\n if (this._showSuggestionAfterError) {\n const candidateNames = [];\n this.createHelp()\n .visibleCommands(this)\n .forEach((command) => {\n candidateNames.push(command.name());\n // just visible alias\n if (command.alias()) candidateNames.push(command.alias());\n });\n suggestion = suggestSimilar(unknownName, candidateNames);\n }\n\n const message = `error: unknown command '${unknownName}'${suggestion}`;\n this.error(message, { code: 'commander.unknownCommand' });\n }\n\n /**\n * Get or set the program version.\n *\n * This method auto-registers the \"-V, --version\" option which will print the version number.\n *\n * You can optionally supply the flags and description to override the defaults.\n *\n * @param {string} [str]\n * @param {string} [flags]\n * @param {string} [description]\n * @return {(this | string | undefined)} `this` command for chaining, or version string if no arguments\n */\n\n version(str, flags, description) {\n if (str === undefined) return this._version;\n this._version = str;\n flags = flags || '-V, --version';\n description = description || 'output the version number';\n const versionOption = this.createOption(flags, description);\n this._versionOptionName = versionOption.attributeName();\n this._registerOption(versionOption);\n\n this.on('option:' + versionOption.name(), () => {\n this._outputConfiguration.writeOut(`${str}\\n`);\n this._exit(0, 'commander.version', str);\n });\n return this;\n }\n\n /**\n * Set the description.\n *\n * @param {string} [str]\n * @param {object} [argsDescription]\n * @return {(string|Command)}\n */\n description(str, argsDescription) {\n if (str === undefined && argsDescription === undefined)\n return this._description;\n this._description = str;\n if (argsDescription) {\n this._argsDescription = argsDescription;\n }\n return this;\n }\n\n /**\n * Set the summary. Used when listed as subcommand of parent.\n *\n * @param {string} [str]\n * @return {(string|Command)}\n */\n summary(str) {\n if (str === undefined) return this._summary;\n this._summary = str;\n return this;\n }\n\n /**\n * Set an alias for the command.\n *\n * You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.\n *\n * @param {string} [alias]\n * @return {(string|Command)}\n */\n\n alias(alias) {\n if (alias === undefined) return this._aliases[0]; // just return first, for backwards compatibility\n\n /** @type {Command} */\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let command = this;\n if (\n this.commands.length !== 0 &&\n this.commands[this.commands.length - 1]._executableHandler\n ) {\n // assume adding alias for last added executable subcommand, rather than this\n command = this.commands[this.commands.length - 1];\n }\n\n if (alias === command._name)\n throw new Error(\"Command alias can't be the same as its name\");\n const matchingCommand = this.parent?._findCommand(alias);\n if (matchingCommand) {\n // c.f. _registerCommand\n const existingCmd = [matchingCommand.name()]\n .concat(matchingCommand.aliases())\n .join('|');\n throw new Error(\n `cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`,\n );\n }\n\n command._aliases.push(alias);\n return this;\n }\n\n /**\n * Set aliases for the command.\n *\n * Only the first alias is shown in the auto-generated help.\n *\n * @param {string[]} [aliases]\n * @return {(string[]|Command)}\n */\n\n aliases(aliases) {\n // Getter for the array of aliases is the main reason for having aliases() in addition to alias().\n if (aliases === undefined) return this._aliases;\n\n aliases.forEach((alias) => this.alias(alias));\n return this;\n }\n\n /**\n * Set / get the command usage `str`.\n *\n * @param {string} [str]\n * @return {(string|Command)}\n */\n\n usage(str) {\n if (str === undefined) {\n if (this._usage) return this._usage;\n\n const args = this.registeredArguments.map((arg) => {\n return humanReadableArgName(arg);\n });\n return []\n .concat(\n this.options.length || this._helpOption !== null ? '[options]' : [],\n this.commands.length ? '[command]' : [],\n this.registeredArguments.length ? args : [],\n )\n .join(' ');\n }\n\n this._usage = str;\n return this;\n }\n\n /**\n * Get or set the name of the command.\n *\n * @param {string} [str]\n * @return {(string|Command)}\n */\n\n name(str) {\n if (str === undefined) return this._name;\n this._name = str;\n return this;\n }\n\n /**\n * Set/get the help group heading for this subcommand in parent command's help.\n *\n * @param {string} [heading]\n * @return {Command | string}\n */\n\n helpGroup(heading) {\n if (heading === undefined) return this._helpGroupHeading ?? '';\n this._helpGroupHeading = heading;\n return this;\n }\n\n /**\n * Set/get the default help group heading for subcommands added to this command.\n * (This does not override a group set directly on the subcommand using .helpGroup().)\n *\n * @example\n * program.commandsGroup('Development Commands:);\n * program.command('watch')...\n * program.command('lint')...\n * ...\n *\n * @param {string} [heading]\n * @returns {Command | string}\n */\n commandsGroup(heading) {\n if (heading === undefined) return this._defaultCommandGroup ?? '';\n this._defaultCommandGroup = heading;\n return this;\n }\n\n /**\n * Set/get the default help group heading for options added to this command.\n * (This does not override a group set directly on the option using .helpGroup().)\n *\n * @example\n * program\n * .optionsGroup('Development Options:')\n * .option('-d, --debug', 'output extra debugging')\n * .option('-p, --profile', 'output profiling information')\n *\n * @param {string} [heading]\n * @returns {Command | string}\n */\n optionsGroup(heading) {\n if (heading === undefined) return this._defaultOptionGroup ?? '';\n this._defaultOptionGroup = heading;\n return this;\n }\n\n /**\n * @param {Option} option\n * @private\n */\n _initOptionGroup(option) {\n if (this._defaultOptionGroup && !option.helpGroupHeading)\n option.helpGroup(this._defaultOptionGroup);\n }\n\n /**\n * @param {Command} cmd\n * @private\n */\n _initCommandGroup(cmd) {\n if (this._defaultCommandGroup && !cmd.helpGroup())\n cmd.helpGroup(this._defaultCommandGroup);\n }\n\n /**\n * Set the name of the command from script filename, such as process.argv[1],\n * or import.meta.filename.\n *\n * (Used internally and public although not documented in README.)\n *\n * @example\n * program.nameFromFilename(import.meta.filename);\n *\n * @param {string} filename\n * @return {Command}\n */\n\n nameFromFilename(filename) {\n this._name = path.basename(filename, path.extname(filename));\n\n return this;\n }\n\n /**\n * Get or set the directory for searching for executable subcommands of this command.\n *\n * @example\n * program.executableDir(import.meta.dirname);\n * // or\n * program.executableDir('subcommands');\n *\n * @param {string} [path]\n * @return {(string|null|Command)}\n */\n\n executableDir(path) {\n if (path === undefined) return this._executableDir;\n this._executableDir = path;\n return this;\n }\n\n /**\n * Return program help documentation.\n *\n * @param {{ error: boolean }} [contextOptions] - pass {error:true} to wrap for stderr instead of stdout\n * @return {string}\n */\n\n helpInformation(contextOptions) {\n const helper = this.createHelp();\n const context = this._getOutputContext(contextOptions);\n helper.prepareContext({\n error: context.error,\n helpWidth: context.helpWidth,\n outputHasColors: context.hasColors,\n });\n const text = helper.formatHelp(this, helper);\n if (context.hasColors) return text;\n return this._outputConfiguration.stripColor(text);\n }\n\n /**\n * @typedef HelpContext\n * @type {object}\n * @property {boolean} error\n * @property {number} helpWidth\n * @property {boolean} hasColors\n * @property {function} write - includes stripColor if needed\n *\n * @returns {HelpContext}\n * @private\n */\n\n _getOutputContext(contextOptions) {\n contextOptions = contextOptions || {};\n const error = !!contextOptions.error;\n let baseWrite;\n let hasColors;\n let helpWidth;\n if (error) {\n baseWrite = (str) => this._outputConfiguration.writeErr(str);\n hasColors = this._outputConfiguration.getErrHasColors();\n helpWidth = this._outputConfiguration.getErrHelpWidth();\n } else {\n baseWrite = (str) => this._outputConfiguration.writeOut(str);\n hasColors = this._outputConfiguration.getOutHasColors();\n helpWidth = this._outputConfiguration.getOutHelpWidth();\n }\n const write = (str) => {\n if (!hasColors) str = this._outputConfiguration.stripColor(str);\n return baseWrite(str);\n };\n return { error, write, hasColors, helpWidth };\n }\n\n /**\n * Output help information for this command.\n *\n * Outputs built-in help, and custom text added using `.addHelpText()`.\n *\n * @param {{ error: boolean } | Function} [contextOptions] - pass {error:true} to write to stderr instead of stdout\n */\n\n outputHelp(contextOptions) {\n let deprecatedCallback;\n if (typeof contextOptions === 'function') {\n deprecatedCallback = contextOptions;\n contextOptions = undefined;\n }\n\n const outputContext = this._getOutputContext(contextOptions);\n /** @type {HelpTextEventContext} */\n const eventContext = {\n error: outputContext.error,\n write: outputContext.write,\n command: this,\n };\n\n this._getCommandAndAncestors()\n .reverse()\n .forEach((command) => command.emit('beforeAllHelp', eventContext));\n this.emit('beforeHelp', eventContext);\n\n let helpInformation = this.helpInformation({ error: outputContext.error });\n if (deprecatedCallback) {\n helpInformation = deprecatedCallback(helpInformation);\n if (\n typeof helpInformation !== 'string' &&\n !Buffer.isBuffer(helpInformation)\n ) {\n throw new Error('outputHelp callback must return a string or a Buffer');\n }\n }\n outputContext.write(helpInformation);\n\n if (this._getHelpOption()?.long) {\n this.emit(this._getHelpOption().long); // deprecated\n }\n this.emit('afterHelp', eventContext);\n this._getCommandAndAncestors().forEach((command) =>\n command.emit('afterAllHelp', eventContext),\n );\n }\n\n /**\n * You can pass in flags and a description to customise the built-in help option.\n * Pass in false to disable the built-in help option.\n *\n * @example\n * program.helpOption('-?, --help' 'show help'); // customise\n * program.helpOption(false); // disable\n *\n * @param {(string | boolean)} flags\n * @param {string} [description]\n * @return {Command} `this` command for chaining\n */\n\n helpOption(flags, description) {\n // Support enabling/disabling built-in help option.\n if (typeof flags === 'boolean') {\n if (flags) {\n if (this._helpOption === null) this._helpOption = undefined; // reenable\n if (this._defaultOptionGroup) {\n // make the option to store the group\n this._initOptionGroup(this._getHelpOption());\n }\n } else {\n this._helpOption = null; // disable\n }\n return this;\n }\n\n // Customise flags and description.\n this._helpOption = this.createOption(\n flags ?? '-h, --help',\n description ?? 'display help for command',\n );\n // init group unless lazy create\n if (flags || description) this._initOptionGroup(this._helpOption);\n\n return this;\n }\n\n /**\n * Lazy create help option.\n * Returns null if has been disabled with .helpOption(false).\n *\n * @returns {(Option | null)} the help option\n * @package\n */\n _getHelpOption() {\n // Lazy create help option on demand.\n if (this._helpOption === undefined) {\n this.helpOption(undefined, undefined);\n }\n return this._helpOption;\n }\n\n /**\n * Supply your own option to use for the built-in help option.\n * This is an alternative to using helpOption() to customise the flags and description etc.\n *\n * @param {Option} option\n * @return {Command} `this` command for chaining\n */\n addHelpOption(option) {\n this._helpOption = option;\n this._initOptionGroup(option);\n return this;\n }\n\n /**\n * Output help information and exit.\n *\n * Outputs built-in help, and custom text added using `.addHelpText()`.\n *\n * @param {{ error: boolean }} [contextOptions] - pass {error:true} to write to stderr instead of stdout\n */\n\n help(contextOptions) {\n this.outputHelp(contextOptions);\n let exitCode = Number(process.exitCode ?? 0); // process.exitCode does allow a string or an integer, but we prefer just a number\n if (\n exitCode === 0 &&\n contextOptions &&\n typeof contextOptions !== 'function' &&\n contextOptions.error\n ) {\n exitCode = 1;\n }\n // message: do not have all displayed text available so only passing placeholder.\n this._exit(exitCode, 'commander.help', '(outputHelp)');\n }\n\n /**\n * // Do a little typing to coordinate emit and listener for the help text events.\n * @typedef HelpTextEventContext\n * @type {object}\n * @property {boolean} error\n * @property {Command} command\n * @property {function} write\n */\n\n /**\n * Add additional text to be displayed with the built-in help.\n *\n * Position is 'before' or 'after' to affect just this command,\n * and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.\n *\n * @param {string} position - before or after built-in help\n * @param {(string | Function)} text - string to add, or a function returning a string\n * @return {Command} `this` command for chaining\n */\n\n addHelpText(position, text) {\n const allowedValues = ['beforeAll', 'before', 'after', 'afterAll'];\n if (!allowedValues.includes(position)) {\n throw new Error(`Unexpected value for position to addHelpText.\nExpecting one of '${allowedValues.join(\"', '\")}'`);\n }\n\n const helpEvent = `${position}Help`;\n this.on(helpEvent, (/** @type {HelpTextEventContext} */ context) => {\n let helpStr;\n if (typeof text === 'function') {\n helpStr = text({ error: context.error, command: context.command });\n } else {\n helpStr = text;\n }\n // Ignore falsy value when nothing to output.\n if (helpStr) {\n context.write(`${helpStr}\\n`);\n }\n });\n return this;\n }\n\n /**\n * Output help information if help flags specified\n *\n * @param {Array} args - array of options to search for help flags\n * @private\n */\n\n _outputHelpIfRequested(args) {\n const helpOption = this._getHelpOption();\n const helpRequested = helpOption && args.find((arg) => helpOption.is(arg));\n if (helpRequested) {\n this.outputHelp();\n // (Do not have all displayed text available so only passing placeholder.)\n this._exit(0, 'commander.helpDisplayed', '(outputHelp)');\n }\n }\n}\n\n/**\n * Scan arguments and increment port number for inspect calls (to avoid conflicts when spawning new command).\n *\n * @param {string[]} args - array of arguments from node.execArgv\n * @returns {string[]}\n * @private\n */\n\nfunction incrementNodeInspectorPort(args) {\n // Testing for these options:\n // --inspect[=[host:]port]\n // --inspect-brk[=[host:]port]\n // --inspect-port=[host:]port\n return args.map((arg) => {\n if (!arg.startsWith('--inspect')) {\n return arg;\n }\n let debugOption;\n let debugHost = '127.0.0.1';\n let debugPort = '9229';\n let match;\n if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {\n // e.g. --inspect\n debugOption = match[1];\n } else if (\n (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null\n ) {\n debugOption = match[1];\n if (/^\\d+$/.test(match[3])) {\n // e.g. --inspect=1234\n debugPort = match[3];\n } else {\n // e.g. --inspect=localhost\n debugHost = match[3];\n }\n } else if (\n (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\\d+)$/)) !== null\n ) {\n // e.g. --inspect=localhost:1234\n debugOption = match[1];\n debugHost = match[3];\n debugPort = match[4];\n }\n\n if (debugOption && debugPort !== '0') {\n return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;\n }\n return arg;\n });\n}\n\n/**\n * Exported for using from tests, not otherwise used outside this file.\n *\n * @returns {boolean | undefined}\n * @package\n */\nexport function useColor() {\n // Test for common conventions.\n // NB: the observed behaviour is in combination with how author adds color! For example:\n // - we do not test NODE_DISABLE_COLORS, but util:styletext does\n // - we do test NO_COLOR, but Chalk does not\n //\n // References:\n // https://no-color.org\n // https://bixense.com/clicolors/\n // https://github.com/nodejs/node/blob/0a00217a5f67ef4a22384cfc80eb6dd9a917fdc1/lib/internal/tty.js#L109\n // https://github.com/chalk/supports-color/blob/c214314a14bcb174b12b3014b2b0a8de375029ae/index.js#L33\n // (https://force-color.org recent web page from 2023, does not match major javascript implementations)\n\n if (\n process.env.NO_COLOR ||\n process.env.FORCE_COLOR === '0' ||\n process.env.FORCE_COLOR === 'false'\n )\n return false;\n if (process.env.FORCE_COLOR || process.env.CLICOLOR_FORCE !== undefined)\n return true;\n return undefined;\n}\n", "import { humanReadableArgName } from './argument.js';\nimport { stripVTControlCharacters } from 'node:util';\n\n/**\n * TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`\n * https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types\n * @typedef { import(\"./argument.js\").Argument } Argument\n * @typedef { import(\"./command.js\").Command } Command\n * @typedef { import(\"./option.js\").Option } Option\n */\n\n// Although this is a class, methods are static in style to allow override using subclass or just functions.\nexport class Help {\n constructor() {\n this.helpWidth = undefined;\n this.minWidthToWrap = 40;\n this.sortSubcommands = false;\n this.sortOptions = false;\n this.showGlobalOptions = false;\n }\n\n /**\n * prepareContext is called by Commander after applying overrides from `Command.configureHelp()`\n * and just before calling `formatHelp()`.\n *\n * Commander just uses the helpWidth and the rest is provided for optional use by more complex subclasses.\n *\n * @param {{ error?: boolean, helpWidth?: number, outputHasColors?: boolean }} contextOptions\n */\n prepareContext(contextOptions) {\n this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;\n }\n\n /**\n * Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.\n *\n * @param {Command} cmd\n * @returns {Command[]}\n */\n\n visibleCommands(cmd) {\n const visibleCommands = cmd.commands.filter((cmd) => !cmd._hidden);\n const helpCommand = cmd._getHelpCommand();\n if (helpCommand && !helpCommand._hidden) {\n visibleCommands.push(helpCommand);\n }\n if (this.sortSubcommands) {\n visibleCommands.sort((a, b) => {\n // @ts-ignore: because overloaded return type\n return a.name().localeCompare(b.name());\n });\n }\n return visibleCommands;\n }\n\n /**\n * Compare options for sort.\n *\n * @param {Option} a\n * @param {Option} b\n * @returns {number}\n */\n compareOptions(a, b) {\n const getSortKey = (option) => {\n // WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated.\n return option.short\n ? option.short.replace(/^-/, '')\n : option.long.replace(/^--/, '');\n };\n return getSortKey(a).localeCompare(getSortKey(b));\n }\n\n /**\n * Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.\n *\n * @param {Command} cmd\n * @returns {Option[]}\n */\n\n visibleOptions(cmd) {\n const visibleOptions = cmd.options.filter((option) => !option.hidden);\n // Built-in help option.\n const helpOption = cmd._getHelpOption();\n if (helpOption && !helpOption.hidden) {\n // Automatically hide conflicting flags. Bit dubious but a historical behaviour that is convenient for single-command programs.\n const removeShort = helpOption.short && cmd._findOption(helpOption.short);\n const removeLong = helpOption.long && cmd._findOption(helpOption.long);\n if (!removeShort && !removeLong) {\n visibleOptions.push(helpOption); // no changes needed\n } else if (helpOption.long && !removeLong) {\n visibleOptions.push(\n cmd.createOption(helpOption.long, helpOption.description),\n );\n } else if (helpOption.short && !removeShort) {\n visibleOptions.push(\n cmd.createOption(helpOption.short, helpOption.description),\n );\n }\n }\n if (this.sortOptions) {\n visibleOptions.sort(this.compareOptions);\n }\n return visibleOptions;\n }\n\n /**\n * Get an array of the visible global options. (Not including help.)\n *\n * @param {Command} cmd\n * @returns {Option[]}\n */\n\n visibleGlobalOptions(cmd) {\n if (!this.showGlobalOptions) return [];\n\n const globalOptions = [];\n for (\n let ancestorCmd = cmd.parent;\n ancestorCmd;\n ancestorCmd = ancestorCmd.parent\n ) {\n const visibleOptions = ancestorCmd.options.filter(\n (option) => !option.hidden,\n );\n globalOptions.push(...visibleOptions);\n }\n if (this.sortOptions) {\n globalOptions.sort(this.compareOptions);\n }\n return globalOptions;\n }\n\n /**\n * Get an array of the arguments if any have a description.\n *\n * @param {Command} cmd\n * @returns {Argument[]}\n */\n\n visibleArguments(cmd) {\n // Side effect! Apply the legacy descriptions before the arguments are displayed.\n if (cmd._argsDescription) {\n cmd.registeredArguments.forEach((argument) => {\n argument.description =\n argument.description || cmd._argsDescription[argument.name()] || '';\n });\n }\n\n // If there are any arguments with a description then return all the arguments.\n if (cmd.registeredArguments.find((argument) => argument.description)) {\n return cmd.registeredArguments;\n }\n return [];\n }\n\n /**\n * Get the command term to show in the list of subcommands.\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n subcommandTerm(cmd) {\n // Legacy. Ignores custom usage string, and nested commands.\n const args = cmd.registeredArguments\n .map((arg) => humanReadableArgName(arg))\n .join(' ');\n return (\n cmd._name +\n (cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +\n (cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option\n (args ? ' ' + args : '')\n );\n }\n\n /**\n * Get the option term to show in the list of options.\n *\n * @param {Option} option\n * @returns {string}\n */\n\n optionTerm(option) {\n return option.flags;\n }\n\n /**\n * Get the argument term to show in the list of arguments.\n *\n * @param {Argument} argument\n * @returns {string}\n */\n\n argumentTerm(argument) {\n return argument.name();\n }\n\n /**\n * Get the longest command term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestSubcommandTermLength(cmd, helper) {\n return helper.visibleCommands(cmd).reduce((max, command) => {\n return Math.max(\n max,\n this.displayWidth(\n helper.styleSubcommandTerm(helper.subcommandTerm(command)),\n ),\n );\n }, 0);\n }\n\n /**\n * Get the longest option term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestOptionTermLength(cmd, helper) {\n return helper.visibleOptions(cmd).reduce((max, option) => {\n return Math.max(\n max,\n this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),\n );\n }, 0);\n }\n\n /**\n * Get the longest global option term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestGlobalOptionTermLength(cmd, helper) {\n return helper.visibleGlobalOptions(cmd).reduce((max, option) => {\n return Math.max(\n max,\n this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),\n );\n }, 0);\n }\n\n /**\n * Get the longest argument term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestArgumentTermLength(cmd, helper) {\n return helper.visibleArguments(cmd).reduce((max, argument) => {\n return Math.max(\n max,\n this.displayWidth(\n helper.styleArgumentTerm(helper.argumentTerm(argument)),\n ),\n );\n }, 0);\n }\n\n /**\n * Get the command usage to be displayed at the top of the built-in help.\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n commandUsage(cmd) {\n // Usage\n let cmdName = cmd._name;\n if (cmd._aliases[0]) {\n cmdName = cmdName + '|' + cmd._aliases[0];\n }\n let ancestorCmdNames = '';\n for (\n let ancestorCmd = cmd.parent;\n ancestorCmd;\n ancestorCmd = ancestorCmd.parent\n ) {\n ancestorCmdNames = ancestorCmd.name() + ' ' + ancestorCmdNames;\n }\n return ancestorCmdNames + cmdName + ' ' + cmd.usage();\n }\n\n /**\n * Get the description for the command.\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n commandDescription(cmd) {\n // @ts-ignore: because overloaded return type\n return cmd.description();\n }\n\n /**\n * Get the subcommand summary to show in the list of subcommands.\n * (Fallback to description for backwards compatibility.)\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n subcommandDescription(cmd) {\n // @ts-ignore: because overloaded return type\n return cmd.summary() || cmd.description();\n }\n\n /**\n * Get the option description to show in the list of options.\n *\n * @param {Option} option\n * @return {string}\n */\n\n optionDescription(option) {\n const extraInfo = [];\n\n if (option.argChoices) {\n extraInfo.push(\n // use stringify to match the display of the default value\n `choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,\n );\n }\n if (option.defaultValue !== undefined) {\n // default for boolean and negated more for programmer than end user,\n // but show true/false for boolean option as may be for hand-rolled env or config processing.\n const showDefault =\n option.required ||\n option.optional ||\n (option.isBoolean() && typeof option.defaultValue === 'boolean');\n if (showDefault) {\n extraInfo.push(\n `default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`,\n );\n }\n }\n // preset for boolean and negated are more for programmer than end user\n if (option.presetArg !== undefined && option.optional) {\n extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);\n }\n if (option.envVar !== undefined) {\n extraInfo.push(`env: ${option.envVar}`);\n }\n if (extraInfo.length > 0) {\n const extraDescription = `(${extraInfo.join(', ')})`;\n if (option.description) {\n return `${option.description} ${extraDescription}`;\n }\n return extraDescription;\n }\n\n return option.description;\n }\n\n /**\n * Get the argument description to show in the list of arguments.\n *\n * @param {Argument} argument\n * @return {string}\n */\n\n argumentDescription(argument) {\n const extraInfo = [];\n if (argument.argChoices) {\n extraInfo.push(\n // use stringify to match the display of the default value\n `choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,\n );\n }\n if (argument.defaultValue !== undefined) {\n extraInfo.push(\n `default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`,\n );\n }\n if (extraInfo.length > 0) {\n const extraDescription = `(${extraInfo.join(', ')})`;\n if (argument.description) {\n return `${argument.description} ${extraDescription}`;\n }\n return extraDescription;\n }\n return argument.description;\n }\n\n /**\n * Format a list of items, given a heading and an array of formatted items.\n *\n * @param {string} heading\n * @param {string[]} items\n * @param {Help} helper\n * @returns string[]\n */\n formatItemList(heading, items, helper) {\n if (items.length === 0) return [];\n\n return [helper.styleTitle(heading), ...items, ''];\n }\n\n /**\n * Group items by their help group heading.\n *\n * @param {Command[] | Option[]} unsortedItems\n * @param {Command[] | Option[]} visibleItems\n * @param {Function} getGroup\n * @returns {Map}\n */\n groupItems(unsortedItems, visibleItems, getGroup) {\n const result = new Map();\n // Add groups in order of appearance in unsortedItems.\n unsortedItems.forEach((item) => {\n const group = getGroup(item);\n if (!result.has(group)) result.set(group, []);\n });\n // Add items in order of appearance in visibleItems.\n visibleItems.forEach((item) => {\n const group = getGroup(item);\n if (!result.has(group)) {\n result.set(group, []);\n }\n result.get(group).push(item);\n });\n return result;\n }\n\n /**\n * Generate the built-in help text.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {string}\n */\n\n formatHelp(cmd, helper) {\n const termWidth = helper.padWidth(cmd, helper);\n const helpWidth = helper.helpWidth ?? 80; // in case prepareContext() was not called\n\n function callFormatItem(term, description) {\n return helper.formatItem(term, termWidth, description, helper);\n }\n\n // Usage\n let output = [\n `${helper.styleTitle('Usage:')} ${helper.styleUsage(helper.commandUsage(cmd))}`,\n '',\n ];\n\n // Description\n const commandDescription = helper.commandDescription(cmd);\n if (commandDescription.length > 0) {\n output = output.concat([\n helper.boxWrap(\n helper.styleCommandDescription(commandDescription),\n helpWidth,\n ),\n '',\n ]);\n }\n\n // Arguments\n const argumentList = helper.visibleArguments(cmd).map((argument) => {\n return callFormatItem(\n helper.styleArgumentTerm(helper.argumentTerm(argument)),\n helper.styleArgumentDescription(helper.argumentDescription(argument)),\n );\n });\n output = output.concat(\n this.formatItemList('Arguments:', argumentList, helper),\n );\n\n // Options\n const optionGroups = this.groupItems(\n cmd.options,\n helper.visibleOptions(cmd),\n (option) => option.helpGroupHeading ?? 'Options:',\n );\n optionGroups.forEach((options, group) => {\n const optionList = options.map((option) => {\n return callFormatItem(\n helper.styleOptionTerm(helper.optionTerm(option)),\n helper.styleOptionDescription(helper.optionDescription(option)),\n );\n });\n output = output.concat(this.formatItemList(group, optionList, helper));\n });\n\n if (helper.showGlobalOptions) {\n const globalOptionList = helper\n .visibleGlobalOptions(cmd)\n .map((option) => {\n return callFormatItem(\n helper.styleOptionTerm(helper.optionTerm(option)),\n helper.styleOptionDescription(helper.optionDescription(option)),\n );\n });\n output = output.concat(\n this.formatItemList('Global Options:', globalOptionList, helper),\n );\n }\n\n // Commands\n const commandGroups = this.groupItems(\n cmd.commands,\n helper.visibleCommands(cmd),\n (sub) => sub.helpGroup() || 'Commands:',\n );\n commandGroups.forEach((commands, group) => {\n const commandList = commands.map((sub) => {\n return callFormatItem(\n helper.styleSubcommandTerm(helper.subcommandTerm(sub)),\n helper.styleSubcommandDescription(helper.subcommandDescription(sub)),\n );\n });\n output = output.concat(this.formatItemList(group, commandList, helper));\n });\n\n return output.join('\\n');\n }\n\n /**\n * Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.\n *\n * @param {string} str\n * @returns {number}\n */\n displayWidth(str) {\n return stripVTControlCharacters(str).length;\n }\n\n /**\n * Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.\n *\n * @param {string} str\n * @returns {string}\n */\n styleTitle(str) {\n return str;\n }\n\n styleUsage(str) {\n // Usage has lots of parts the user might like to color separately! Assume default usage string which is formed like:\n // command subcommand [options] [command] [bar]\n return str\n .split(' ')\n .map((word) => {\n if (word === '[options]') return this.styleOptionText(word);\n if (word === '[command]') return this.styleSubcommandText(word);\n if (word[0] === '[' || word[0] === '<')\n return this.styleArgumentText(word);\n return this.styleCommandText(word); // Restrict to initial words?\n })\n .join(' ');\n }\n styleCommandDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleOptionDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleSubcommandDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleArgumentDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleDescriptionText(str) {\n return str;\n }\n styleOptionTerm(str) {\n return this.styleOptionText(str);\n }\n styleSubcommandTerm(str) {\n // This is very like usage with lots of parts! Assume default string which is formed like:\n // subcommand [options] [bar]\n return str\n .split(' ')\n .map((word) => {\n if (word === '[options]') return this.styleOptionText(word);\n if (word[0] === '[' || word[0] === '<')\n return this.styleArgumentText(word);\n return this.styleSubcommandText(word); // Restrict to initial words?\n })\n .join(' ');\n }\n styleArgumentTerm(str) {\n return this.styleArgumentText(str);\n }\n styleOptionText(str) {\n return str;\n }\n styleArgumentText(str) {\n return str;\n }\n styleSubcommandText(str) {\n return str;\n }\n styleCommandText(str) {\n return str;\n }\n\n /**\n * Calculate the pad width from the maximum term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n padWidth(cmd, helper) {\n return Math.max(\n helper.longestOptionTermLength(cmd, helper),\n helper.longestGlobalOptionTermLength(cmd, helper),\n helper.longestSubcommandTermLength(cmd, helper),\n helper.longestArgumentTermLength(cmd, helper),\n );\n }\n\n /**\n * Detect manually wrapped and indented strings by checking for line break followed by whitespace.\n *\n * @param {string} str\n * @returns {boolean}\n */\n preformatted(str) {\n return /\\n[^\\S\\r\\n]/.test(str);\n }\n\n /**\n * Format the \"item\", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.\n *\n * So \"TTT\", 5, \"DDD DDDD DD DDD\" might be formatted for this.helpWidth=17 like so:\n * TTT DDD DDDD\n * DD DDD\n *\n * @param {string} term\n * @param {number} termWidth\n * @param {string} description\n * @param {Help} helper\n * @returns {string}\n */\n formatItem(term, termWidth, description, helper) {\n const itemIndent = 2;\n const itemIndentStr = ' '.repeat(itemIndent);\n if (!description) return itemIndentStr + term;\n\n // Pad the term out to a consistent width, so descriptions are aligned.\n const paddedTerm = term.padEnd(\n termWidth + term.length - helper.displayWidth(term),\n );\n\n // Format the description.\n const spacerWidth = 2; // between term and description\n const helpWidth = this.helpWidth ?? 80; // in case prepareContext() was not called\n const remainingWidth = helpWidth - termWidth - spacerWidth - itemIndent;\n let formattedDescription;\n if (\n remainingWidth < this.minWidthToWrap ||\n helper.preformatted(description)\n ) {\n formattedDescription = description;\n } else {\n const wrappedDescription = helper.boxWrap(description, remainingWidth);\n formattedDescription = wrappedDescription.replace(\n /\\n/g,\n '\\n' + ' '.repeat(termWidth + spacerWidth),\n );\n }\n\n // Construct and overall indent.\n return (\n itemIndentStr +\n paddedTerm +\n ' '.repeat(spacerWidth) +\n formattedDescription.replace(/\\n/g, `\\n${itemIndentStr}`)\n );\n }\n\n /**\n * Wrap a string at whitespace, preserving existing line breaks.\n * Wrapping is skipped if the width is less than `minWidthToWrap`.\n *\n * @param {string} str\n * @param {number} width\n * @returns {string}\n */\n boxWrap(str, width) {\n if (width < this.minWidthToWrap) return str;\n\n const rawLines = str.split(/\\r\\n|\\n/);\n // split up text by whitespace\n const chunkPattern = /[\\s]*[^\\s]+/g;\n const wrappedLines = [];\n rawLines.forEach((line) => {\n const chunks = line.match(chunkPattern);\n if (chunks === null) {\n wrappedLines.push('');\n return;\n }\n\n let sumChunks = [chunks.shift()];\n let sumWidth = this.displayWidth(sumChunks[0]);\n chunks.forEach((chunk) => {\n const visibleWidth = this.displayWidth(chunk);\n // Accumulate chunks while they fit into width.\n if (sumWidth + visibleWidth <= width) {\n sumChunks.push(chunk);\n sumWidth += visibleWidth;\n return;\n }\n wrappedLines.push(sumChunks.join(''));\n\n const nextChunk = chunk.trimStart(); // trim space at line break\n sumChunks = [nextChunk];\n sumWidth = this.displayWidth(nextChunk);\n });\n wrappedLines.push(sumChunks.join(''));\n });\n\n return wrappedLines.join('\\n');\n }\n}\n", "import { InvalidArgumentError } from './error.js';\n\nexport class Option {\n /**\n * Initialize a new `Option` with the given `flags` and `description`.\n *\n * @param {string} flags\n * @param {string} [description]\n */\n\n constructor(flags, description) {\n this.flags = flags;\n this.description = description || '';\n\n this.required = flags.includes('<'); // A value must be supplied when the option is specified.\n this.optional = flags.includes('['); // A value is optional when the option is specified.\n // variadic test ignores et al which might be used to describe custom splitting of single argument\n this.variadic = /\\w\\.\\.\\.[>\\]]$/.test(flags); // The option can take multiple values.\n this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.\n const optionFlags = splitOptionFlags(flags);\n this.short = optionFlags.shortFlag; // May be a short flag, undefined, or even a long flag (if option has two long flags).\n this.long = optionFlags.longFlag;\n this.negate = false;\n if (this.long) {\n this.negate = this.long.startsWith('--no-');\n }\n this.defaultValue = undefined;\n this.defaultValueDescription = undefined;\n this.presetArg = undefined;\n this.envVar = undefined;\n this.parseArg = undefined;\n this.hidden = false;\n this.argChoices = undefined;\n this.conflictsWith = [];\n this.implied = undefined;\n this.helpGroupHeading = undefined; // soft initialised when option added to command\n }\n\n /**\n * Set the default value, and optionally supply the description to be displayed in the help.\n *\n * @param {*} value\n * @param {string} [description]\n * @return {Option}\n */\n\n default(value, description) {\n this.defaultValue = value;\n this.defaultValueDescription = description;\n return this;\n }\n\n /**\n * Preset to use when option used without option-argument, especially optional but also boolean and negated.\n * The custom processing (parseArg) is called.\n *\n * @example\n * new Option('--color').default('GREYSCALE').preset('RGB');\n * new Option('--donate [amount]').preset('20').argParser(parseFloat);\n *\n * @param {*} arg\n * @return {Option}\n */\n\n preset(arg) {\n this.presetArg = arg;\n return this;\n }\n\n /**\n * Add option name(s) that conflict with this option.\n * An error will be displayed if conflicting options are found during parsing.\n *\n * @example\n * new Option('--rgb').conflicts('cmyk');\n * new Option('--js').conflicts(['ts', 'jsx']);\n *\n * @param {(string | string[])} names\n * @return {Option}\n */\n\n conflicts(names) {\n this.conflictsWith = this.conflictsWith.concat(names);\n return this;\n }\n\n /**\n * Specify implied option values for when this option is set and the implied options are not.\n *\n * The custom processing (parseArg) is not called on the implied values.\n *\n * @example\n * program\n * .addOption(new Option('--log', 'write logging information to file'))\n * .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));\n *\n * @param {object} impliedOptionValues\n * @return {Option}\n */\n implies(impliedOptionValues) {\n let newImplied = impliedOptionValues;\n if (typeof impliedOptionValues === 'string') {\n // string is not documented, but easy mistake and we can do what user probably intended.\n newImplied = { [impliedOptionValues]: true };\n }\n this.implied = Object.assign(this.implied || {}, newImplied);\n return this;\n }\n\n /**\n * Set environment variable to check for option value.\n *\n * An environment variable is only used if when processed the current option value is\n * undefined, or the source of the current value is 'default' or 'config' or 'env'.\n *\n * @param {string} name\n * @return {Option}\n */\n\n env(name) {\n this.envVar = name;\n return this;\n }\n\n /**\n * Set the custom handler for processing CLI option arguments into option values.\n *\n * @param {Function} [fn]\n * @return {Option}\n */\n\n argParser(fn) {\n this.parseArg = fn;\n return this;\n }\n\n /**\n * Whether the option is mandatory and must have a value after parsing.\n *\n * @param {boolean} [mandatory=true]\n * @return {Option}\n */\n\n makeOptionMandatory(mandatory = true) {\n this.mandatory = !!mandatory;\n return this;\n }\n\n /**\n * Hide option in help.\n *\n * @param {boolean} [hide=true]\n * @return {Option}\n */\n\n hideHelp(hide = true) {\n this.hidden = !!hide;\n return this;\n }\n\n /**\n * @package\n */\n\n _collectValue(value, previous) {\n if (previous === this.defaultValue || !Array.isArray(previous)) {\n return [value];\n }\n\n previous.push(value);\n return previous;\n }\n\n /**\n * Only allow option value to be one of choices.\n *\n * @param {string[]} values\n * @return {Option}\n */\n\n choices(values) {\n this.argChoices = values.slice();\n this.parseArg = (arg, previous) => {\n if (!this.argChoices.includes(arg)) {\n throw new InvalidArgumentError(\n `Allowed choices are ${this.argChoices.join(', ')}.`,\n );\n }\n if (this.variadic) {\n return this._collectValue(arg, previous);\n }\n return arg;\n };\n return this;\n }\n\n /**\n * Return option name.\n *\n * @return {string}\n */\n\n name() {\n if (this.long) {\n return this.long.replace(/^--/, '');\n }\n return this.short.replace(/^-/, '');\n }\n\n /**\n * Return option name, in a camelcase format that can be used\n * as an object attribute key.\n *\n * @return {string}\n */\n\n attributeName() {\n if (this.negate) {\n return camelcase(this.name().replace(/^no-/, ''));\n }\n return camelcase(this.name());\n }\n\n /**\n * Set the help group heading.\n *\n * @param {string} heading\n * @return {Option}\n */\n helpGroup(heading) {\n this.helpGroupHeading = heading;\n return this;\n }\n\n /**\n * Check if `arg` matches the short or long flag.\n *\n * @param {string} arg\n * @return {boolean}\n * @package\n */\n\n is(arg) {\n return this.short === arg || this.long === arg;\n }\n\n /**\n * Return whether a boolean option.\n *\n * Options are one of boolean, negated, required argument, or optional argument.\n *\n * @return {boolean}\n * @package\n */\n\n isBoolean() {\n return !this.required && !this.optional && !this.negate;\n }\n}\n\n/**\n * This class is to make it easier to work with dual options, without changing the existing\n * implementation. We support separate dual options for separate positive and negative options,\n * like `--build` and `--no-build`, which share a single option value. This works nicely for some\n * use cases, but is tricky for others where we want separate behaviours despite\n * the single shared option value.\n */\nexport class DualOptions {\n /**\n * @param {Option[]} options\n */\n constructor(options) {\n this.positiveOptions = new Map();\n this.negativeOptions = new Map();\n this.dualOptions = new Set();\n options.forEach((option) => {\n if (option.negate) {\n this.negativeOptions.set(option.attributeName(), option);\n } else {\n this.positiveOptions.set(option.attributeName(), option);\n }\n });\n this.negativeOptions.forEach((value, key) => {\n if (this.positiveOptions.has(key)) {\n this.dualOptions.add(key);\n }\n });\n }\n\n /**\n * Did the value come from the option, and not from possible matching dual option?\n *\n * @param {*} value\n * @param {Option} option\n * @returns {boolean}\n */\n valueFromOption(value, option) {\n const optionKey = option.attributeName();\n if (!this.dualOptions.has(optionKey)) return true;\n\n // Use the value to deduce if (probably) came from the option.\n const preset = this.negativeOptions.get(optionKey).presetArg;\n const negativeValue = preset !== undefined ? preset : false;\n return option.negate === (negativeValue === value);\n }\n}\n\n/**\n * Convert string from kebab-case to camelCase.\n *\n * @param {string} str\n * @return {string}\n * @private\n */\n\nfunction camelcase(str) {\n return str.split('-').reduce((str, word) => {\n return str + word[0].toUpperCase() + word.slice(1);\n });\n}\n\n/**\n * Split the short and long flag out of something like '-m,--mixed '\n *\n * @private\n */\n\nfunction splitOptionFlags(flags) {\n let shortFlag;\n let longFlag;\n // short flag, single dash and single character\n const shortFlagExp = /^-[^-]$/;\n // long flag, double dash and at least one character\n const longFlagExp = /^--[^-]/;\n\n const flagParts = flags.split(/[ |,]+/).concat('guard');\n // Normal is short and/or long.\n if (shortFlagExp.test(flagParts[0])) shortFlag = flagParts.shift();\n if (longFlagExp.test(flagParts[0])) longFlag = flagParts.shift();\n // Long then short. Rarely used but fine.\n if (!shortFlag && shortFlagExp.test(flagParts[0]))\n shortFlag = flagParts.shift();\n // Allow two long flags, like '--ws, --workspace'\n // This is the supported way to have a shortish option flag.\n if (!shortFlag && longFlagExp.test(flagParts[0])) {\n shortFlag = longFlag;\n longFlag = flagParts.shift();\n }\n\n // Check for unprocessed flag. Fail noisily rather than silently ignore.\n if (flagParts[0].startsWith('-')) {\n const unsupportedFlag = flagParts[0];\n const baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;\n if (/^-[^-][^-]/.test(unsupportedFlag))\n throw new Error(\n `${baseError}\n- a short flag is a single dash and a single character\n - either use a single dash and a single character (for a short flag)\n - or use a double dash for a long option (and can have two, like '--ws, --workspace')`,\n );\n if (shortFlagExp.test(unsupportedFlag))\n throw new Error(`${baseError}\n- too many short flags`);\n if (longFlagExp.test(unsupportedFlag))\n throw new Error(`${baseError}\n- too many long flags`);\n\n throw new Error(`${baseError}\n- unrecognised flag format`);\n }\n if (shortFlag === undefined && longFlag === undefined)\n throw new Error(\n `option creation failed due to no flags found in '${flags}'.`,\n );\n\n return { shortFlag, longFlag };\n}\n", "const maxDistance = 3;\n\nfunction editDistance(a, b) {\n // https://en.wikipedia.org/wiki/Damerau\u2013Levenshtein_distance\n // Calculating optimal string alignment distance, no substring is edited more than once.\n // (Simple implementation.)\n\n // Quick early exit, return worst case.\n if (Math.abs(a.length - b.length) > maxDistance)\n return Math.max(a.length, b.length);\n\n // distance between prefix substrings of a and b\n const d = [];\n\n // pure deletions turn a into empty string\n for (let i = 0; i <= a.length; i++) {\n d[i] = [i];\n }\n // pure insertions turn empty string into b\n for (let j = 0; j <= b.length; j++) {\n d[0][j] = j;\n }\n\n // fill matrix\n for (let j = 1; j <= b.length; j++) {\n for (let i = 1; i <= a.length; i++) {\n let cost;\n if (a[i - 1] === b[j - 1]) {\n cost = 0;\n } else {\n cost = 1;\n }\n d[i][j] = Math.min(\n d[i - 1][j] + 1, // deletion\n d[i][j - 1] + 1, // insertion\n d[i - 1][j - 1] + cost, // substitution\n );\n // transposition\n if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);\n }\n }\n }\n\n return d[a.length][b.length];\n}\n\n/**\n * Find close matches, restricted to same number of edits.\n *\n * @param {string} word\n * @param {string[]} candidates\n * @returns {string}\n */\n\nexport function suggestSimilar(word, candidates) {\n if (!candidates || candidates.length === 0) return '';\n // remove possible duplicates\n candidates = Array.from(new Set(candidates));\n\n const searchingOptions = word.startsWith('--');\n if (searchingOptions) {\n word = word.slice(2);\n candidates = candidates.map((candidate) => candidate.slice(2));\n }\n\n let similar = [];\n let bestDistance = maxDistance;\n const minSimilarity = 0.4;\n candidates.forEach((candidate) => {\n if (candidate.length <= 1) return; // no one character guesses\n\n const distance = editDistance(word, candidate);\n const length = Math.max(word.length, candidate.length);\n const similarity = (length - distance) / length;\n if (similarity > minSimilarity) {\n if (distance < bestDistance) {\n // better edit distance, throw away previous worse matches\n bestDistance = distance;\n similar = [candidate];\n } else if (distance === bestDistance) {\n similar.push(candidate);\n }\n }\n });\n\n similar.sort((a, b) => a.localeCompare(b));\n if (searchingOptions) {\n similar = similar.map((candidate) => `--${candidate}`);\n }\n\n if (similar.length > 1) {\n return `\\n(Did you mean one of ${similar.join(', ')}?)`;\n }\n if (similar.length === 1) {\n return `\\n(Did you mean ${similar[0]}?)`;\n }\n return '';\n}\n", "import { Argument } from './lib/argument.js';\nimport { Command } from './lib/command.js';\nimport { CommanderError, InvalidArgumentError } from './lib/error.js';\nimport { Help } from './lib/help.js';\nimport { Option } from './lib/option.js';\n\nexport const program = new Command();\n\nexport const createCommand = (name) => new Command(name);\nexport const createOption = (flags, description) =>\n new Option(flags, description);\nexport const createArgument = (name, description) =>\n new Argument(name, description);\n\n/**\n * Expose classes\n */\n\nexport { Command, Option, Argument, Help };\nexport { CommanderError, InvalidArgumentError };\nexport { InvalidArgumentError as InvalidOptionArgumentError }; // Deprecated\n", "// Generated by scripts/generate-bidi-data.ts. Do not edit by hand.\n// Source: https://www.unicode.org/Public/17.0.0/ucd/extracted/DerivedBidiClass.txt\n// SHA-256: 4867b4b7f0731ed1bfcd34cc6251211ff1542541fce0734b6fbda139ee80b3a4\n// Source: https://www.unicode.org/Public/17.0.0/ucd/extracted/DerivedGeneralCategory.txt\n// SHA-256: d62e5bab70ca74f099343f71224fa051cb1fdd61a1ab45c0488c44cfc0b6102e\n\nexport const UNICODE_BIDI_VERSION = '17.0.0';\nexport const UNICODE_BIDI_SHA256 = '4867b4b7f0731ed1bfcd34cc6251211ff1542541fce0734b6fbda139ee80b3a4';\nexport const UNICODE_GENERAL_CATEGORY_SHA256 = 'd62e5bab70ca74f099343f71224fa051cb1fdd61a1ab45c0488c44cfc0b6102e';\n\nexport const RTL_BIDI_RANGES: ReadonlyArray = [\n 0x590, 0x590,\n 0x5be, 0x5be,\n 0x5c0, 0x5c0,\n 0x5c3, 0x5c3,\n 0x5c6, 0x5c6,\n 0x5c8, 0x5ff,\n 0x608, 0x608,\n 0x60b, 0x60b,\n 0x60d, 0x60d,\n 0x61b, 0x64a,\n 0x66d, 0x66f,\n 0x671, 0x6d5,\n 0x6e5, 0x6e6,\n 0x6ee, 0x6ef,\n 0x6fa, 0x710,\n 0x712, 0x72f,\n 0x74b, 0x7a5,\n 0x7b1, 0x7ea,\n 0x7f4, 0x7f5,\n 0x7fa, 0x7fc,\n 0x7fe, 0x815,\n 0x81a, 0x81a,\n 0x824, 0x824,\n 0x828, 0x828,\n 0x82e, 0x858,\n 0x85c, 0x88f,\n 0x892, 0x896,\n 0x8a0, 0x8c9,\n 0x200f, 0x200f,\n 0xfb1d, 0xfb1d,\n 0xfb1f, 0xfb28,\n 0xfb2a, 0xfbc2,\n 0xfbd3, 0xfd3d,\n 0xfd50, 0xfd8f,\n 0xfd92, 0xfdc7,\n 0xfdf0, 0xfdfc,\n 0xfe70, 0xfefe,\n 0x10800, 0x1091e,\n 0x10920, 0x10a00,\n 0x10a04, 0x10a04,\n 0x10a07, 0x10a0b,\n 0x10a10, 0x10a37,\n 0x10a3b, 0x10a3e,\n 0x10a40, 0x10ae4,\n 0x10ae7, 0x10b38,\n 0x10b40, 0x10d23,\n 0x10d28, 0x10d2f,\n 0x10d3a, 0x10d3f,\n 0x10d4a, 0x10d68,\n 0x10d6f, 0x10e5f,\n 0x10e7f, 0x10eaa,\n 0x10ead, 0x10ecf,\n 0x10ed9, 0x10ef9,\n 0x10f00, 0x10f45,\n 0x10f51, 0x10f81,\n 0x10f86, 0x10fff,\n 0x1e800, 0x1e8cf,\n 0x1e8d7, 0x1e943,\n 0x1e94b, 0x1eeef,\n 0x1eef2, 0x1efff\n];\n\nexport const NON_STRONG_BIDI_RANGES: ReadonlyArray = [\n 0x0, 0x40,\n 0x5b, 0x60,\n 0x7b, 0xa9,\n 0xab, 0xb4,\n 0xb6, 0xb9,\n 0xbb, 0xbf,\n 0xd7, 0xd7,\n 0xf7, 0xf7,\n 0x2b9, 0x2ba,\n 0x2c2, 0x2cf,\n 0x2d2, 0x2df,\n 0x2e5, 0x2ed,\n 0x2ef, 0x36f,\n 0x374, 0x375,\n 0x37e, 0x37e,\n 0x384, 0x385,\n 0x387, 0x387,\n 0x3f6, 0x3f6,\n 0x483, 0x489,\n 0x58a, 0x58a,\n 0x58d, 0x58f,\n 0x591, 0x5bd,\n 0x5bf, 0x5bf,\n 0x5c1, 0x5c2,\n 0x5c4, 0x5c5,\n 0x5c7, 0x5c7,\n 0x600, 0x607,\n 0x609, 0x60a,\n 0x60c, 0x60c,\n 0x60e, 0x61a,\n 0x64b, 0x66c,\n 0x670, 0x670,\n 0x6d6, 0x6e4,\n 0x6e7, 0x6ed,\n 0x6f0, 0x6f9,\n 0x711, 0x711,\n 0x730, 0x74a,\n 0x7a6, 0x7b0,\n 0x7eb, 0x7f3,\n 0x7f6, 0x7f9,\n 0x7fd, 0x7fd,\n 0x816, 0x819,\n 0x81b, 0x823,\n 0x825, 0x827,\n 0x829, 0x82d,\n 0x859, 0x85b,\n 0x890, 0x891,\n 0x897, 0x89f,\n 0x8ca, 0x902,\n 0x93a, 0x93a,\n 0x93c, 0x93c,\n 0x941, 0x948,\n 0x94d, 0x94d,\n 0x951, 0x957,\n 0x962, 0x963,\n 0x981, 0x981,\n 0x9bc, 0x9bc,\n 0x9c1, 0x9c4,\n 0x9cd, 0x9cd,\n 0x9e2, 0x9e3,\n 0x9f2, 0x9f3,\n 0x9fb, 0x9fb,\n 0x9fe, 0x9fe,\n 0xa01, 0xa02,\n 0xa3c, 0xa3c,\n 0xa41, 0xa42,\n 0xa47, 0xa48,\n 0xa4b, 0xa4d,\n 0xa51, 0xa51,\n 0xa70, 0xa71,\n 0xa75, 0xa75,\n 0xa81, 0xa82,\n 0xabc, 0xabc,\n 0xac1, 0xac5,\n 0xac7, 0xac8,\n 0xacd, 0xacd,\n 0xae2, 0xae3,\n 0xaf1, 0xaf1,\n 0xafa, 0xaff,\n 0xb01, 0xb01,\n 0xb3c, 0xb3c,\n 0xb3f, 0xb3f,\n 0xb41, 0xb44,\n 0xb4d, 0xb4d,\n 0xb55, 0xb56,\n 0xb62, 0xb63,\n 0xb82, 0xb82,\n 0xbc0, 0xbc0,\n 0xbcd, 0xbcd,\n 0xbf3, 0xbfa,\n 0xc00, 0xc00,\n 0xc04, 0xc04,\n 0xc3c, 0xc3c,\n 0xc3e, 0xc40,\n 0xc46, 0xc48,\n 0xc4a, 0xc4d,\n 0xc55, 0xc56,\n 0xc62, 0xc63,\n 0xc78, 0xc7e,\n 0xc81, 0xc81,\n 0xcbc, 0xcbc,\n 0xccc, 0xccd,\n 0xce2, 0xce3,\n 0xd00, 0xd01,\n 0xd3b, 0xd3c,\n 0xd41, 0xd44,\n 0xd4d, 0xd4d,\n 0xd62, 0xd63,\n 0xd81, 0xd81,\n 0xdca, 0xdca,\n 0xdd2, 0xdd4,\n 0xdd6, 0xdd6,\n 0xe31, 0xe31,\n 0xe34, 0xe3a,\n 0xe3f, 0xe3f,\n 0xe47, 0xe4e,\n 0xeb1, 0xeb1,\n 0xeb4, 0xebc,\n 0xec8, 0xece,\n 0xf18, 0xf19,\n 0xf35, 0xf35,\n 0xf37, 0xf37,\n 0xf39, 0xf3d,\n 0xf71, 0xf7e,\n 0xf80, 0xf84,\n 0xf86, 0xf87,\n 0xf8d, 0xf97,\n 0xf99, 0xfbc,\n 0xfc6, 0xfc6,\n 0x102d, 0x1030,\n 0x1032, 0x1037,\n 0x1039, 0x103a,\n 0x103d, 0x103e,\n 0x1058, 0x1059,\n 0x105e, 0x1060,\n 0x1071, 0x1074,\n 0x1082, 0x1082,\n 0x1085, 0x1086,\n 0x108d, 0x108d,\n 0x109d, 0x109d,\n 0x135d, 0x135f,\n 0x1390, 0x1399,\n 0x1400, 0x1400,\n 0x1680, 0x1680,\n 0x169b, 0x169c,\n 0x1712, 0x1714,\n 0x1732, 0x1733,\n 0x1752, 0x1753,\n 0x1772, 0x1773,\n 0x17b4, 0x17b5,\n 0x17b7, 0x17bd,\n 0x17c6, 0x17c6,\n 0x17c9, 0x17d3,\n 0x17db, 0x17db,\n 0x17dd, 0x17dd,\n 0x17f0, 0x17f9,\n 0x1800, 0x180f,\n 0x1885, 0x1886,\n 0x18a9, 0x18a9,\n 0x1920, 0x1922,\n 0x1927, 0x1928,\n 0x1932, 0x1932,\n 0x1939, 0x193b,\n 0x1940, 0x1940,\n 0x1944, 0x1945,\n 0x19de, 0x19ff,\n 0x1a17, 0x1a18,\n 0x1a1b, 0x1a1b,\n 0x1a56, 0x1a56,\n 0x1a58, 0x1a5e,\n 0x1a60, 0x1a60,\n 0x1a62, 0x1a62,\n 0x1a65, 0x1a6c,\n 0x1a73, 0x1a7c,\n 0x1a7f, 0x1a7f,\n 0x1ab0, 0x1add,\n 0x1ae0, 0x1aeb,\n 0x1b00, 0x1b03,\n 0x1b34, 0x1b34,\n 0x1b36, 0x1b3a,\n 0x1b3c, 0x1b3c,\n 0x1b42, 0x1b42,\n 0x1b6b, 0x1b73,\n 0x1b80, 0x1b81,\n 0x1ba2, 0x1ba5,\n 0x1ba8, 0x1ba9,\n 0x1bab, 0x1bad,\n 0x1be6, 0x1be6,\n 0x1be8, 0x1be9,\n 0x1bed, 0x1bed,\n 0x1bef, 0x1bf1,\n 0x1c2c, 0x1c33,\n 0x1c36, 0x1c37,\n 0x1cd0, 0x1cd2,\n 0x1cd4, 0x1ce0,\n 0x1ce2, 0x1ce8,\n 0x1ced, 0x1ced,\n 0x1cf4, 0x1cf4,\n 0x1cf8, 0x1cf9,\n 0x1dc0, 0x1dff,\n 0x1fbd, 0x1fbd,\n 0x1fbf, 0x1fc1,\n 0x1fcd, 0x1fcf,\n 0x1fdd, 0x1fdf,\n 0x1fed, 0x1fef,\n 0x1ffd, 0x1ffe,\n 0x2000, 0x200d,\n 0x2010, 0x2070,\n 0x2074, 0x207e,\n 0x2080, 0x208e,\n 0x20a0, 0x20f0,\n 0x2100, 0x2101,\n 0x2103, 0x2106,\n 0x2108, 0x2109,\n 0x2114, 0x2114,\n 0x2116, 0x2118,\n 0x211e, 0x2123,\n 0x2125, 0x2125,\n 0x2127, 0x2127,\n 0x2129, 0x2129,\n 0x212e, 0x212e,\n 0x213a, 0x213b,\n 0x2140, 0x2144,\n 0x214a, 0x214d,\n 0x2150, 0x215f,\n 0x2189, 0x218b,\n 0x2190, 0x2335,\n 0x237b, 0x2394,\n 0x2396, 0x2429,\n 0x2440, 0x244a,\n 0x2460, 0x249b,\n 0x24ea, 0x26ab,\n 0x26ad, 0x27ff,\n 0x2900, 0x2b73,\n 0x2b76, 0x2bff,\n 0x2ce5, 0x2cea,\n 0x2cef, 0x2cf1,\n 0x2cf9, 0x2cff,\n 0x2d7f, 0x2d7f,\n 0x2de0, 0x2e5d,\n 0x2e80, 0x2e99,\n 0x2e9b, 0x2ef3,\n 0x2f00, 0x2fd5,\n 0x2ff0, 0x3004,\n 0x3008, 0x3020,\n 0x302a, 0x302d,\n 0x3030, 0x3030,\n 0x3036, 0x3037,\n 0x303d, 0x303f,\n 0x3099, 0x309c,\n 0x30a0, 0x30a0,\n 0x30fb, 0x30fb,\n 0x31c0, 0x31e5,\n 0x31ef, 0x31ef,\n 0x321d, 0x321e,\n 0x3250, 0x325f,\n 0x327c, 0x327e,\n 0x32b1, 0x32bf,\n 0x32cc, 0x32cf,\n 0x3377, 0x337a,\n 0x33de, 0x33df,\n 0x33ff, 0x33ff,\n 0x4dc0, 0x4dff,\n 0xa490, 0xa4c6,\n 0xa60d, 0xa60f,\n 0xa66f, 0xa67f,\n 0xa69e, 0xa69f,\n 0xa6f0, 0xa6f1,\n 0xa700, 0xa721,\n 0xa788, 0xa788,\n 0xa802, 0xa802,\n 0xa806, 0xa806,\n 0xa80b, 0xa80b,\n 0xa825, 0xa826,\n 0xa828, 0xa82c,\n 0xa838, 0xa839,\n 0xa874, 0xa877,\n 0xa8c4, 0xa8c5,\n 0xa8e0, 0xa8f1,\n 0xa8ff, 0xa8ff,\n 0xa926, 0xa92d,\n 0xa947, 0xa951,\n 0xa980, 0xa982,\n 0xa9b3, 0xa9b3,\n 0xa9b6, 0xa9b9,\n 0xa9bc, 0xa9bd,\n 0xa9e5, 0xa9e5,\n 0xaa29, 0xaa2e,\n 0xaa31, 0xaa32,\n 0xaa35, 0xaa36,\n 0xaa43, 0xaa43,\n 0xaa4c, 0xaa4c,\n 0xaa7c, 0xaa7c,\n 0xaab0, 0xaab0,\n 0xaab2, 0xaab4,\n 0xaab7, 0xaab8,\n 0xaabe, 0xaabf,\n 0xaac1, 0xaac1,\n 0xaaec, 0xaaed,\n 0xaaf6, 0xaaf6,\n 0xab6a, 0xab6b,\n 0xabe5, 0xabe5,\n 0xabe8, 0xabe8,\n 0xabed, 0xabed,\n 0xfb1e, 0xfb1e,\n 0xfb29, 0xfb29,\n 0xfbc3, 0xfbd2,\n 0xfd3e, 0xfd4f,\n 0xfd90, 0xfd91,\n 0xfdc8, 0xfdef,\n 0xfdfd, 0xfe19,\n 0xfe20, 0xfe52,\n 0xfe54, 0xfe66,\n 0xfe68, 0xfe6b,\n 0xfeff, 0xfeff,\n 0xff01, 0xff20,\n 0xff3b, 0xff40,\n 0xff5b, 0xff65,\n 0xffe0, 0xffe6,\n 0xffe8, 0xffee,\n 0xfff0, 0xffff,\n 0x10101, 0x10101,\n 0x10140, 0x1018c,\n 0x10190, 0x1019c,\n 0x101a0, 0x101a0,\n 0x101fd, 0x101fd,\n 0x102e0, 0x102fb,\n 0x10376, 0x1037a,\n 0x1091f, 0x1091f,\n 0x10a01, 0x10a03,\n 0x10a05, 0x10a06,\n 0x10a0c, 0x10a0f,\n 0x10a38, 0x10a3a,\n 0x10a3f, 0x10a3f,\n 0x10ae5, 0x10ae6,\n 0x10b39, 0x10b3f,\n 0x10d24, 0x10d27,\n 0x10d30, 0x10d39,\n 0x10d40, 0x10d49,\n 0x10d69, 0x10d6e,\n 0x10e60, 0x10e7e,\n 0x10eab, 0x10eac,\n 0x10ed0, 0x10ed8,\n 0x10efa, 0x10eff,\n 0x10f46, 0x10f50,\n 0x10f82, 0x10f85,\n 0x11001, 0x11001,\n 0x11038, 0x11046,\n 0x11052, 0x11065,\n 0x11070, 0x11070,\n 0x11073, 0x11074,\n 0x1107f, 0x11081,\n 0x110b3, 0x110b6,\n 0x110b9, 0x110ba,\n 0x110c2, 0x110c2,\n 0x11100, 0x11102,\n 0x11127, 0x1112b,\n 0x1112d, 0x11134,\n 0x11173, 0x11173,\n 0x11180, 0x11181,\n 0x111b6, 0x111be,\n 0x111c9, 0x111cc,\n 0x111cf, 0x111cf,\n 0x1122f, 0x11231,\n 0x11234, 0x11234,\n 0x11236, 0x11237,\n 0x1123e, 0x1123e,\n 0x11241, 0x11241,\n 0x112df, 0x112df,\n 0x112e3, 0x112ea,\n 0x11300, 0x11301,\n 0x1133b, 0x1133c,\n 0x11340, 0x11340,\n 0x11366, 0x1136c,\n 0x11370, 0x11374,\n 0x113bb, 0x113c0,\n 0x113ce, 0x113ce,\n 0x113d0, 0x113d0,\n 0x113d2, 0x113d2,\n 0x113e1, 0x113e2,\n 0x11438, 0x1143f,\n 0x11442, 0x11444,\n 0x11446, 0x11446,\n 0x1145e, 0x1145e,\n 0x114b3, 0x114b8,\n 0x114ba, 0x114ba,\n 0x114bf, 0x114c0,\n 0x114c2, 0x114c3,\n 0x115b2, 0x115b5,\n 0x115bc, 0x115bd,\n 0x115bf, 0x115c0,\n 0x115dc, 0x115dd,\n 0x11633, 0x1163a,\n 0x1163d, 0x1163d,\n 0x1163f, 0x11640,\n 0x11660, 0x1166c,\n 0x116ab, 0x116ab,\n 0x116ad, 0x116ad,\n 0x116b0, 0x116b5,\n 0x116b7, 0x116b7,\n 0x1171d, 0x1171d,\n 0x1171f, 0x1171f,\n 0x11722, 0x11725,\n 0x11727, 0x1172b,\n 0x1182f, 0x11837,\n 0x11839, 0x1183a,\n 0x1193b, 0x1193c,\n 0x1193e, 0x1193e,\n 0x11943, 0x11943,\n 0x119d4, 0x119d7,\n 0x119da, 0x119db,\n 0x119e0, 0x119e0,\n 0x11a01, 0x11a06,\n 0x11a09, 0x11a0a,\n 0x11a33, 0x11a38,\n 0x11a3b, 0x11a3e,\n 0x11a47, 0x11a47,\n 0x11a51, 0x11a56,\n 0x11a59, 0x11a5b,\n 0x11a8a, 0x11a96,\n 0x11a98, 0x11a99,\n 0x11b60, 0x11b60,\n 0x11b62, 0x11b64,\n 0x11b66, 0x11b66,\n 0x11c30, 0x11c36,\n 0x11c38, 0x11c3d,\n 0x11c92, 0x11ca7,\n 0x11caa, 0x11cb0,\n 0x11cb2, 0x11cb3,\n 0x11cb5, 0x11cb6,\n 0x11d31, 0x11d36,\n 0x11d3a, 0x11d3a,\n 0x11d3c, 0x11d3d,\n 0x11d3f, 0x11d45,\n 0x11d47, 0x11d47,\n 0x11d90, 0x11d91,\n 0x11d95, 0x11d95,\n 0x11d97, 0x11d97,\n 0x11ef3, 0x11ef4,\n 0x11f00, 0x11f01,\n 0x11f36, 0x11f3a,\n 0x11f40, 0x11f40,\n 0x11f42, 0x11f42,\n 0x11f5a, 0x11f5a,\n 0x11fd5, 0x11ff1,\n 0x13440, 0x13440,\n 0x13447, 0x13455,\n 0x1611e, 0x16129,\n 0x1612d, 0x1612f,\n 0x16af0, 0x16af4,\n 0x16b30, 0x16b36,\n 0x16f4f, 0x16f4f,\n 0x16f8f, 0x16f92,\n 0x16fe2, 0x16fe2,\n 0x16fe4, 0x16fe4,\n 0x1bc9d, 0x1bc9e,\n 0x1bca0, 0x1bca3,\n 0x1cc00, 0x1ccd5,\n 0x1ccf0, 0x1ccfc,\n 0x1cd00, 0x1ceb3,\n 0x1ceba, 0x1ced0,\n 0x1cee0, 0x1cef0,\n 0x1cf00, 0x1cf2d,\n 0x1cf30, 0x1cf46,\n 0x1d167, 0x1d169,\n 0x1d173, 0x1d182,\n 0x1d185, 0x1d18b,\n 0x1d1aa, 0x1d1ad,\n 0x1d1e9, 0x1d1ea,\n 0x1d200, 0x1d245,\n 0x1d300, 0x1d356,\n 0x1d6c1, 0x1d6c1,\n 0x1d6db, 0x1d6db,\n 0x1d6fb, 0x1d6fb,\n 0x1d715, 0x1d715,\n 0x1d735, 0x1d735,\n 0x1d74f, 0x1d74f,\n 0x1d76f, 0x1d76f,\n 0x1d789, 0x1d789,\n 0x1d7a9, 0x1d7a9,\n 0x1d7c3, 0x1d7c3,\n 0x1d7ce, 0x1d7ff,\n 0x1da00, 0x1da36,\n 0x1da3b, 0x1da6c,\n 0x1da75, 0x1da75,\n 0x1da84, 0x1da84,\n 0x1da9b, 0x1da9f,\n 0x1daa1, 0x1daaf,\n 0x1e000, 0x1e006,\n 0x1e008, 0x1e018,\n 0x1e01b, 0x1e021,\n 0x1e023, 0x1e024,\n 0x1e026, 0x1e02a,\n 0x1e08f, 0x1e08f,\n 0x1e130, 0x1e136,\n 0x1e2ae, 0x1e2ae,\n 0x1e2ec, 0x1e2ef,\n 0x1e2ff, 0x1e2ff,\n 0x1e4ec, 0x1e4ef,\n 0x1e5ee, 0x1e5ef,\n 0x1e6e3, 0x1e6e3,\n 0x1e6e6, 0x1e6e6,\n 0x1e6ee, 0x1e6ef,\n 0x1e6f5, 0x1e6f5,\n 0x1e8d0, 0x1e8d6,\n 0x1e944, 0x1e94a,\n 0x1eef0, 0x1eef1,\n 0x1f000, 0x1f02b,\n 0x1f030, 0x1f093,\n 0x1f0a0, 0x1f0ae,\n 0x1f0b1, 0x1f0bf,\n 0x1f0c1, 0x1f0cf,\n 0x1f0d1, 0x1f0f5,\n 0x1f100, 0x1f10f,\n 0x1f12f, 0x1f12f,\n 0x1f16a, 0x1f16f,\n 0x1f1ad, 0x1f1ad,\n 0x1f260, 0x1f265,\n 0x1f300, 0x1f6d8,\n 0x1f6dc, 0x1f6ec,\n 0x1f6f0, 0x1f6fc,\n 0x1f700, 0x1f7d9,\n 0x1f7e0, 0x1f7eb,\n 0x1f7f0, 0x1f7f0,\n 0x1f800, 0x1f80b,\n 0x1f810, 0x1f847,\n 0x1f850, 0x1f859,\n 0x1f860, 0x1f887,\n 0x1f890, 0x1f8ad,\n 0x1f8b0, 0x1f8bb,\n 0x1f8c0, 0x1f8c1,\n 0x1f8d0, 0x1f8d8,\n 0x1f900, 0x1fa57,\n 0x1fa60, 0x1fa6d,\n 0x1fa70, 0x1fa7c,\n 0x1fa80, 0x1fa8a,\n 0x1fa8e, 0x1fac6,\n 0x1fac8, 0x1fac8,\n 0x1facd, 0x1fadc,\n 0x1fadf, 0x1faea,\n 0x1faef, 0x1faf8,\n 0x1fb00, 0x1fb92,\n 0x1fb94, 0x1fbfa,\n 0x1fffe, 0x1ffff,\n 0x2fffe, 0x2ffff,\n 0x3fffe, 0x3ffff,\n 0x4fffe, 0x4ffff,\n 0x5fffe, 0x5ffff,\n 0x6fffe, 0x6ffff,\n 0x7fffe, 0x7ffff,\n 0x8fffe, 0x8ffff,\n 0x9fffe, 0x9ffff,\n 0xafffe, 0xaffff,\n 0xbfffe, 0xbffff,\n 0xcfffe, 0xcffff,\n 0xdfffe, 0xe0fff,\n 0xefffe, 0xeffff,\n 0xffffe, 0xfffff,\n 0x10fffe, 0x10ffff\n];\n\nexport const NATURAL_LETTER_RANGES: ReadonlyArray = [\n 0x41, 0x5a,\n 0x61, 0x7a,\n 0xaa, 0xaa,\n 0xb5, 0xb5,\n 0xba, 0xba,\n 0xc0, 0xd6,\n 0xd8, 0xf6,\n 0xf8, 0x2c1,\n 0x2c6, 0x2d1,\n 0x2e0, 0x2e4,\n 0x2ec, 0x2ec,\n 0x2ee, 0x2ee,\n 0x370, 0x374,\n 0x376, 0x377,\n 0x37a, 0x37d,\n 0x37f, 0x37f,\n 0x386, 0x386,\n 0x388, 0x38a,\n 0x38c, 0x38c,\n 0x38e, 0x3a1,\n 0x3a3, 0x3f5,\n 0x3f7, 0x481,\n 0x48a, 0x52f,\n 0x531, 0x556,\n 0x559, 0x559,\n 0x560, 0x588,\n 0x5d0, 0x5ea,\n 0x5ef, 0x5f2,\n 0x620, 0x64a,\n 0x66e, 0x66f,\n 0x671, 0x6d3,\n 0x6d5, 0x6d5,\n 0x6e5, 0x6e6,\n 0x6ee, 0x6ef,\n 0x6fa, 0x6fc,\n 0x6ff, 0x6ff,\n 0x710, 0x710,\n 0x712, 0x72f,\n 0x74d, 0x7a5,\n 0x7b1, 0x7b1,\n 0x7ca, 0x7ea,\n 0x7f4, 0x7f5,\n 0x7fa, 0x7fa,\n 0x800, 0x815,\n 0x81a, 0x81a,\n 0x824, 0x824,\n 0x828, 0x828,\n 0x840, 0x858,\n 0x860, 0x86a,\n 0x870, 0x887,\n 0x889, 0x88f,\n 0x8a0, 0x8c9,\n 0x904, 0x939,\n 0x93d, 0x93d,\n 0x950, 0x950,\n 0x958, 0x961,\n 0x971, 0x980,\n 0x985, 0x98c,\n 0x98f, 0x990,\n 0x993, 0x9a8,\n 0x9aa, 0x9b0,\n 0x9b2, 0x9b2,\n 0x9b6, 0x9b9,\n 0x9bd, 0x9bd,\n 0x9ce, 0x9ce,\n 0x9dc, 0x9dd,\n 0x9df, 0x9e1,\n 0x9f0, 0x9f1,\n 0x9fc, 0x9fc,\n 0xa05, 0xa0a,\n 0xa0f, 0xa10,\n 0xa13, 0xa28,\n 0xa2a, 0xa30,\n 0xa32, 0xa33,\n 0xa35, 0xa36,\n 0xa38, 0xa39,\n 0xa59, 0xa5c,\n 0xa5e, 0xa5e,\n 0xa72, 0xa74,\n 0xa85, 0xa8d,\n 0xa8f, 0xa91,\n 0xa93, 0xaa8,\n 0xaaa, 0xab0,\n 0xab2, 0xab3,\n 0xab5, 0xab9,\n 0xabd, 0xabd,\n 0xad0, 0xad0,\n 0xae0, 0xae1,\n 0xaf9, 0xaf9,\n 0xb05, 0xb0c,\n 0xb0f, 0xb10,\n 0xb13, 0xb28,\n 0xb2a, 0xb30,\n 0xb32, 0xb33,\n 0xb35, 0xb39,\n 0xb3d, 0xb3d,\n 0xb5c, 0xb5d,\n 0xb5f, 0xb61,\n 0xb71, 0xb71,\n 0xb83, 0xb83,\n 0xb85, 0xb8a,\n 0xb8e, 0xb90,\n 0xb92, 0xb95,\n 0xb99, 0xb9a,\n 0xb9c, 0xb9c,\n 0xb9e, 0xb9f,\n 0xba3, 0xba4,\n 0xba8, 0xbaa,\n 0xbae, 0xbb9,\n 0xbd0, 0xbd0,\n 0xc05, 0xc0c,\n 0xc0e, 0xc10,\n 0xc12, 0xc28,\n 0xc2a, 0xc39,\n 0xc3d, 0xc3d,\n 0xc58, 0xc5a,\n 0xc5c, 0xc5d,\n 0xc60, 0xc61,\n 0xc80, 0xc80,\n 0xc85, 0xc8c,\n 0xc8e, 0xc90,\n 0xc92, 0xca8,\n 0xcaa, 0xcb3,\n 0xcb5, 0xcb9,\n 0xcbd, 0xcbd,\n 0xcdc, 0xcde,\n 0xce0, 0xce1,\n 0xcf1, 0xcf2,\n 0xd04, 0xd0c,\n 0xd0e, 0xd10,\n 0xd12, 0xd3a,\n 0xd3d, 0xd3d,\n 0xd4e, 0xd4e,\n 0xd54, 0xd56,\n 0xd5f, 0xd61,\n 0xd7a, 0xd7f,\n 0xd85, 0xd96,\n 0xd9a, 0xdb1,\n 0xdb3, 0xdbb,\n 0xdbd, 0xdbd,\n 0xdc0, 0xdc6,\n 0xe01, 0xe30,\n 0xe32, 0xe33,\n 0xe40, 0xe46,\n 0xe81, 0xe82,\n 0xe84, 0xe84,\n 0xe86, 0xe8a,\n 0xe8c, 0xea3,\n 0xea5, 0xea5,\n 0xea7, 0xeb0,\n 0xeb2, 0xeb3,\n 0xebd, 0xebd,\n 0xec0, 0xec4,\n 0xec6, 0xec6,\n 0xedc, 0xedf,\n 0xf00, 0xf00,\n 0xf40, 0xf47,\n 0xf49, 0xf6c,\n 0xf88, 0xf8c,\n 0x1000, 0x102a,\n 0x103f, 0x103f,\n 0x1050, 0x1055,\n 0x105a, 0x105d,\n 0x1061, 0x1061,\n 0x1065, 0x1066,\n 0x106e, 0x1070,\n 0x1075, 0x1081,\n 0x108e, 0x108e,\n 0x10a0, 0x10c5,\n 0x10c7, 0x10c7,\n 0x10cd, 0x10cd,\n 0x10d0, 0x10fa,\n 0x10fc, 0x1248,\n 0x124a, 0x124d,\n 0x1250, 0x1256,\n 0x1258, 0x1258,\n 0x125a, 0x125d,\n 0x1260, 0x1288,\n 0x128a, 0x128d,\n 0x1290, 0x12b0,\n 0x12b2, 0x12b5,\n 0x12b8, 0x12be,\n 0x12c0, 0x12c0,\n 0x12c2, 0x12c5,\n 0x12c8, 0x12d6,\n 0x12d8, 0x1310,\n 0x1312, 0x1315,\n 0x1318, 0x135a,\n 0x1380, 0x138f,\n 0x13a0, 0x13f5,\n 0x13f8, 0x13fd,\n 0x1401, 0x166c,\n 0x166f, 0x167f,\n 0x1681, 0x169a,\n 0x16a0, 0x16ea,\n 0x16f1, 0x16f8,\n 0x1700, 0x1711,\n 0x171f, 0x1731,\n 0x1740, 0x1751,\n 0x1760, 0x176c,\n 0x176e, 0x1770,\n 0x1780, 0x17b3,\n 0x17d7, 0x17d7,\n 0x17dc, 0x17dc,\n 0x1820, 0x1878,\n 0x1880, 0x1884,\n 0x1887, 0x18a8,\n 0x18aa, 0x18aa,\n 0x18b0, 0x18f5,\n 0x1900, 0x191e,\n 0x1950, 0x196d,\n 0x1970, 0x1974,\n 0x1980, 0x19ab,\n 0x19b0, 0x19c9,\n 0x1a00, 0x1a16,\n 0x1a20, 0x1a54,\n 0x1aa7, 0x1aa7,\n 0x1b05, 0x1b33,\n 0x1b45, 0x1b4c,\n 0x1b83, 0x1ba0,\n 0x1bae, 0x1baf,\n 0x1bba, 0x1be5,\n 0x1c00, 0x1c23,\n 0x1c4d, 0x1c4f,\n 0x1c5a, 0x1c7d,\n 0x1c80, 0x1c8a,\n 0x1c90, 0x1cba,\n 0x1cbd, 0x1cbf,\n 0x1ce9, 0x1cec,\n 0x1cee, 0x1cf3,\n 0x1cf5, 0x1cf6,\n 0x1cfa, 0x1cfa,\n 0x1d00, 0x1dbf,\n 0x1e00, 0x1f15,\n 0x1f18, 0x1f1d,\n 0x1f20, 0x1f45,\n 0x1f48, 0x1f4d,\n 0x1f50, 0x1f57,\n 0x1f59, 0x1f59,\n 0x1f5b, 0x1f5b,\n 0x1f5d, 0x1f5d,\n 0x1f5f, 0x1f7d,\n 0x1f80, 0x1fb4,\n 0x1fb6, 0x1fbc,\n 0x1fbe, 0x1fbe,\n 0x1fc2, 0x1fc4,\n 0x1fc6, 0x1fcc,\n 0x1fd0, 0x1fd3,\n 0x1fd6, 0x1fdb,\n 0x1fe0, 0x1fec,\n 0x1ff2, 0x1ff4,\n 0x1ff6, 0x1ffc,\n 0x2071, 0x2071,\n 0x207f, 0x207f,\n 0x2090, 0x209c,\n 0x2102, 0x2102,\n 0x2107, 0x2107,\n 0x210a, 0x2113,\n 0x2115, 0x2115,\n 0x2119, 0x211d,\n 0x2124, 0x2124,\n 0x2126, 0x2126,\n 0x2128, 0x2128,\n 0x212a, 0x212d,\n 0x212f, 0x2139,\n 0x213c, 0x213f,\n 0x2145, 0x2149,\n 0x214e, 0x214e,\n 0x2183, 0x2184,\n 0x2c00, 0x2ce4,\n 0x2ceb, 0x2cee,\n 0x2cf2, 0x2cf3,\n 0x2d00, 0x2d25,\n 0x2d27, 0x2d27,\n 0x2d2d, 0x2d2d,\n 0x2d30, 0x2d67,\n 0x2d6f, 0x2d6f,\n 0x2d80, 0x2d96,\n 0x2da0, 0x2da6,\n 0x2da8, 0x2dae,\n 0x2db0, 0x2db6,\n 0x2db8, 0x2dbe,\n 0x2dc0, 0x2dc6,\n 0x2dc8, 0x2dce,\n 0x2dd0, 0x2dd6,\n 0x2dd8, 0x2dde,\n 0x2e2f, 0x2e2f,\n 0x3005, 0x3006,\n 0x3031, 0x3035,\n 0x303b, 0x303c,\n 0x3041, 0x3096,\n 0x309d, 0x309f,\n 0x30a1, 0x30fa,\n 0x30fc, 0x30ff,\n 0x3105, 0x312f,\n 0x3131, 0x318e,\n 0x31a0, 0x31bf,\n 0x31f0, 0x31ff,\n 0x3400, 0x4dbf,\n 0x4e00, 0xa48c,\n 0xa4d0, 0xa4fd,\n 0xa500, 0xa60c,\n 0xa610, 0xa61f,\n 0xa62a, 0xa62b,\n 0xa640, 0xa66e,\n 0xa67f, 0xa69d,\n 0xa6a0, 0xa6e5,\n 0xa717, 0xa71f,\n 0xa722, 0xa788,\n 0xa78b, 0xa7dc,\n 0xa7f1, 0xa801,\n 0xa803, 0xa805,\n 0xa807, 0xa80a,\n 0xa80c, 0xa822,\n 0xa840, 0xa873,\n 0xa882, 0xa8b3,\n 0xa8f2, 0xa8f7,\n 0xa8fb, 0xa8fb,\n 0xa8fd, 0xa8fe,\n 0xa90a, 0xa925,\n 0xa930, 0xa946,\n 0xa960, 0xa97c,\n 0xa984, 0xa9b2,\n 0xa9cf, 0xa9cf,\n 0xa9e0, 0xa9e4,\n 0xa9e6, 0xa9ef,\n 0xa9fa, 0xa9fe,\n 0xaa00, 0xaa28,\n 0xaa40, 0xaa42,\n 0xaa44, 0xaa4b,\n 0xaa60, 0xaa76,\n 0xaa7a, 0xaa7a,\n 0xaa7e, 0xaaaf,\n 0xaab1, 0xaab1,\n 0xaab5, 0xaab6,\n 0xaab9, 0xaabd,\n 0xaac0, 0xaac0,\n 0xaac2, 0xaac2,\n 0xaadb, 0xaadd,\n 0xaae0, 0xaaea,\n 0xaaf2, 0xaaf4,\n 0xab01, 0xab06,\n 0xab09, 0xab0e,\n 0xab11, 0xab16,\n 0xab20, 0xab26,\n 0xab28, 0xab2e,\n 0xab30, 0xab5a,\n 0xab5c, 0xab69,\n 0xab70, 0xabe2,\n 0xac00, 0xd7a3,\n 0xd7b0, 0xd7c6,\n 0xd7cb, 0xd7fb,\n 0xf900, 0xfa6d,\n 0xfa70, 0xfad9,\n 0xfb00, 0xfb06,\n 0xfb13, 0xfb17,\n 0xfb1d, 0xfb1d,\n 0xfb1f, 0xfb28,\n 0xfb2a, 0xfb36,\n 0xfb38, 0xfb3c,\n 0xfb3e, 0xfb3e,\n 0xfb40, 0xfb41,\n 0xfb43, 0xfb44,\n 0xfb46, 0xfbb1,\n 0xfbd3, 0xfd3d,\n 0xfd50, 0xfd8f,\n 0xfd92, 0xfdc7,\n 0xfdf0, 0xfdfb,\n 0xfe70, 0xfe74,\n 0xfe76, 0xfefc,\n 0xff21, 0xff3a,\n 0xff41, 0xff5a,\n 0xff66, 0xffbe,\n 0xffc2, 0xffc7,\n 0xffca, 0xffcf,\n 0xffd2, 0xffd7,\n 0xffda, 0xffdc,\n 0x10000, 0x1000b,\n 0x1000d, 0x10026,\n 0x10028, 0x1003a,\n 0x1003c, 0x1003d,\n 0x1003f, 0x1004d,\n 0x10050, 0x1005d,\n 0x10080, 0x100fa,\n 0x10280, 0x1029c,\n 0x102a0, 0x102d0,\n 0x10300, 0x1031f,\n 0x1032d, 0x10340,\n 0x10342, 0x10349,\n 0x10350, 0x10375,\n 0x10380, 0x1039d,\n 0x103a0, 0x103c3,\n 0x103c8, 0x103cf,\n 0x10400, 0x1049d,\n 0x104b0, 0x104d3,\n 0x104d8, 0x104fb,\n 0x10500, 0x10527,\n 0x10530, 0x10563,\n 0x10570, 0x1057a,\n 0x1057c, 0x1058a,\n 0x1058c, 0x10592,\n 0x10594, 0x10595,\n 0x10597, 0x105a1,\n 0x105a3, 0x105b1,\n 0x105b3, 0x105b9,\n 0x105bb, 0x105bc,\n 0x105c0, 0x105f3,\n 0x10600, 0x10736,\n 0x10740, 0x10755,\n 0x10760, 0x10767,\n 0x10780, 0x10785,\n 0x10787, 0x107b0,\n 0x107b2, 0x107ba,\n 0x10800, 0x10805,\n 0x10808, 0x10808,\n 0x1080a, 0x10835,\n 0x10837, 0x10838,\n 0x1083c, 0x1083c,\n 0x1083f, 0x10855,\n 0x10860, 0x10876,\n 0x10880, 0x1089e,\n 0x108e0, 0x108f2,\n 0x108f4, 0x108f5,\n 0x10900, 0x10915,\n 0x10920, 0x10939,\n 0x10940, 0x10959,\n 0x10980, 0x109b7,\n 0x109be, 0x109bf,\n 0x10a00, 0x10a00,\n 0x10a10, 0x10a13,\n 0x10a15, 0x10a17,\n 0x10a19, 0x10a35,\n 0x10a60, 0x10a7c,\n 0x10a80, 0x10a9c,\n 0x10ac0, 0x10ac7,\n 0x10ac9, 0x10ae4,\n 0x10b00, 0x10b35,\n 0x10b40, 0x10b55,\n 0x10b60, 0x10b72,\n 0x10b80, 0x10b91,\n 0x10c00, 0x10c48,\n 0x10c80, 0x10cb2,\n 0x10cc0, 0x10cf2,\n 0x10d00, 0x10d23,\n 0x10d4a, 0x10d65,\n 0x10d6f, 0x10d85,\n 0x10e80, 0x10ea9,\n 0x10eb0, 0x10eb1,\n 0x10ec2, 0x10ec7,\n 0x10f00, 0x10f1c,\n 0x10f27, 0x10f27,\n 0x10f30, 0x10f45,\n 0x10f70, 0x10f81,\n 0x10fb0, 0x10fc4,\n 0x10fe0, 0x10ff6,\n 0x11003, 0x11037,\n 0x11071, 0x11072,\n 0x11075, 0x11075,\n 0x11083, 0x110af,\n 0x110d0, 0x110e8,\n 0x11103, 0x11126,\n 0x11144, 0x11144,\n 0x11147, 0x11147,\n 0x11150, 0x11172,\n 0x11176, 0x11176,\n 0x11183, 0x111b2,\n 0x111c1, 0x111c4,\n 0x111da, 0x111da,\n 0x111dc, 0x111dc,\n 0x11200, 0x11211,\n 0x11213, 0x1122b,\n 0x1123f, 0x11240,\n 0x11280, 0x11286,\n 0x11288, 0x11288,\n 0x1128a, 0x1128d,\n 0x1128f, 0x1129d,\n 0x1129f, 0x112a8,\n 0x112b0, 0x112de,\n 0x11305, 0x1130c,\n 0x1130f, 0x11310,\n 0x11313, 0x11328,\n 0x1132a, 0x11330,\n 0x11332, 0x11333,\n 0x11335, 0x11339,\n 0x1133d, 0x1133d,\n 0x11350, 0x11350,\n 0x1135d, 0x11361,\n 0x11380, 0x11389,\n 0x1138b, 0x1138b,\n 0x1138e, 0x1138e,\n 0x11390, 0x113b5,\n 0x113b7, 0x113b7,\n 0x113d1, 0x113d1,\n 0x113d3, 0x113d3,\n 0x11400, 0x11434,\n 0x11447, 0x1144a,\n 0x1145f, 0x11461,\n 0x11480, 0x114af,\n 0x114c4, 0x114c5,\n 0x114c7, 0x114c7,\n 0x11580, 0x115ae,\n 0x115d8, 0x115db,\n 0x11600, 0x1162f,\n 0x11644, 0x11644,\n 0x11680, 0x116aa,\n 0x116b8, 0x116b8,\n 0x11700, 0x1171a,\n 0x11740, 0x11746,\n 0x11800, 0x1182b,\n 0x118a0, 0x118df,\n 0x118ff, 0x11906,\n 0x11909, 0x11909,\n 0x1190c, 0x11913,\n 0x11915, 0x11916,\n 0x11918, 0x1192f,\n 0x1193f, 0x1193f,\n 0x11941, 0x11941,\n 0x119a0, 0x119a7,\n 0x119aa, 0x119d0,\n 0x119e1, 0x119e1,\n 0x119e3, 0x119e3,\n 0x11a00, 0x11a00,\n 0x11a0b, 0x11a32,\n 0x11a3a, 0x11a3a,\n 0x11a50, 0x11a50,\n 0x11a5c, 0x11a89,\n 0x11a9d, 0x11a9d,\n 0x11ab0, 0x11af8,\n 0x11bc0, 0x11be0,\n 0x11c00, 0x11c08,\n 0x11c0a, 0x11c2e,\n 0x11c40, 0x11c40,\n 0x11c72, 0x11c8f,\n 0x11d00, 0x11d06,\n 0x11d08, 0x11d09,\n 0x11d0b, 0x11d30,\n 0x11d46, 0x11d46,\n 0x11d60, 0x11d65,\n 0x11d67, 0x11d68,\n 0x11d6a, 0x11d89,\n 0x11d98, 0x11d98,\n 0x11db0, 0x11ddb,\n 0x11ee0, 0x11ef2,\n 0x11f02, 0x11f02,\n 0x11f04, 0x11f10,\n 0x11f12, 0x11f33,\n 0x11fb0, 0x11fb0,\n 0x12000, 0x12399,\n 0x12480, 0x12543,\n 0x12f90, 0x12ff0,\n 0x13000, 0x1342f,\n 0x13441, 0x13446,\n 0x13460, 0x143fa,\n 0x14400, 0x14646,\n 0x16100, 0x1611d,\n 0x16800, 0x16a38,\n 0x16a40, 0x16a5e,\n 0x16a70, 0x16abe,\n 0x16ad0, 0x16aed,\n 0x16b00, 0x16b2f,\n 0x16b40, 0x16b43,\n 0x16b63, 0x16b77,\n 0x16b7d, 0x16b8f,\n 0x16d40, 0x16d6c,\n 0x16e40, 0x16e7f,\n 0x16ea0, 0x16eb8,\n 0x16ebb, 0x16ed3,\n 0x16f00, 0x16f4a,\n 0x16f50, 0x16f50,\n 0x16f93, 0x16f9f,\n 0x16fe0, 0x16fe1,\n 0x16fe3, 0x16fe3,\n 0x16ff2, 0x16ff3,\n 0x17000, 0x18cd5,\n 0x18cff, 0x18d1e,\n 0x18d80, 0x18df2,\n 0x1aff0, 0x1aff3,\n 0x1aff5, 0x1affb,\n 0x1affd, 0x1affe,\n 0x1b000, 0x1b122,\n 0x1b132, 0x1b132,\n 0x1b150, 0x1b152,\n 0x1b155, 0x1b155,\n 0x1b164, 0x1b167,\n 0x1b170, 0x1b2fb,\n 0x1bc00, 0x1bc6a,\n 0x1bc70, 0x1bc7c,\n 0x1bc80, 0x1bc88,\n 0x1bc90, 0x1bc99,\n 0x1d400, 0x1d454,\n 0x1d456, 0x1d49c,\n 0x1d49e, 0x1d49f,\n 0x1d4a2, 0x1d4a2,\n 0x1d4a5, 0x1d4a6,\n 0x1d4a9, 0x1d4ac,\n 0x1d4ae, 0x1d4b9,\n 0x1d4bb, 0x1d4bb,\n 0x1d4bd, 0x1d4c3,\n 0x1d4c5, 0x1d505,\n 0x1d507, 0x1d50a,\n 0x1d50d, 0x1d514,\n 0x1d516, 0x1d51c,\n 0x1d51e, 0x1d539,\n 0x1d53b, 0x1d53e,\n 0x1d540, 0x1d544,\n 0x1d546, 0x1d546,\n 0x1d54a, 0x1d550,\n 0x1d552, 0x1d6a5,\n 0x1d6a8, 0x1d6c0,\n 0x1d6c2, 0x1d6da,\n 0x1d6dc, 0x1d6fa,\n 0x1d6fc, 0x1d714,\n 0x1d716, 0x1d734,\n 0x1d736, 0x1d74e,\n 0x1d750, 0x1d76e,\n 0x1d770, 0x1d788,\n 0x1d78a, 0x1d7a8,\n 0x1d7aa, 0x1d7c2,\n 0x1d7c4, 0x1d7cb,\n 0x1df00, 0x1df1e,\n 0x1df25, 0x1df2a,\n 0x1e030, 0x1e06d,\n 0x1e100, 0x1e12c,\n 0x1e137, 0x1e13d,\n 0x1e14e, 0x1e14e,\n 0x1e290, 0x1e2ad,\n 0x1e2c0, 0x1e2eb,\n 0x1e4d0, 0x1e4eb,\n 0x1e5d0, 0x1e5ed,\n 0x1e5f0, 0x1e5f0,\n 0x1e6c0, 0x1e6de,\n 0x1e6e0, 0x1e6e2,\n 0x1e6e4, 0x1e6e5,\n 0x1e6e7, 0x1e6ed,\n 0x1e6f0, 0x1e6f4,\n 0x1e6fe, 0x1e6ff,\n 0x1e7e0, 0x1e7e6,\n 0x1e7e8, 0x1e7eb,\n 0x1e7ed, 0x1e7ee,\n 0x1e7f0, 0x1e7fe,\n 0x1e800, 0x1e8c4,\n 0x1e900, 0x1e943,\n 0x1e94b, 0x1e94b,\n 0x1ee00, 0x1ee03,\n 0x1ee05, 0x1ee1f,\n 0x1ee21, 0x1ee22,\n 0x1ee24, 0x1ee24,\n 0x1ee27, 0x1ee27,\n 0x1ee29, 0x1ee32,\n 0x1ee34, 0x1ee37,\n 0x1ee39, 0x1ee39,\n 0x1ee3b, 0x1ee3b,\n 0x1ee42, 0x1ee42,\n 0x1ee47, 0x1ee47,\n 0x1ee49, 0x1ee49,\n 0x1ee4b, 0x1ee4b,\n 0x1ee4d, 0x1ee4f,\n 0x1ee51, 0x1ee52,\n 0x1ee54, 0x1ee54,\n 0x1ee57, 0x1ee57,\n 0x1ee59, 0x1ee59,\n 0x1ee5b, 0x1ee5b,\n 0x1ee5d, 0x1ee5d,\n 0x1ee5f, 0x1ee5f,\n 0x1ee61, 0x1ee62,\n 0x1ee64, 0x1ee64,\n 0x1ee67, 0x1ee6a,\n 0x1ee6c, 0x1ee72,\n 0x1ee74, 0x1ee77,\n 0x1ee79, 0x1ee7c,\n 0x1ee7e, 0x1ee7e,\n 0x1ee80, 0x1ee89,\n 0x1ee8b, 0x1ee9b,\n 0x1eea1, 0x1eea3,\n 0x1eea5, 0x1eea9,\n 0x1eeab, 0x1eebb,\n 0x20000, 0x2a6df,\n 0x2a700, 0x2b81d,\n 0x2b820, 0x2cead,\n 0x2ceb0, 0x2ebe0,\n 0x2ebf0, 0x2ee5d,\n 0x2f800, 0x2fa1d,\n 0x30000, 0x3134a,\n 0x31350, 0x33479\n];\n", "import type { Direction } from './types.js';\nimport {\n NON_STRONG_BIDI_RANGES,\n NATURAL_LETTER_RANGES,\n RTL_BIDI_RANGES,\n UNICODE_BIDI_SHA256,\n UNICODE_GENERAL_CATEGORY_SHA256,\n UNICODE_BIDI_VERSION\n} from './generated/bidi-ranges.js';\n\nfunction isInRanges(codePoint: number, ranges: ReadonlyArray): boolean {\n let low = 0;\n let high = ranges.length / 2 - 1;\n while (low <= high) {\n const middle = (low + high) >> 1;\n const start = ranges[middle * 2]!;\n const end = ranges[middle * 2 + 1]!;\n if (codePoint < start) high = middle - 1;\n else if (codePoint > end) low = middle + 1;\n else return true;\n }\n return false;\n}\n\nexport function isRtlCodePoint(codePoint: number): boolean {\n return isInRanges(codePoint, RTL_BIDI_RANGES);\n}\n\n/** Returns the Unicode Bidi_Class strong direction, including LRM/RLM/ALM. */\nexport function classifyBidiStrongCharacter(character: string): Direction {\n const codePoint = character.codePointAt(0);\n if (codePoint === undefined || isInRanges(codePoint, NON_STRONG_BIDI_RANGES)) return 'neutral';\n return isRtlCodePoint(codePoint) ? 'rtl' : 'ltr';\n}\n\n/** Classifies natural-language letters while leaving numbers and punctuation neutral. */\nexport function classifyCharacter(character: string): Direction {\n const codePoint = character.codePointAt(0);\n if (codePoint === undefined) return 'neutral';\n return isInRanges(codePoint, NATURAL_LETTER_RANGES) ? classifyBidiStrongCharacter(character) : 'neutral';\n}\n\nexport const UNICODE_DATA_VERSION = UNICODE_BIDI_VERSION;\nexport const UNICODE_DATA_SHA256 = UNICODE_BIDI_SHA256;\nexport const UNICODE_LETTER_DATA_SHA256 = UNICODE_GENERAL_CATEGORY_SHA256;\n", "import { classifyBidiStrongCharacter, classifyCharacter } from './classify.js';\nimport type {\n DetectionOptions,\n Direction,\n ParagraphAnalysis,\n StrongCharacterCounts,\n TextAnalysis\n} from './types.js';\n\nexport interface TechnicalTokenRange {\n text: string;\n start: number;\n end: number;\n kind: 'code' | 'url' | 'email' | 'path' | 'version' | 'hash' | 'identifier' | 'number' | 'command' | 'math' | 'html';\n}\n\nconst DEFAULT_OPTIONS: Required = {\n strategy: 'content-majority',\n fallback: 'neutral',\n inheritedDirection: 'ltr',\n minimumStrongCharacters: 1,\n majorityThreshold: 0.5,\n excludeTechnicalTokens: true,\n technicalIdentifiers: []\n};\n\nexport const DEFAULT_TECHNICAL_IDENTIFIERS = Object.freeze([\n 'ai', 'api', 'anthropic', 'chatgpt', 'claude', 'cli', 'codex', 'copilot', 'cursor',\n 'deepseek', 'electron', 'gemini', 'github', 'gitlab', 'grok', 'huggingface',\n 'javascript', 'json', 'llama', 'markdown', 'mistral', 'node', 'npm', 'openai',\n 'python', 'qwen', 'react', 'rust', 'svelte', 'typescript', 'url', 'version',\n 'vscode', 'vue', 'web', 'webpack', 'yaml',\n 'angular', 'astro', 'chrome', 'docker', 'esbuild', 'eslint', 'firefox',\n 'kubernetes', 'kubectl', 'nuxt', 'playwright', 'pnpm', 'preact', 'remix',\n 'rollup', 'safari', 'stencil', 'storybook', 'tailwind', 'turbopack', 'vite',\n 'vitest'\n] as const);\nconst KNOWN_TECHNICAL_TOKENS = new Set(DEFAULT_TECHNICAL_IDENTIFIERS);\nconst CUSTOM_TECHNICAL_IDENTIFIER_CACHE = new WeakMap>();\n\nfunction normalizeOptions(options: DetectionOptions = {}): Required {\n const strategy = options.strategy ?? DEFAULT_OPTIONS.strategy;\n const majorityStrategy = strategy === 'content-majority'\n || strategy === 'semantic-dominant'\n || strategy === 'majority';\n return {\n strategy,\n fallback: options.fallback ?? options.inheritedDirection ?? DEFAULT_OPTIONS.fallback,\n inheritedDirection: options.inheritedDirection ?? DEFAULT_OPTIONS.inheritedDirection,\n minimumStrongCharacters: Math.max(1, options.minimumStrongCharacters ?? DEFAULT_OPTIONS.minimumStrongCharacters),\n majorityThreshold: Math.min(1, Math.max(0.5, options.majorityThreshold ?? DEFAULT_OPTIONS.majorityThreshold)),\n // Compatibility/strict first-strong modes must see the real first strong\n // character (including a leading technical identifier), like dir=\"auto\".\n excludeTechnicalTokens: options.excludeTechnicalTokens ?? majorityStrategy,\n technicalIdentifiers: options.technicalIdentifiers ?? DEFAULT_OPTIONS.technicalIdentifiers\n };\n}\n\nfunction addRange(\n ranges: TechnicalTokenRange[],\n text: string,\n start: number,\n end: number,\n kind: TechnicalTokenRange['kind']\n): void {\n if (end > start) ranges.push({ text: text.slice(start, end), start, end, kind });\n}\n\nfunction addMatches(\n text: string,\n ranges: TechnicalTokenRange[],\n expression: RegExp,\n kind: TechnicalTokenRange['kind'],\n group = 0\n): void {\n expression.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = expression.exec(text)) !== null) {\n const value = match[group];\n if (value === undefined) continue;\n const start = match.index + match[0].indexOf(value);\n addRange(ranges, text, start, start + value.length, kind);\n }\n}\n\n/**\n * Adds `$...$`, `$$...$$`, and `\\(...\\)` math ranges in one forward pass.\n * A combined lazy regular expression restarts its search after every unmatched\n * `\\(` opener, which makes adversarial input quadratic.\n */\nfunction addMathRanges(text: string, ranges: TechnicalTokenRange[]): void {\n let i = 0;\n let scanned = -1;\n while (i < text.length) {\n const p = text[i] === '\\\\' && text[i + 1] === '(';\n const d = text[i] === '$'\n ? (text[i + 1] === '$' ? '$$' : '$')\n : (p && i >= scanned ? '\\\\)' : '');\n if (!d) { i++; continue; }\n\n let e = i + (p ? 2 : d.length);\n while (e < text.length\n && text[e] !== '\\r'\n && text[e] !== '\\n'\n && !text.startsWith(d, e)) e++;\n\n if (text.startsWith(d, e) && (d !== '$' || e > i + 1)) {\n addRange(ranges, text, i, e + d.length, 'math');\n i = e + d.length;\n } else {\n if (p) scanned = e;\n i++;\n }\n }\n}\n\nfunction trimTechnicalPunctuation(value: string): string {\n let end = value.length;\n while (end > 0 && /[.,;:!?\u060C\u061B\u061F\u3002\u0964\u06D4]/u.test(value[end - 1]!)) end -= 1;\n return end === value.length ? value : value.slice(0, end);\n}\n\nfunction addValidatedMatches(\n text: string,\n ranges: TechnicalTokenRange[],\n expression: RegExp,\n kind: TechnicalTokenRange['kind'],\n validate: (value: string) => boolean,\n group = 0\n): void {\n expression.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = expression.exec(text)) !== null) {\n const value = match[group];\n if (value === undefined || !validate(value)) continue;\n const start = match.index + match[0].indexOf(value);\n addRange(ranges, text, start, start + value.length, kind);\n }\n}\n\nfunction addNormalizedMatches(\n text: string,\n ranges: TechnicalTokenRange[],\n expression: RegExp,\n kind: TechnicalTokenRange['kind'],\n normalize: (value: string) => string,\n group = 0\n): void {\n expression.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = expression.exec(text)) !== null) {\n const original = match[group];\n if (original === undefined) continue;\n const value = normalize(original);\n if (!value) continue;\n const start = match.index + match[0].indexOf(original);\n addRange(ranges, text, start, start + value.length, kind);\n }\n}\n\nfunction isIpv4(value: string): boolean {\n const parts = value.split('.');\n return parts.length === 4 && parts.every((part) => /^\\d{1,3}$/u.test(part) && Number(part) <= 255);\n}\n\nfunction isIpv6(value: string): boolean {\n if (!/^[0-9A-F:]+$/iu.test(value) || !value.includes(':')) return false;\n const compression = value.indexOf('::');\n if (compression !== value.lastIndexOf('::')) return false;\n const sides = compression >= 0 ? value.split('::') : [value];\n const groups = sides.flatMap((side) => side ? side.split(':') : []);\n if (!groups.every((group) => /^[0-9A-F]{1,4}$/iu.test(group))) return false;\n return compression >= 0 ? groups.length < 8 : groups.length === 8;\n}\n\nfunction addCodeRanges(text: string, ranges: TechnicalTokenRange[]): void {\n let fence: { marker: '`' | '~'; length: number; start: number } | undefined;\n const closedFences: Array<{ start: number; end: number }> = [];\n let lineStart = 0;\n while (lineStart < text.length) {\n let lineEnd = lineStart;\n while (lineEnd < text.length && text[lineEnd] !== '\\r' && text[lineEnd] !== '\\n') lineEnd += 1;\n let nextLine = lineEnd;\n if (text[nextLine] === '\\r') nextLine += 1;\n if (text[nextLine] === '\\n') nextLine += 1;\n const line = text.slice(lineStart, lineEnd);\n if (!fence) {\n const openerMatch = /^ {0,3}(`{3,}|~{3,})(.*)$/u.exec(line);\n const opener = openerMatch?.[1];\n const info = openerMatch?.[2] ?? '';\n if (opener && !(opener[0] === '`' && info.includes('`'))) fence = {\n marker: opener[0] as '`' | '~',\n length: opener.length,\n start: lineStart\n };\n } else {\n const closer = /^ {0,3}(`+|~+)[ \\t]*$/u.exec(line)?.[1];\n if (closer?.[0] === fence.marker && closer.length >= fence.length) {\n closedFences.push({ start: fence.start, end: nextLine });\n fence = undefined;\n }\n }\n lineStart = nextLine;\n }\n // Decide once over the union of all closed spans. Scanning each fence's\n // complementary text separately would be quadratic and would mistake code\n // inside a second standalone fence for prose outside the first.\n let fenceIndex = 0;\n let utf16Index = 0;\n let hasOutsideNaturalText = false;\n for (const character of text) {\n while (fenceIndex < closedFences.length && utf16Index >= closedFences[fenceIndex]!.end) {\n fenceIndex += 1;\n }\n const span = closedFences[fenceIndex];\n const insideFence = span !== undefined && utf16Index >= span.start && utf16Index < span.end;\n if (!insideFence && classifyCharacter(character) !== 'neutral') {\n hasOutsideNaturalText = true;\n break;\n }\n utf16Index += character.length;\n }\n // Standalone fenced code keeps its historical raw-text direction evidence.\n // Parser-aware Markdown adapters force code blocks LTR. Excluding complete\n // fences is useful when surrounding prose\u2014not code literals\u2014must decide the\n // containing raw block's natural direction.\n if (hasOutsideNaturalText) {\n for (const span of closedFences) addRange(ranges, text, span.start, span.end, 'code');\n }\n\n const lineExpression = /[^\\r\\n]*/gu;\n let lineMatch: RegExpExecArray | null;\n while ((lineMatch = lineExpression.exec(text)) !== null) {\n const line = lineMatch[0];\n const lineStart = lineMatch.index;\n const runs: Array<{ start: number; length: number }> = [];\n for (let index = 0; index < line.length;) {\n if (line[index] !== '`') {\n index += 1;\n continue;\n }\n const start = index;\n while (index < line.length && line[index] === '`') index += 1;\n runs.push({ start, length: index - start });\n }\n const suffixMaximum = new Array(runs.length + 1).fill(0);\n for (let index = runs.length - 1; index >= 0; index -= 1) {\n suffixMaximum[index] = Math.max(runs[index]!.length, suffixMaximum[index + 1]!);\n }\n let runIndex = 0;\n let cursor = runs[0]?.start ?? 0;\n while (runIndex < runs.length) {\n const opener = runs[runIndex]!;\n const openerEnd = opener.start + opener.length;\n if (cursor >= openerEnd) {\n runIndex += 1;\n cursor = runs[runIndex]?.start ?? 0;\n continue;\n }\n const available = openerEnd - cursor;\n const delimiterLength = Math.min(\n available,\n Math.max(Math.floor(available / 2), suffixMaximum[runIndex + 1]!)\n );\n if (delimiterLength === 0) {\n runIndex += 1;\n cursor = runs[runIndex]?.start ?? 0;\n continue;\n }\n let closingRunIndex = runIndex;\n let closingStart = cursor + delimiterLength;\n if (available - delimiterLength < delimiterLength) {\n closingRunIndex += 1;\n while (closingRunIndex < runs.length\n && runs[closingRunIndex]!.length < delimiterLength) closingRunIndex += 1;\n if (closingRunIndex >= runs.length) {\n runIndex += 1;\n cursor = runs[runIndex]?.start ?? 0;\n continue;\n }\n closingStart = runs[closingRunIndex]!.start;\n }\n const end = closingStart + delimiterLength;\n addRange(ranges, text, lineStart + cursor, lineStart + end, 'code');\n runIndex = closingRunIndex;\n cursor = end;\n }\n if (lineMatch[0].length === 0) lineExpression.lastIndex += 1;\n }\n}\n\nfunction customTechnicalIdentifiers(values: readonly string[]): ReadonlySet {\n const cacheable = Object.isFrozen(values);\n const cached = cacheable ? CUSTOM_TECHNICAL_IDENTIFIER_CACHE.get(values) : undefined;\n if (cached) return cached;\n const identifiers = new Set();\n for (const value of values) {\n if (/^[A-Za-z][A-Za-z0-9_.-]*$/u.test(value)) identifiers.add(value.toLowerCase());\n }\n if (cacheable) CUSTOM_TECHNICAL_IDENTIFIER_CACHE.set(values, identifiers);\n return identifiers;\n}\n\n/**\n * Acronyms are short. A longer all-capital word is emphasized prose, not an\n * identifier, and must keep deciding the natural-language base direction.\n */\nconst ACRONYM_MAXIMUM_LENGTH = 5;\n\nfunction isKnownTechnicalWord(value: string, custom: ReadonlySet): boolean {\n const normalized = value.toLowerCase();\n return KNOWN_TECHNICAL_TOKENS.has(normalized) || custom.has(normalized);\n}\n\n/**\n * Reports whether capitals are the block's prose style rather than an\n * identifier signal. `PLEASE READ THIS WARNING` is emphasized natural language;\n * the same `API` token inside mixed-case prose is an acronym. Deciding this per\n * block keeps the rule deterministic and needs no dictionary or language model.\n */\nfunction usesUppercaseProse(text: string): boolean {\n const words = text.match(/\\b[A-Za-z]{2,}\\b/gu);\n if (words === null || words.length < 2) return false;\n let capitalized = 0;\n let hasLongCapitalizedWord = false;\n // Every candidate is alphabetic, so \"contains no lowercase\" means all-capital.\n for (const word of words) {\n if (/[a-z]/u.test(word)) continue;\n capitalized += 1;\n if (word.length > ACRONYM_MAXIMUM_LENGTH) hasLongCapitalizedWord = true;\n }\n // `HTTP API` is an acronym sequence, not proof of an uppercase prose style.\n // Requiring one long word keeps that short technical phrase excluded while\n // still recognizing natural-language emphasis such as `PLEASE READ THIS`.\n return hasLongCapitalizedWord && capitalized * 2 > words.length;\n}\n\n/**\n * Only tokens starting with an ASCII letter reach this test, so every false\n * exclusion removes LTR evidence and never RTL evidence. An over-broad rule\n * therefore biases mixed blocks toward RTL \u2014 the mirror of the failure this\n * project exists to fix \u2014 which is why the hyphen is not a signal on its own.\n */\nfunction isTechnicalIdentifier(\n token: string,\n custom: ReadonlySet,\n uppercaseProse: boolean\n): boolean {\n if (isKnownTechnicalWord(token, custom)) return true;\n // A hyphenated token is technical when a segment is itself a known technical\n // word (`react-markdown`, `web-app`), not merely because it is hyphenated.\n if (token.includes('-')\n && token.split('-').some((segment) => segment !== '' && isKnownTechnicalWord(segment, custom))) {\n return true;\n }\n // Digits, underscores, and dots are structural identifier syntax.\n return /[0-9_.]/u.test(token)\n || /[a-z][A-Z]/u.test(token)\n || (!uppercaseProse\n && token.length <= ACRONYM_MAXIMUM_LENGTH\n && /^[A-Z]{2,}$/u.test(token));\n}\n\n/** Finds ranges that should not decide the natural-language base direction. */\nexport function findTechnicalTokenRanges(\n text: string,\n technicalIdentifiers: readonly string[] = []\n): TechnicalTokenRange[] {\n const ranges: TechnicalTokenRange[] = [];\n addCodeRanges(text, ranges);\n addMatches(text, ranges, /<\\/?[A-Za-z][^<>\\r\\n]*>/gu, 'html');\n addMathRanges(text, ranges);\n\n const urls = /\\b(?:https?|ftp):\\/\\/[^\\s<>{}\"']+/giu;\n let urlMatch: RegExpExecArray | null;\n while ((urlMatch = urls.exec(text)) !== null) {\n let value = urlMatch[0];\n value = trimTechnicalPunctuation(value);\n for (const [open, close] of [['(', ')'], ['[', ']'], ['{', '}']] as const) {\n if (!value.endsWith(close)) continue;\n let balance = 0;\n for (const character of value) {\n if (character === open) balance += 1;\n else if (character === close) balance -= 1;\n }\n if (balance >= 0) continue;\n let end = value.length;\n while (balance < 0 && end > 0 && value[end - 1] === close) {\n balance += 1;\n end -= 1;\n }\n if (end !== value.length) value = value.slice(0, end);\n }\n addRange(ranges, text, urlMatch.index, urlMatch.index + value.length, 'url');\n }\n addMatches(text, ranges, /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/giu, 'email');\n addNormalizedMatches(\n text,\n ranges,\n /(?()\\x5B\\x5D{}]+/gu,\n 'path',\n trimTechnicalPunctuation\n );\n addMatches(text, ranges, /\\b(?:[A-Za-z0-9_.-]+[\\\\/])+(?:[A-Za-z0-9_.-]+)\\b/gu, 'path');\n addMatches(text, ranges, /(? a.start - b.start || b.end - a.end);\n const merged: TechnicalTokenRange[] = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end) {\n previous.end = Math.max(previous.end, range.end);\n previous.text = text.slice(previous.start, previous.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged;\n}\n\nexport function countStrongCharacters(\n text: string,\n options: DetectionOptions = {}\n): StrongCharacterCounts & { firstStrong: Direction; technicalTokens: TechnicalTokenRange[] } {\n const normalized = normalizeOptions(options);\n return countStrongCharactersNormalized(text, normalized);\n}\n\nfunction countStrongCharactersNormalized(\n text: string,\n normalized: Required\n): StrongCharacterCounts & { firstStrong: Direction; technicalTokens: TechnicalTokenRange[] } {\n const technicalTokens = normalized.excludeTechnicalTokens\n ? findTechnicalTokenRanges(text, normalized.technicalIdentifiers)\n : [];\n let ltr = 0;\n let rtl = 0;\n let firstStrong: Direction = 'neutral';\n let index = 0;\n let technicalIndex = 0;\n const classify = normalized.strategy === 'first-strong' || normalized.strategy === 'strict-uax9'\n ? classifyBidiStrongCharacter\n : classifyCharacter;\n\n for (const character of text) {\n // Technical ranges are sorted and merged, so advance one cursor instead\n // of rescanning every range for every code point. This keeps detection\n // linear even for long transcripts containing many URLs/identifiers.\n while (technicalIndex < technicalTokens.length && index >= technicalTokens[technicalIndex]!.end) {\n technicalIndex += 1;\n }\n const technicalRange = technicalTokens[technicalIndex];\n const isTechnical = technicalRange !== undefined\n && index >= technicalRange.start\n && index < technicalRange.end;\n if (!isTechnical) {\n const direction = classify(character);\n if (direction === 'ltr') ltr += 1;\n if (direction === 'rtl') rtl += 1;\n if (firstStrong === 'neutral' && direction !== 'neutral') firstStrong = direction;\n }\n index += character.length;\n }\n\n return { ltr, rtl, total: ltr + rtl, firstStrong, technicalTokens };\n}\n\nfunction fallbackDirection(options: Required): Direction {\n return options.fallback;\n}\n\nfunction directionFromCounts(\n counts: StrongCharacterCounts & { firstStrong: Direction },\n normalized: Required\n): Direction {\n if (normalized.strategy === 'ltr' || normalized.strategy === 'rtl') return normalized.strategy;\n if (normalized.strategy === 'inherit') return normalized.inheritedDirection;\n if (counts.total < normalized.minimumStrongCharacters) return fallbackDirection(normalized);\n\n if (normalized.strategy === 'first-strong' || normalized.strategy === 'strict-uax9') {\n return counts.firstStrong === 'neutral' ? fallbackDirection(normalized) : counts.firstStrong;\n }\n\n if (counts.rtl > counts.ltr && counts.rtl / counts.total >= normalized.majorityThreshold) return 'rtl';\n if (counts.ltr > counts.rtl && counts.ltr / counts.total >= normalized.majorityThreshold) return 'ltr';\n return counts.firstStrong === 'neutral' ? fallbackDirection(normalized) : counts.firstStrong;\n}\n\nexport function detectDirection(text: string, options: DetectionOptions = {}): Direction {\n const normalized = normalizeOptions(options);\n if (normalized.strategy === 'ltr' || normalized.strategy === 'rtl') return normalized.strategy;\n if (normalized.strategy === 'inherit') return normalized.inheritedDirection;\n return directionFromCounts(countStrongCharactersNormalized(text, normalized), normalized);\n}\n\nfunction confidenceFor(counts: StrongCharacterCounts, direction: Direction): number {\n if (counts.total === 0 || direction === 'neutral') return 0;\n const matching = direction === 'rtl' ? counts.rtl : counts.ltr;\n return Number((matching / counts.total).toFixed(4));\n}\n\nfunction firstBidiStrongCharacter(text: string): Direction {\n for (const character of text) {\n const direction = classifyBidiStrongCharacter(character);\n if (direction !== 'neutral') return direction;\n }\n return 'neutral';\n}\n\nfunction splitParagraphs(text: string): Array<{ text: string; start: number; end: number }> {\n const paragraphs: Array<{ text: string; start: number; end: number }> = [];\n const separator = /\\r\\n|\\n|\\r|\\u2029/gu;\n let start = 0;\n let match: RegExpExecArray | null;\n\n while ((match = separator.exec(text)) !== null) {\n paragraphs.push({ text: text.slice(start, match.index), start, end: match.index });\n start = match.index + match[0].length;\n }\n paragraphs.push({ text: text.slice(start), start, end: text.length });\n return paragraphs;\n}\n\nexport function analyzeParagraph(text: string, start = 0, options: DetectionOptions = {}): ParagraphAnalysis {\n const normalized = normalizeOptions(options);\n const countsWithFirst = countStrongCharactersNormalized(text, normalized);\n const counts: StrongCharacterCounts = {\n ltr: countsWithFirst.ltr,\n rtl: countsWithFirst.rtl,\n total: countsWithFirst.total\n };\n const direction = directionFromCounts(countsWithFirst, normalized);\n return {\n text,\n start,\n end: start + text.length,\n direction,\n firstStrong: countsWithFirst.firstStrong,\n confidence: confidenceFor(counts, direction),\n counts\n };\n}\n\nexport function analyzeText(text: string, options: DetectionOptions = {}): TextAnalysis {\n const normalized = normalizeOptions(options);\n const countsWithFirst = countStrongCharactersNormalized(text, normalized);\n const counts: StrongCharacterCounts = {\n ltr: countsWithFirst.ltr,\n rtl: countsWithFirst.rtl,\n total: countsWithFirst.total\n };\n const direction = directionFromCounts(countsWithFirst, normalized);\n const rawCountsWithFirst = countStrongCharactersNormalized(text, normalizeOptions({\n ...normalized,\n strategy: 'content-majority',\n excludeTechnicalTokens: false\n }));\n const rawCounts: StrongCharacterCounts = {\n ltr: rawCountsWithFirst.ltr,\n rtl: rawCountsWithFirst.rtl,\n total: rawCountsWithFirst.total\n };\n const split = splitParagraphs(text);\n const paragraphs = split.length === 1\n ? [{\n text,\n start: 0,\n end: text.length,\n direction,\n firstStrong: countsWithFirst.firstStrong,\n confidence: confidenceFor(counts, direction),\n counts\n }]\n : split.map((paragraph) => analyzeParagraph(paragraph.text, paragraph.start, normalized));\n return {\n text,\n direction,\n firstStrong: countsWithFirst.firstStrong,\n rawFirstStrong: firstBidiStrongCharacter(text),\n confidence: confidenceFor(counts, direction),\n counts,\n rawCounts,\n paragraphs,\n mixed: rawCounts.ltr > 0 && rawCounts.rtl > 0\n };\n}\n", "import type {\n BidiControlFinding,\n BidiControlRisk,\n BidiControlSanitizationGroup,\n BidiSecurityFinding,\n BidiSecurityMode,\n BidiSecurityReport,\n BidiSecuritySeverity\n} from './types.js';\n\nconst CONTROL_METADATA = new Map>([\n [0x061c, { name: 'ARABIC LETTER MARK', risk: 'low', category: 'mark' }],\n [0x200e, { name: 'LEFT-TO-RIGHT MARK', risk: 'low', category: 'mark' }],\n [0x200f, { name: 'RIGHT-TO-LEFT MARK', risk: 'low', category: 'mark' }],\n [0x202a, { name: 'LEFT-TO-RIGHT EMBEDDING', risk: 'high', category: 'embedding' }],\n [0x202b, { name: 'RIGHT-TO-LEFT EMBEDDING', risk: 'high', category: 'embedding' }],\n [0x202c, { name: 'POP DIRECTIONAL FORMATTING', risk: 'medium', category: 'pop' }],\n [0x202d, { name: 'LEFT-TO-RIGHT OVERRIDE', risk: 'high', category: 'override' }],\n [0x202e, { name: 'RIGHT-TO-LEFT OVERRIDE', risk: 'high', category: 'override' }],\n [0x2066, { name: 'LEFT-TO-RIGHT ISOLATE', risk: 'medium', category: 'isolate' }],\n [0x2067, { name: 'RIGHT-TO-LEFT ISOLATE', risk: 'medium', category: 'isolate' }],\n [0x2068, { name: 'FIRST STRONG ISOLATE', risk: 'medium', category: 'isolate' }],\n [0x2069, { name: 'POP DIRECTIONAL ISOLATE', risk: 'medium', category: 'pop' }],\n [0x206a, { name: 'INHIBIT SYMMETRIC SWAPPING', risk: 'medium', category: 'deprecated' }],\n [0x206b, { name: 'ACTIVATE SYMMETRIC SWAPPING', risk: 'medium', category: 'deprecated' }],\n [0x206c, { name: 'INHIBIT ARABIC FORM SHAPING', risk: 'medium', category: 'deprecated' }],\n [0x206d, { name: 'ACTIVATE ARABIC FORM SHAPING', risk: 'medium', category: 'deprecated' }],\n [0x206e, { name: 'NATIONAL DIGIT SHAPES', risk: 'medium', category: 'deprecated' }],\n [0x206f, { name: 'NOMINAL DIGIT SHAPES', risk: 'medium', category: 'deprecated' }]\n]);\n\nconst REMEDIATION = 'Remove the control unless a documented plain-text protocol requires it; prefer semantic markup and isolation.';\n\nfunction severityForRisk(risk: BidiControlRisk): BidiSecuritySeverity {\n if (risk === 'high') return 'high';\n if (risk === 'medium') return 'warning';\n return 'info';\n}\n\nfunction rangeFor(control: BidiControlFinding): BidiSecurityFinding['sourceRange'] {\n return {\n utf16: { start: control.index, end: control.end },\n codePoint: { start: control.codePointIndex, end: control.codePointIndex + 1 }\n };\n}\n\nfunction codeForControl(control: BidiControlFinding): string {\n if (control.category === 'override') return 'BIDI_OVERRIDE_CONTROL';\n if (control.category === 'embedding') return 'BIDI_EMBEDDING_CONTROL';\n if (control.category === 'isolate') return 'BIDI_ISOLATE_CONTROL';\n if (control.category === 'mark') return 'BIDI_DIRECTIONAL_MARK';\n if (control.category === 'deprecated') return 'BIDI_DEPRECATED_CONTROL';\n return 'BIDI_POP_CONTROL';\n}\n\nfunction controlFinding(control: BidiControlFinding): BidiSecurityFinding {\n return {\n code: codeForControl(control),\n severity: severityForRisk(control.risk),\n message: `${control.name} (${control.codePoint}) is invisible and changes bidirectional interpretation.`,\n sourceRange: rangeFor(control),\n remediation: REMEDIATION,\n control\n };\n}\n\nexport function findBidiControls(text: string): BidiControlFinding[] {\n const findings: BidiControlFinding[] = [];\n let utf16Index = 0;\n let codePointIndex = 0;\n\n for (const character of text) {\n const codePoint = character.codePointAt(0)!;\n const metadata = CONTROL_METADATA.get(codePoint);\n if (metadata) {\n findings.push({\n character,\n codePoint: `U+${codePoint.toString(16).toUpperCase().padStart(4, '0')}`,\n index: utf16Index,\n end: utf16Index + character.length,\n codePointIndex,\n ...metadata\n });\n }\n utf16Index += character.length;\n codePointIndex += 1;\n }\n return findings;\n}\n\nexport function visibleBidiControls(text: string): string {\n const namesByCodePoint = new Map([...CONTROL_METADATA].map(([codePoint, metadata]) => [codePoint, metadata.name]));\n let result = '';\n for (const character of text) {\n const codePoint = character.codePointAt(0)!;\n const name = namesByCodePoint.get(codePoint);\n result += name ? `\u27E6${name}\u27E7` : character;\n }\n return result;\n}\n\nexport function highestControlRisk(findings: readonly BidiControlFinding[]): BidiControlRisk | null {\n if (findings.some((finding) => finding.risk === 'high')) return 'high';\n if (findings.some((finding) => finding.risk === 'medium')) return 'medium';\n if (findings.some((finding) => finding.risk === 'low')) return 'low';\n return null;\n}\n\ninterface FormattingFrame {\n kind: 'embedding' | 'isolate';\n control: BidiControlFinding;\n}\n\nfunction lastFrameIndex(stack: readonly FormattingFrame[], kind: FormattingFrame['kind']): number {\n for (let index = stack.length - 1; index >= 0; index -= 1) {\n if (stack[index]?.kind === kind) return index;\n }\n return -1;\n}\n\nfunction balanceFindings(controls: readonly BidiControlFinding[]): BidiSecurityFinding[] {\n const findings: BidiSecurityFinding[] = [];\n const stack: FormattingFrame[] = [];\n\n for (const control of controls) {\n const codePoint = control.codePoint;\n if (codePoint === 'U+202A' || codePoint === 'U+202B' || codePoint === 'U+202D' || codePoint === 'U+202E') {\n stack.push({ kind: 'embedding', control });\n continue;\n }\n if (codePoint === 'U+2066' || codePoint === 'U+2067' || codePoint === 'U+2068') {\n stack.push({ kind: 'isolate', control });\n continue;\n }\n if (codePoint === 'U+202C') {\n const isolateIndex = lastFrameIndex(stack, 'isolate');\n const embeddingIndex = lastFrameIndex(stack, 'embedding');\n if (embeddingIndex <= isolateIndex) {\n findings.push({\n code: 'BIDI_UNMATCHED_PDF',\n severity: 'high',\n message: 'POP DIRECTIONAL FORMATTING has no matching active embedding or override.',\n sourceRange: rangeFor(control),\n remediation: 'Remove the unmatched PDF or add the intended opener within the same isolate.',\n control\n });\n } else {\n stack.splice(embeddingIndex, 1);\n }\n continue;\n }\n if (codePoint === 'U+2069') {\n const isolateIndex = lastFrameIndex(stack, 'isolate');\n if (isolateIndex < 0) {\n findings.push({\n code: 'BIDI_UNMATCHED_PDI',\n severity: 'high',\n message: 'POP DIRECTIONAL ISOLATE has no matching isolate opener.',\n sourceRange: rangeFor(control),\n remediation: 'Remove the unmatched PDI or add the intended LRI, RLI, or FSI opener.',\n control\n });\n } else {\n const crossing = stack.slice(isolateIndex + 1).filter((frame) => frame.kind === 'embedding');\n for (const frame of crossing) {\n findings.push({\n code: 'BIDI_FORMAT_CROSSES_ISOLATE_BOUNDARY',\n severity: 'high',\n message: `${frame.control.name} is not closed before the containing isolate ends.`,\n sourceRange: rangeFor(frame.control),\n remediation: 'Close the embedding or override with PDF before PDI.',\n control: frame.control\n });\n }\n stack.splice(isolateIndex);\n }\n }\n }\n\n for (const frame of stack) {\n findings.push({\n code: frame.kind === 'isolate' ? 'BIDI_UNCLOSED_ISOLATE' : 'BIDI_UNCLOSED_EMBEDDING',\n severity: 'high',\n message: `${frame.control.name} is not terminated before the end of the text.`,\n sourceRange: rangeFor(frame.control),\n remediation: frame.kind === 'isolate'\n ? 'Add the matching PDI or remove the isolate opener.'\n : 'Add the matching PDF or remove the embedding/override opener.',\n control: frame.control\n });\n }\n return findings;\n}\n\nfunction isAsciiIdentifierCharacter(value: string | undefined): boolean {\n return value !== undefined && /^[A-Za-z0-9_$]$/u.test(value);\n}\n\nfunction invisibleCharacterFindings(text: string): BidiSecurityFinding[] {\n const findings: BidiSecurityFinding[] = [];\n const characters = [...text];\n let utf16Index = 0;\n for (let codePointIndex = 0; codePointIndex < characters.length; codePointIndex += 1) {\n const character = characters[codePointIndex]!;\n const sourceRange = {\n utf16: { start: utf16Index, end: utf16Index + character.length },\n codePoint: { start: codePointIndex, end: codePointIndex + 1 }\n };\n if (character === '\\u200B') {\n findings.push({\n code: 'HIDDEN_ZERO_WIDTH_SPACE',\n severity: 'warning',\n message: 'ZERO WIDTH SPACE (U+200B) is hidden and can disguise identifiers, links, or filenames.',\n sourceRange,\n remediation: 'Remove it from identifiers and source-like content unless its use is explicitly required.'\n });\n }\n if ((character === '\\u200C' || character === '\\u200D')\n && isAsciiIdentifierCharacter(characters[codePointIndex - 1])\n && isAsciiIdentifierCharacter(characters[codePointIndex + 1])) {\n const name = character === '\\u200C' ? 'ZERO WIDTH NON-JOINER' : 'ZERO WIDTH JOINER';\n findings.push({\n code: 'HIDDEN_IDENTIFIER_JOINER',\n severity: 'warning',\n message: `${name} is hidden inside an ASCII identifier-like token.`,\n sourceRange,\n remediation: 'Remove the joiner from machine identifiers, or document and validate the identifier protocol that requires it.'\n });\n }\n if (character === '\\u2060') {\n findings.push({\n code: 'HIDDEN_WORD_JOINER',\n severity: 'info',\n message: 'WORD JOINER (U+2060) is invisible and can disguise token boundaries.',\n sourceRange,\n remediation: 'Confirm that non-breaking behavior is required; remove it from identifiers and source-like content.'\n });\n }\n // A leading U+FEFF can represent a decoded byte-order signature. The same\n // character midstream is invisible content and deserves an explicit finding.\n if (character === '\\uFEFF' && codePointIndex > 0) {\n findings.push({\n code: 'HIDDEN_MIDSTREAM_BOM',\n severity: 'warning',\n message: 'ZERO WIDTH NO-BREAK SPACE/BOM (U+FEFF) appears inside the text.',\n sourceRange,\n remediation: 'Remove the midstream BOM unless a documented protocol explicitly requires it.'\n });\n }\n utf16Index += character.length;\n }\n return findings;\n}\n\n/** Audits hidden bidi formatting without mutating the source string. */\nexport function scanBidiSecurity(\n text: string,\n options: { mode?: BidiSecurityMode } = {}\n): BidiSecurityReport {\n const mode = options.mode ?? 'audit';\n if (mode === 'off') return { mode, safe: true, shouldBlock: false, controls: [], findings: [] };\n const controls = findBidiControls(text);\n const findings = [\n ...controls.map(controlFinding),\n ...balanceFindings(controls),\n ...invisibleCharacterFindings(text)\n ].sort((a, b) => a.sourceRange.utf16.start - b.sourceRange.utf16.start || a.code.localeCompare(b.code));\n const hasHigh = findings.some((finding) => finding.severity === 'high');\n return {\n mode,\n safe: !hasHigh,\n shouldBlock: mode === 'strict' ? findings.length > 0 : mode === 'warn' && hasHigh,\n controls,\n findings\n };\n}\n\nexport interface SanitizeBidiControlsOptions {\n /** Remove controls with these risk levels. Defaults to every level. */\n remove?: BidiControlRisk[];\n /**\n * Remove only these semantic control groups. PDF follows embedding/override;\n * PDI follows isolate, so preserved isolate pairs stay structurally intact.\n */\n removeGroups?: BidiControlSanitizationGroup[];\n}\n\nconst ALL_SANITIZATION_GROUPS: readonly BidiControlSanitizationGroup[] = [\n 'mark', 'embedding-override', 'isolate', 'deprecated'\n];\n\nconst SANITIZATION_GROUP_RISK: Readonly> = {\n mark: 'low',\n 'embedding-override': 'high',\n isolate: 'medium',\n deprecated: 'medium'\n};\n\nfunction sanitizationGroup(codePoint: number, category: BidiControlFinding['category']): BidiControlSanitizationGroup {\n if (codePoint === 0x202c || category === 'embedding' || category === 'override') {\n return 'embedding-override';\n }\n if (codePoint === 0x2069 || category === 'isolate') return 'isolate';\n if (category === 'mark' || category === 'deprecated') return category;\n // Every recognized pop is handled above; keep an explicit defensive\n // fallback so future metadata cannot silently escape the default sanitizer.\n return 'deprecated';\n}\n\nexport function sanitizeBidiControls(\n text: string,\n options: SanitizeBidiControlsOptions = {}\n): { text: string; removed: BidiControlFinding[] } {\n const remove = new Set(options.remove ?? ['high', 'medium', 'low']);\n const removeGroups = new Set(options.removeGroups ?? ALL_SANITIZATION_GROUPS);\n const grouped = options.removeGroups !== undefined;\n const removed: BidiControlFinding[] = [];\n let output = '';\n let utf16Index = 0;\n let codePointIndex = 0;\n\n for (const character of text) {\n const codePoint = character.codePointAt(0)!;\n const metadata = CONTROL_METADATA.get(codePoint);\n const group = metadata && sanitizationGroup(codePoint, metadata.category);\n const selected = metadata && group && removeGroups.has(group)\n && remove.has(grouped ? SANITIZATION_GROUP_RISK[group] : metadata.risk);\n if (metadata && selected) {\n removed.push({\n character,\n codePoint: `U+${codePoint.toString(16).toUpperCase().padStart(4, '0')}`,\n index: utf16Index,\n end: utf16Index + character.length,\n codePointIndex,\n ...metadata\n });\n } else {\n output += character;\n }\n utf16Index += character.length;\n codePointIndex += 1;\n }\n\n return { text: output, removed };\n}\n", "import { classifyBidiStrongCharacter } from './classify.js';\nimport { findBidiControls } from './security.js';\nimport type { ResolvedDirection } from './types.js';\n\n/**\n * `auto` is the non-interference default: ordinary LTR content in an LTR\n * context receives no BidiLens markup or DOM mutation. `always` retains the\n * explicit-annotation behavior for integrations that require stable markers.\n */\nexport type BidiInterventionMode = 'auto' | 'always';\n\nexport interface BidiInterventionOptions {\n intervention?: BidiInterventionMode | undefined;\n inheritedDirection?: ResolvedDirection | undefined;\n}\n\n/**\n * Reports whether rendering metadata is needed for a string in its host\n * context. Hidden bidi controls deliberately disable the LTR fast path so an\n * apparently English string cannot bypass bidi-aware handling.\n */\nexport function needsBidiIntervention(\n text: string,\n options: BidiInterventionOptions = {}\n): boolean {\n if (options.intervention === 'always') return true;\n if (findBidiControls(text).length > 0) return true;\n\n let hasLtr = false;\n for (const character of text) {\n const direction = classifyBidiStrongCharacter(character);\n if (direction === 'rtl') return true;\n if (direction === 'ltr') hasLtr = true;\n }\n\n return options.inheritedDirection === 'rtl' && (hasLtr || text.length > 0);\n}\n", "import { classifyCharacter } from './classify.js';\nimport { isolateText } from './controls.js';\nimport { findTechnicalTokenRanges } from './detect.js';\nimport { needsBidiIntervention } from './intervention.js';\nimport type { BidiInterventionMode } from './intervention.js';\nimport type { Direction, DirectionalRun, InlineIsolation } from './types.js';\n\ntype PlannedIsolation = Omit;\n\nfunction attachSourceRanges(text: string, isolations: Omit[]): InlineIsolation[] {\n const codePointAtUtf16 = new Uint32Array(text.length + 1);\n let utf16Offset = 0;\n let codePointOffset = 0;\n for (const character of text) {\n codePointAtUtf16.fill(codePointOffset, utf16Offset, utf16Offset + character.length);\n utf16Offset += character.length;\n codePointOffset += 1;\n }\n codePointAtUtf16.fill(codePointOffset, utf16Offset);\n return isolations.map((isolation) => ({\n ...isolation,\n sourceRange: {\n utf16: { start: isolation.start, end: isolation.end },\n codePoint: {\n start: codePointAtUtf16[isolation.start]!,\n end: codePointAtUtf16[isolation.end]!\n }\n }\n }));\n}\n\nfunction resolveNeutralRuns(runs: DirectionalRun[]): DirectionalRun[] {\n const previousStrong: Direction[] = new Array(runs.length).fill('neutral');\n const nextStrong: Direction[] = new Array(runs.length).fill('neutral');\n let previous: Direction = 'neutral';\n let next: Direction = 'neutral';\n\n for (let index = 0; index < runs.length; index += 1) {\n previousStrong[index] = previous;\n const direction = runs[index]!.direction;\n if (direction !== 'neutral') previous = direction;\n }\n\n for (let index = runs.length - 1; index >= 0; index -= 1) {\n nextStrong[index] = next;\n const direction = runs[index]!.direction;\n if (direction !== 'neutral') next = direction;\n }\n\n return runs.map((run, index) => {\n if (run.direction !== 'neutral') return run;\n const before = previousStrong[index] ?? 'neutral';\n const after = nextStrong[index] ?? 'neutral';\n const direction: Direction = before === after && before !== 'neutral'\n ? before\n : before !== 'neutral'\n ? before\n : after;\n return { ...run, direction };\n });\n}\n\nfunction mergeAdjacent(runs: DirectionalRun[]): DirectionalRun[] {\n const merged: DirectionalRun[] = [];\n for (const run of runs) {\n const previous = merged.at(-1);\n if (previous && previous.direction === run.direction) {\n previous.text += run.text;\n previous.end = run.end;\n } else {\n merged.push({ ...run });\n }\n }\n return merged;\n}\n\nfunction trimNeutralBoundaries(text: string, start: number, end: number): { start: number; end: number } {\n while (start < end) {\n const character = text.slice(start).match(/^./su)?.[0];\n if (!character || classifyCharacter(character) !== 'neutral') break;\n start += character.length;\n }\n while (end > start) {\n const character = text.slice(0, end).match(/.$/su)?.[0];\n if (!character || classifyCharacter(character) !== 'neutral') break;\n end -= character.length;\n }\n return { start, end };\n}\n\nconst HARD_FRAGMENT_SEPARATOR = /[,\u060C;\u061B:!?\u061F|]/u;\n\n/**\n * Punctuation separates semantic LTR fragments in an RTL paragraph, while\n * whitespace joins adjacent fragments into one ordered phrase. Without this\n * normalization, two neighboring isolates such as `page` and `97` are\n * reordered as independent RTL atoms.\n */\nfunction normalizeIsolationPlan(text: string, isolations: PlannedIsolation[]): PlannedIsolation[] {\n const split: PlannedIsolation[] = [];\n for (const isolation of isolations) {\n if (isolation.kind !== 'opposite-direction-run') {\n split.push(isolation);\n continue;\n }\n let pieceStart = isolation.start;\n let cursor = isolation.start;\n for (const character of text.slice(isolation.start, isolation.end)) {\n const index = cursor;\n cursor += character.length;\n if (HARD_FRAGMENT_SEPARATOR.test(character)) {\n const trimmed = trimNeutralBoundaries(text, pieceStart, index);\n if (trimmed.start < trimmed.end) {\n split.push({\n ...isolation,\n text: text.slice(trimmed.start, trimmed.end),\n start: trimmed.start,\n end: trimmed.end\n });\n }\n pieceStart = cursor;\n }\n }\n const trimmed = trimNeutralBoundaries(text, pieceStart, isolation.end);\n if (trimmed.start < trimmed.end) {\n split.push({\n ...isolation,\n text: text.slice(trimmed.start, trimmed.end),\n start: trimmed.start,\n end: trimmed.end\n });\n }\n }\n\n const ordered = split.sort((a, b) => a.start - b.start || a.end - b.end);\n const merged: PlannedIsolation[] = [];\n for (const isolation of ordered) {\n const previous = merged.at(-1);\n if (\n previous &&\n previous.direction === isolation.direction &&\n previous.end <= isolation.start &&\n /^\\s*$/u.test(text.slice(previous.end, isolation.start))\n ) {\n previous.end = isolation.end;\n previous.text = text.slice(previous.start, previous.end);\n if (previous.kind !== isolation.kind) previous.kind = 'opposite-direction-run';\n } else {\n merged.push({ ...isolation });\n }\n }\n return merged;\n}\n\nexport function segmentDirectionalRuns(text: string): DirectionalRun[] {\n if (!text) return [];\n const runs: DirectionalRun[] = [];\n let currentDirection: Direction | null = null;\n let currentText = '';\n let start = 0;\n let index = 0;\n\n for (const character of text) {\n const direction = classifyCharacter(character);\n if (currentDirection === null) {\n currentDirection = direction;\n currentText = character;\n start = index;\n } else if (direction === currentDirection) {\n currentText += character;\n } else {\n runs.push({ text: currentText, direction: currentDirection, start, end: index });\n currentDirection = direction;\n currentText = character;\n start = index;\n }\n index += character.length;\n }\n\n if (currentDirection !== null) {\n runs.push({ text: currentText, direction: currentDirection, start, end: index });\n }\n\n return mergeAdjacent(resolveNeutralRuns(runs));\n}\n\nexport function isolateDirectionalRuns(text: string): string {\n return segmentDirectionalRuns(text)\n .map((run) => isolateText(run.text, run.direction))\n .join('');\n}\n\n/**\n * Plans semantic inline boundaries without changing the stored source text.\n * Technical ranges are isolated first; opposite natural-language runs are\n * then isolated only when they differ from the block's base direction.\n */\nexport function planInlineIsolation(\n text: string,\n blockDirection: Exclude,\n options: {\n excludeTechnicalTokens?: boolean;\n isolateOppositeRuns?: boolean;\n intervention?: BidiInterventionMode | undefined;\n technicalIdentifiers?: readonly string[] | undefined;\n } = {}\n): InlineIsolation[] {\n if (!needsBidiIntervention(text, {\n intervention: options.intervention,\n inheritedDirection: blockDirection\n })) return [];\n const technical = options.excludeTechnicalTokens === false\n ? []\n : findTechnicalTokenRanges(text, options.technicalIdentifiers);\n const isolations: Omit[] = technical.map((range) => ({\n text: range.text,\n direction: 'ltr',\n start: range.start,\n end: range.end,\n kind: range.kind\n }));\n\n if (options.isolateOppositeRuns === false) {\n return attachSourceRanges(text, normalizeIsolationPlan(text, isolations));\n }\n\n let technicalIndex = 0;\n for (const run of segmentDirectionalRuns(text)) {\n if (run.direction === 'neutral' || run.direction === blockDirection) continue;\n while (technicalIndex < technical.length && technical[technicalIndex]!.end <= run.start) {\n technicalIndex += 1;\n }\n let cursor = run.start;\n for (let index = technicalIndex; index < technical.length; index += 1) {\n const range = technical[index]!;\n if (range.end <= cursor) continue;\n if (range.start >= run.end) break;\n const partEnd = Math.min(range.start, run.end);\n if (cursor < partEnd) {\n const trimmed = trimNeutralBoundaries(text, cursor, partEnd);\n if (trimmed.start < trimmed.end) isolations.push({\n text: text.slice(trimmed.start, trimmed.end),\n direction: run.direction,\n start: trimmed.start,\n end: trimmed.end,\n kind: 'opposite-direction-run'\n });\n }\n cursor = Math.max(cursor, range.end);\n if (cursor >= run.end) break;\n }\n if (cursor < run.end) {\n const trimmed = trimNeutralBoundaries(text, cursor, run.end);\n if (trimmed.start < trimmed.end) isolations.push({\n text: text.slice(trimmed.start, trimmed.end),\n direction: run.direction,\n start: trimmed.start,\n end: trimmed.end,\n kind: 'opposite-direction-run'\n });\n }\n }\n\n return attachSourceRanges(text, normalizeIsolationPlan(text, isolations));\n}\n", "import {\n analyzeText,\n needsBidiIntervention,\n planInlineIsolation,\n type BidiInterventionMode,\n type DetectionOptions,\n type ResolvedDirection,\n type TextAnalysis\n} from '@bidilens/core';\n\nexport interface RenderHtmlOptions extends DetectionOptions {\n blockTag?: string;\n containerTag?: string | false;\n blockClassName?: string;\n containerClassName?: string;\n includeDataAttributes?: boolean;\n /** Skip BidiLens markup for LTR-only text in an LTR context. */\n intervention?: BidiInterventionMode;\n}\n\nexport interface RenderedHtmlBlock {\n text: string;\n html: string;\n direction: ResolvedDirection;\n start: number;\n end: number;\n}\n\nexport interface RenderedBidiHtml {\n source: string;\n html: string;\n analysis: TextAnalysis;\n blocks: RenderedHtmlBlock[];\n}\n\nconst SAFE_TAG = /^[a-z][a-z0-9-]*$/u;\nconst SAFE_BLOCK_TAGS = new Set([\n 'address', 'article', 'aside', 'blockquote', 'dd', 'div', 'dt', 'figcaption',\n 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'main', 'nav',\n 'p', 'pre', 'section', 'span', 'td', 'th'\n]);\nconst SAFE_CONTAINER_TAGS = new Set([\n 'article', 'aside', 'blockquote', 'div', 'footer', 'header', 'main', 'nav', 'section', 'span'\n]);\n\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/gu, (character) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": '''\n }[character] ?? character));\n}\n\nfunction checkedTag(value: string, option: string, allowed: ReadonlySet): string {\n const normalized = value.toLowerCase();\n if (!SAFE_TAG.test(normalized) || !allowed.has(normalized)) {\n throw new Error(`${option} must be an allowed non-executable HTML container tag.`);\n }\n return normalized;\n}\n\nfunction classAttribute(value: string | undefined): string {\n return value ? ` class=\"${escapeHtml(value)}\"` : '';\n}\n\nexport function renderInlineBidiHtml(\n source: string,\n direction: ResolvedDirection,\n options: {\n includeDataAttributes?: boolean;\n intervention?: BidiInterventionMode | undefined;\n technicalIdentifiers?: readonly string[] | undefined;\n } = {}\n): string {\n const includeData = options.includeDataAttributes ?? true;\n const isolations = planInlineIsolation(source, direction, {\n intervention: options.intervention,\n technicalIdentifiers: options.technicalIdentifiers\n });\n let html = '';\n let cursor = 0;\n for (const isolation of isolations) {\n html += escapeHtml(source.slice(cursor, isolation.start));\n const tag = isolation.kind === 'code' ? 'code' : 'bdi';\n const data = includeData\n ? ` data-bidilens-isolate=\"\" data-bidilens-kind=\"${isolation.kind}\"${isolation.kind === 'code' ? ' data-bidilens-code=\"\"' : ''}`\n : '';\n html += `<${tag} dir=\"${isolation.direction}\"${data}>${escapeHtml(isolation.text)}`;\n cursor = isolation.end;\n }\n return html + escapeHtml(source.slice(cursor));\n}\n\n/** Serializes untrusted plain text; it never accepts or emits unescaped source HTML. */\nexport function renderBidiHtml(source: string, options: RenderHtmlOptions = {}): RenderedBidiHtml {\n const detection: DetectionOptions = {\n ...options,\n fallback: options.fallback ?? options.inheritedDirection ?? 'ltr'\n };\n const analysis = analyzeText(source, detection);\n const blockTag = checkedTag(options.blockTag ?? 'p', 'blockTag', SAFE_BLOCK_TAGS);\n const includeData = options.includeDataAttributes ?? true;\n const intervene = analysis.paragraphs.some((paragraph) => paragraph.direction === 'rtl')\n || needsBidiIntervention(source, {\n intervention: options.intervention,\n inheritedDirection: options.inheritedDirection\n });\n const blocks = analysis.paragraphs.map((paragraph) => {\n const direction = paragraph.direction === 'neutral'\n ? (options.inheritedDirection ?? 'ltr')\n : paragraph.direction;\n const data = intervene && includeData ? ' data-bidilens-block=\"\"' : '';\n const directionAttribute = intervene ? ` dir=\"${direction}\"` : '';\n const blockClass = classAttribute(options.blockClassName);\n const inline = intervene\n ? renderInlineBidiHtml(paragraph.text, direction, {\n includeDataAttributes: includeData,\n intervention: options.intervention,\n technicalIdentifiers: options.technicalIdentifiers\n })\n : escapeHtml(paragraph.text);\n const html = `<${blockTag}${directionAttribute}${data}${blockClass}>${inline}`;\n return { text: paragraph.text, html, direction, start: paragraph.start, end: paragraph.end };\n });\n\n const serializedBlocks = blocks.map((block, index) => {\n const next = blocks[index + 1];\n const separator = next ? source.slice(block.end, next.start) : '';\n return `${block.html}${escapeHtml(separator)}`;\n }).join('');\n const automaticContainer = blocks.length > 1 ? 'div' : false;\n const container = options.containerTag === undefined ? automaticContainer : options.containerTag;\n const html = container === false\n ? serializedBlocks\n : (() => {\n const tag = checkedTag(container, 'containerTag', SAFE_CONTAINER_TAGS);\n const data = intervene && includeData ? ' data-bidilens-document=\"\"' : '';\n const containerClass = classAttribute(options.containerClassName);\n return `<${tag}${data}${containerClass}>${serializedBlocks}`;\n })();\n return { source, html, analysis, blocks };\n}\n", "{\n \"name\": \"@bidilens/cli\",\n \"version\": \"0.3.1\",\n \"description\": \"CLI for inspecting direction and auditing hidden Unicode bidi controls.\",\n \"license\": \"MIT\",\n \"author\": {\n \"name\": \"Shayan SalehiRad\",\n \"url\": \"https://github.com/CodeinScrubs\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/CodeinScrubs/BidiLens.git\",\n \"directory\": \"packages/cli\"\n },\n \"homepage\": \"https://github.com/CodeinScrubs/BidiLens#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/CodeinScrubs/BidiLens/issues\"\n },\n \"type\": \"module\",\n \"sideEffects\": false,\n \"keywords\": [\n \"bidi\",\n \"rtl\",\n \"ltr\",\n \"unicode\",\n \"cli\",\n \"security\"\n ],\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\",\n \"CHANGELOG.md\",\n \"THIRD_PARTY_NOTICES.md\",\n \"corpus\",\n \"examples\"\n ],\n \"bin\": {\n \"bidilens\": \"./dist/bin.js\"\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/bin.ts --format esm --dts --clean --sourcemap\",\n \"prepack\": \"pnpm run build\",\n \"example\": \"node examples/basic.mjs\"\n },\n \"dependencies\": {\n \"@bidilens/core\": \"workspace:*\",\n \"@bidilens/html\": \"workspace:*\",\n \"commander\": \"^15.0.0\"\n },\n \"devDependencies\": {\n \"tsup\": \"^8.5.1\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"], - "mappings": "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AA,EAAM;AAAA,EACN;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAU;AACZ;AAEO,IAAM,wBAA+C;AAAA,EAC1D;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT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", + "sources": ["../src/main.ts", "../src/index.ts", "../../packages/cli/src/index.ts", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/argument.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/command.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/help.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/option.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/suggestSimilar.js", "../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/index.js", "../../packages/core/src/generated/bidi-ranges.ts", "../../packages/core/src/classify.ts", "../../packages/core/src/options.ts", "../../packages/core/src/paragraph.ts", "../../packages/core/src/detect.ts", "../../packages/core/src/security.ts", "../../packages/core/src/intervention.ts", "../../packages/core/src/segments.ts", "../../packages/html/src/index.ts", "../../packages/cli/package.json"], + "sourcesContent": ["import process from 'node:process';\nimport { runAction, workflowError } from './index.js';\n\nasync function main(): Promise {\n try {\n const result = await runAction();\n process.exitCode = result.exitCode;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${workflowError(message)}\\n`);\n process.exitCode = 1;\n }\n}\n\nvoid main();\n", "import { appendFile, mkdir, writeFile } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport process from 'node:process';\nimport { runCli } from '../../packages/cli/src/index.js';\n\nexport type ActionCommand = 'audit' | 'test';\nexport type ActionFormat = 'human' | 'json' | 'sarif';\nexport type ActionMode = 'off' | 'audit' | 'warn' | 'strict';\nexport type ActionRisk = 'low' | 'medium' | 'high';\n\nexport interface ActionInputs {\n command: ActionCommand;\n paths: string[];\n corpus: string;\n mode: ActionMode;\n failOn: ActionRisk;\n format: ActionFormat;\n sarifFile: string;\n}\n\nexport interface ActionContext {\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n log?: (value: string) => void;\n error?: (value: string) => void;\n}\n\nexport interface ActionResult {\n exitCode: number;\n report: string;\n stdout: string;\n stderr: string;\n}\n\nfunction input(env: NodeJS.ProcessEnv, name: string): string {\n return env[`INPUT_${name.toUpperCase()}`]?.trim() ?? '';\n}\n\nfunction choice(\n name: string,\n value: string,\n fallback: Value,\n allowed: readonly Value[]\n): Value {\n const candidate = value || fallback;\n if (!allowed.includes(candidate as Value)) {\n throw new Error(`${name} must be one of ${allowed.join(', ')}; received ${JSON.stringify(candidate)}.`);\n }\n return candidate as Value;\n}\n\nexport function readActionInputs(env: NodeJS.ProcessEnv = process.env): ActionInputs {\n return {\n command: choice('command', input(env, 'COMMAND'), 'audit', ['audit', 'test']),\n paths: (input(env, 'PATHS') || '.').split(/\\r?\\n/u).map((path) => path.trim()).filter(Boolean),\n corpus: input(env, 'CORPUS'),\n mode: choice('mode', input(env, 'MODE'), 'audit', ['off', 'audit', 'warn', 'strict']),\n failOn: choice('fail-on', input(env, 'FAIL-ON'), 'high', ['low', 'medium', 'high']),\n format: choice('format', input(env, 'FORMAT'), 'human', ['human', 'json', 'sarif']),\n sarifFile: input(env, 'SARIF-FILE') || 'bidilens.sarif'\n };\n}\n\nexport function buildCliArguments(inputs: ActionInputs, env: NodeJS.ProcessEnv = process.env): string[] {\n if (inputs.command === 'test') {\n if (inputs.format === 'sarif') throw new Error('SARIF output is available only for the audit command.');\n const actionPath = env.GITHUB_ACTION_PATH\n ? resolve(env.GITHUB_ACTION_PATH)\n : resolve(env.GITHUB_WORKSPACE ?? process.cwd(), 'action');\n const corpus = inputs.corpus || resolve(actionPath, '..', 'corpus', 'cases.json');\n return ['node', 'bidilens', 'test', '--corpus', corpus, ...(inputs.format === 'json' ? ['--json'] : [])];\n }\n\n const format = inputs.format === 'json' ? ['--json'] : inputs.format === 'sarif' ? ['--sarif'] : [];\n return [\n 'node', 'bidilens', 'audit', ...inputs.paths,\n '--mode', inputs.mode,\n '--fail-on', inputs.failOn,\n ...format\n ];\n}\n\nfunction workspaceFile(cwd: string, requested: string): { absolute: string; relative: string } {\n const absolute = resolve(cwd, requested);\n const local = relative(cwd, absolute);\n if (!local || local.startsWith('..') || isAbsolute(local)) {\n throw new Error('sarif-file must resolve to a file inside GITHUB_WORKSPACE.');\n }\n return { absolute, relative: local.replaceAll('\\\\', '/') };\n}\n\nasync function setOutput(path: string | undefined, name: string, value: string): Promise {\n if (!path) return;\n const delimiter = `bidilens_${randomUUID()}`;\n await appendFile(path, `${name}<<${delimiter}\\n${value}\\n${delimiter}\\n`, 'utf8');\n}\n\n/** Executes the bundled CLI without a shell and propagates its real exit code. */\nexport async function runAction(context: ActionContext = {}): Promise {\n const env = context.env ?? process.env;\n const cwd = resolve(context.cwd ?? env.GITHUB_WORKSPACE ?? process.cwd());\n const log = context.log ?? console.log;\n const error = context.error ?? console.error;\n const inputs = readActionInputs(env);\n const stdout: string[] = [];\n const stderr: string[] = [];\n const exitCode = await runCli(buildCliArguments(inputs, env), {\n cwd,\n stdout: (value) => stdout.push(value),\n stderr: (value) => stderr.push(value)\n });\n const stdoutText = stdout.join('');\n const stderrText = stderr.join('');\n let report = '';\n\n if (inputs.format === 'sarif') {\n const target = workspaceFile(cwd, inputs.sarifFile);\n await mkdir(dirname(target.absolute), { recursive: true });\n await writeFile(target.absolute, stdoutText, 'utf8');\n report = target.relative;\n log(`BidiLens SARIF report written to ${report}.`);\n } else if (stdoutText) {\n log(stdoutText.trimEnd());\n }\n if (stderrText) error(stderrText.trimEnd());\n\n await setOutput(env.GITHUB_OUTPUT, 'exit-code', String(exitCode));\n await setOutput(env.GITHUB_OUTPUT, 'report', report);\n if (exitCode !== 0) error(`BidiLens ${inputs.command} failed with exit code ${exitCode}.`);\n return { exitCode, report, stdout: stdoutText, stderr: stderrText };\n}\n\nexport function workflowError(message: string): string {\n const escaped = message\n .replaceAll('%', '%25')\n .replaceAll('\\r', '%0D')\n .replaceAll('\\n', '%0A');\n return `::error title=BidiLens::${escaped}`;\n}\n", "#!/usr/bin/env node\nimport { lstat, readFile, readdir, writeFile } from 'node:fs/promises';\nimport { basename, extname, isAbsolute, relative, resolve } from 'node:path';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport { Command, CommanderError } from 'commander';\nimport { renderBidiHtml } from '@bidilens/html';\nimport packageManifest from '../package.json' with { type: 'json' };\nimport {\n DEFAULT_PARAGRAPH_SEPARATOR_SOURCE,\n analyzeText,\n findBidiControls,\n sanitizeBidiControls,\n scanBidiSecurity,\n visibleBidiControls,\n type BidiControlRisk,\n type BidiInterventionMode,\n type BidiSecurityFinding,\n type BidiSecurityMode\n} from '@bidilens/core';\n\nconst SUPPORTED_EXTENSIONS = new Set([\n '.md', '.mdx', '.txt', '.html', '.htm', '.json', '.yaml', '.yml',\n '.js', '.jsx', '.ts', '.tsx', '.css', '.scss', '.py', '.go', '.rs',\n '.java', '.kt', '.swift', '.c', '.cc', '.cpp', '.h', '.hpp', '.toml',\n '.vue', '.svelte', '.astro', '.dart', '.xml', '.svg', '.sh', '.bash',\n '.zsh', '.fish', '.cs', '.fs', '.fsx', '.vb', '.rb', '.php', '.sql',\n '.ini', '.conf', '.properties', '.gradle', '.groovy', '.lua', '.pl', '.r',\n '.ex', '.exs', '.erl', '.hrl'\n]);\n\nconst SUPPORTED_BASENAMES = new Set([\n 'dockerfile', 'makefile', 'gemfile', 'podfile', 'rakefile', 'cmakelists.txt',\n 'build', 'workspace', '.env'\n]);\n\nconst IGNORED_DIRECTORIES = new Set([\n 'node_modules', '.git', 'dist', 'build', 'coverage', 'test-results',\n 'playwright-report', '.vite', '.next', '.nuxt', '.svelte-kit', '.output'\n]);\n\nconst RISK_ORDER: Record = { low: 1, medium: 2, high: 3 };\nconst CLI_VERSION = packageManifest.version;\n\ninterface CorpusCase {\n id: string;\n text: string;\n expected: 'ltr' | 'rtl' | 'neutral';\n}\n\nexport interface CliRuntime {\n cwd?: string;\n stdout?: (value: string) => void;\n stderr?: (value: string) => void;\n}\n\ninterface RuntimeState {\n cwd: string;\n stdout: (value: string) => void;\n stderr: (value: string) => void;\n exitCode: number;\n}\n\nfunction createRuntime(runtime: CliRuntime): RuntimeState {\n return {\n cwd: resolve(runtime.cwd ?? process.cwd()),\n stdout: runtime.stdout ?? ((value) => process.stdout.write(value)),\n stderr: runtime.stderr ?? ((value) => process.stderr.write(value)),\n exitCode: 0\n };\n}\n\nfunction line(writer: (value: string) => void, value = ''): void {\n writer(`${value}\\n`);\n}\n\nasync function collectFiles(inputs: string[], cwd: string): Promise {\n const files: string[] = [];\n async function visitPath(input: string, explicitlyNamed: boolean): Promise {\n const absolute = resolve(cwd, input);\n const info = await lstat(absolute);\n if (info.isSymbolicLink()) return;\n if (info.isDirectory()) {\n const entries = await readdir(absolute, { withFileTypes: true });\n entries.sort((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n if (IGNORED_DIRECTORIES.has(entry.name.toLowerCase())) continue;\n if (entry.isSymbolicLink()) continue;\n await visitPath(resolve(absolute, entry.name), false);\n }\n return;\n }\n const name = basename(absolute).toLowerCase();\n const supportedName = SUPPORTED_BASENAMES.has(name) || name.startsWith('.env.');\n if (info.isFile() && (explicitlyNamed || supportedName || SUPPORTED_EXTENSIONS.has(extname(absolute).toLowerCase()))) {\n files.push(absolute);\n }\n }\n for (const input of inputs) await visitPath(input, true);\n return files.sort((a, b) => a.localeCompare(b));\n}\n\nfunction parseCorpus(source: string, location: string): CorpusCase[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(source);\n } catch (error) {\n throw new Error(`${location} is not valid JSON. ${String(error)}`, { cause: error });\n }\n if (!Array.isArray(parsed)) throw new Error(`${location} must contain a JSON array.`);\n const ids = new Set();\n return parsed.map((item: unknown, index) => {\n if (typeof item !== 'object' || item === null) {\n throw new Error(`${location}: case ${index + 1} must be an object.`);\n }\n const candidate = item as Record;\n if (typeof candidate.id !== 'string' || candidate.id.length === 0) {\n throw new Error(`${location}: case ${index + 1} must have a non-empty string id.`);\n }\n if (ids.has(candidate.id)) throw new Error(`${location}: duplicate case id \"${candidate.id}\".`);\n ids.add(candidate.id);\n if (typeof candidate.text !== 'string') {\n throw new Error(`${location}: case \"${candidate.id}\" must have string text.`);\n }\n if (candidate.expected !== 'ltr' && candidate.expected !== 'rtl' && candidate.expected !== 'neutral') {\n throw new Error(`${location}: case \"${candidate.id}\" has invalid expected direction.`);\n }\n return { id: candidate.id, text: candidate.text, expected: candidate.expected };\n });\n}\n\nasync function readCorpus(cwd: string, explicitPath?: string): Promise {\n if (explicitPath !== undefined) {\n const location = resolve(cwd, explicitPath);\n return parseCorpus(await readFile(location, 'utf8'), location);\n }\n const candidates: Array = [\n resolve(cwd, 'corpus/cases.json'),\n new URL('../corpus/cases.json', import.meta.url),\n new URL('../../../corpus/cases.json', import.meta.url)\n ];\n let lastError: unknown;\n for (const candidate of candidates) {\n let source: string;\n try {\n source = await readFile(candidate, 'utf8');\n } catch (error) {\n lastError = error;\n continue;\n }\n // An existing, malformed higher-priority corpus is a configuration error,\n // not a reason to silently fall back to a different data set.\n return parseCorpus(source, String(candidate));\n }\n throw new Error(`Unable to locate corpus/cases.json. Pass --corpus . ${String(lastError)}`);\n}\n\nfunction parseRisk(value: string): BidiControlRisk {\n if (value === 'low' || value === 'medium' || value === 'high') return value;\n throw new Error(`Invalid risk level: ${value}`);\n}\n\nfunction parseSecurityMode(value: string): BidiSecurityMode {\n if (value === 'off' || value === 'audit' || value === 'warn' || value === 'strict') return value;\n throw new Error(`Invalid security mode: ${value}`);\n}\n\nfunction parseIntervention(value: string): BidiInterventionMode {\n if (value === 'auto' || value === 'always') return value;\n throw new Error(`Invalid intervention mode: ${value}`);\n}\n\nfunction riskForFinding(finding: BidiSecurityFinding): BidiControlRisk {\n if (finding.severity === 'high') return 'high';\n if (finding.severity === 'warning') return 'medium';\n return 'low';\n}\n\nfunction highestFindingRisk(findings: readonly BidiSecurityFinding[]): BidiControlRisk | null {\n if (findings.some((finding) => finding.severity === 'high')) return 'high';\n if (findings.some((finding) => finding.severity === 'warning')) return 'medium';\n if (findings.length) return 'low';\n return null;\n}\n\nfunction sourcePosition(text: string, utf16Offset: number): { line: number; column: number } {\n let lineNumber = 1;\n let lineStart = 0;\n // Include Unicode paragraph separators plus U+2028 (line separator) so\n // SARIF locations remain line-aware for every supported Unicode boundary.\n const newline = new RegExp(`${DEFAULT_PARAGRAPH_SEPARATOR_SOURCE}|\\\\u2028`, 'gu');\n let match: RegExpExecArray | null;\n while ((match = newline.exec(text)) !== null && match.index < utf16Offset) {\n lineNumber += 1;\n lineStart = match.index + match[0].length;\n }\n return { line: lineNumber, column: utf16Offset - lineStart + 1 };\n}\n\nfunction artifactUri(file: string, cwd: string): string {\n const local = relative(cwd, file);\n if (local && !local.startsWith('..') && !isAbsolute(local)) return local.replaceAll('\\\\', '/');\n return pathToFileURL(file).href;\n}\n\ninterface SecurityFileReport {\n file: string;\n text: string;\n findings: BidiSecurityFinding[];\n highestRisk: BidiControlRisk | null;\n}\n\nasync function readTextInput(\n options: { text?: string; file?: string },\n cwd: string\n): Promise {\n if (options.text === undefined && options.file === undefined) {\n throw new Error('Provide --text or --file.');\n }\n if (options.text !== undefined && options.file !== undefined) {\n throw new Error('Choose either --text or --file, not both.');\n }\n return options.file !== undefined\n ? readFile(resolve(cwd, options.file), 'utf8')\n : options.text!;\n}\n\nfunction sarifForReports(reports: readonly SecurityFileReport[], cwd: string): object {\n return {\n version: '2.1.0',\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n runs: [{\n columnKind: 'utf16CodeUnits',\n tool: { driver: { name: 'BidiLens', semanticVersion: CLI_VERSION } },\n results: reports.flatMap((report) => report.findings.map((finding) => {\n const start = sourcePosition(report.text, finding.sourceRange.utf16.start);\n const end = sourcePosition(report.text, finding.sourceRange.utf16.end);\n return {\n ruleId: finding.code,\n level: finding.severity === 'high' ? 'error' : finding.severity === 'warning' ? 'warning' : 'note',\n message: { text: `${finding.message} ${finding.remediation}` },\n locations: [{\n physicalLocation: {\n artifactLocation: { uri: artifactUri(report.file, cwd) },\n region: {\n startLine: start.line,\n startColumn: start.column,\n endLine: end.line,\n endColumn: end.column\n }\n }\n }]\n };\n }))\n }]\n };\n}\n\nfunction createCliProgram(state: RuntimeState): Command {\n const program = new Command();\n program\n .name('bidilens')\n .description('Inspect and secure mixed bidirectional text')\n .version(CLI_VERSION)\n .exitOverride()\n .configureOutput({ writeOut: state.stdout, writeErr: state.stderr });\n\n program.command('inspect')\n .description('Analyze a string or file')\n .option('-t, --text ', 'text to inspect')\n .option('-f, --file ', 'file to inspect')\n .option('--json', 'emit JSON')\n .action(async (options: { text?: string; file?: string; json?: boolean }) => {\n const text = await readTextInput(options, state.cwd);\n const analysis = analyzeText(text, { strategy: 'content-majority', fallback: 'neutral' });\n const controls = findBidiControls(text);\n const report = { analysis, controls, visible: controls.length ? visibleBidiControls(text) : text };\n if (options.json) line(state.stdout, JSON.stringify(report, null, 2));\n else {\n line(state.stdout, `Direction: ${analysis.direction}`);\n line(state.stdout, `Confidence: ${analysis.confidence}`);\n line(state.stdout, `Strong characters: RTL ${analysis.counts.rtl}, LTR ${analysis.counts.ltr}`);\n line(state.stdout, `Paragraphs: ${analysis.paragraphs.length}`);\n line(state.stdout, `Bidi controls: ${controls.length}`);\n if (controls.length) line(state.stdout, report.visible);\n }\n });\n\n program.command('render')\n .description('Render plain text as escaped, semantic direction-aware HTML')\n .option('-t, --text ', 'text to render')\n .option('-f, --file ', 'file to render')\n .option('--intervention ', 'auto or always', parseIntervention, 'auto')\n .option('--json', 'emit analysis and HTML as JSON')\n .action(async (options: {\n text?: string;\n file?: string;\n intervention: BidiInterventionMode;\n json?: boolean;\n }) => {\n const text = await readTextInput(options, state.cwd);\n const result = renderBidiHtml(text, { intervention: options.intervention });\n line(state.stdout, options.json\n ? JSON.stringify({ analysis: result.analysis, html: result.html }, null, 2)\n : result.html);\n });\n\n program.command('audit')\n .aliases(['security-scan', 'lint'])\n .description('Audit files for hidden and unbalanced bidi controls')\n .argument('', 'files or directories')\n .option('--json', 'emit JSON')\n .option('--sarif', 'emit SARIF 2.1.0')\n .option('--mode ', 'off, audit, warn, or strict', parseSecurityMode, 'audit')\n .option('--fail-on ', 'minimum risk that exits non-zero', parseRisk, 'high')\n .action(async (paths: string[], options: {\n json?: boolean;\n sarif?: boolean;\n mode: BidiSecurityMode;\n failOn: BidiControlRisk;\n }) => {\n if (options.json && options.sarif) throw new Error('Choose either --json or --sarif, not both.');\n const files = await collectFiles(paths, state.cwd);\n const reports: SecurityFileReport[] = [];\n let shouldFail = false;\n\n for (const file of files) {\n const text = await readFile(file, 'utf8');\n const security = scanBidiSecurity(text, { mode: options.mode });\n if (!security.findings.length) continue;\n const highestRisk = highestFindingRisk(security.findings);\n reports.push({ file, text, findings: security.findings, highestRisk });\n if (security.shouldBlock || (highestRisk && RISK_ORDER[highestRisk] >= RISK_ORDER[options.failOn])) shouldFail = true;\n }\n\n if (options.sarif) line(state.stdout, JSON.stringify(sarifForReports(reports, state.cwd), null, 2));\n else if (options.json) {\n line(state.stdout, JSON.stringify({\n scanned: files.length,\n reports: reports.map((report) => ({\n file: report.file,\n findings: report.findings,\n highestRisk: report.highestRisk\n }))\n }, null, 2));\n } else if (!reports.length) line(state.stdout, `No bidi security findings in ${files.length} files.`);\n else {\n for (const report of reports) {\n line(state.stdout, `\\n${report.file} (${report.highestRisk ?? 'unknown'})`);\n for (const finding of report.findings) {\n const position = sourcePosition(report.text, finding.sourceRange.utf16.start);\n line(state.stdout, ` ${finding.code} at ${position.line}:${position.column} [${riskForFinding(finding)}] ${finding.message}`);\n }\n }\n }\n if (shouldFail) state.exitCode = Math.max(state.exitCode, 2);\n });\n\n program.command('test')\n .description('Run the direction conformance corpus')\n .option('--json', 'emit failures as JSON')\n .option('--corpus ', 'corpus JSON path; defaults to the bundled corpus or repository corpus')\n .action(async (options: { json?: boolean; corpus?: string }) => {\n const corpus = await readCorpus(state.cwd, options.corpus);\n const failures = corpus.flatMap((item) => {\n const actual = analyzeText(item.text, { strategy: 'content-majority', fallback: 'neutral' }).direction;\n return actual === item.expected ? [] : [{ id: item.id, expected: item.expected, actual }];\n });\n if (options.json) line(state.stdout, JSON.stringify({ total: corpus.length, failures }, null, 2));\n else line(state.stdout, `Corpus: ${corpus.length - failures.length}/${corpus.length} passed`);\n if (failures.length) state.exitCode = Math.max(state.exitCode, 1);\n });\n\n program.command('sanitize')\n .description('Remove bidi controls from one file')\n .argument('', 'input file')\n .option('-o, --output ', 'output path; defaults to stdout')\n .option('--keep-low', 'preserve low-risk ALM/LRM/RLM marks')\n .action(async (file: string, options: { output?: string; keepLow?: boolean }) => {\n const text = await readFile(resolve(state.cwd, file), 'utf8');\n const remove: BidiControlRisk[] = options.keepLow ? ['high', 'medium'] : ['high', 'medium', 'low'];\n const result = sanitizeBidiControls(text, { remove });\n if (options.output) {\n const output = resolve(state.cwd, options.output);\n await writeFile(output, result.text, 'utf8');\n line(state.stderr, `Removed ${result.removed.length} controls and wrote ${output}.`);\n } else {\n state.stdout(result.text);\n }\n });\n\n return program;\n}\n\nexport async function runCli(argv: readonly string[] = process.argv, runtime: CliRuntime = {}): Promise {\n const state = createRuntime(runtime);\n const program = createCliProgram(state);\n try {\n await program.parseAsync([...argv], { from: 'node' });\n } catch (error) {\n if (error instanceof CommanderError) return Math.max(state.exitCode, error.exitCode);\n const message = error instanceof Error ? error.message : String(error);\n line(state.stderr, `bidilens: ${message}`);\n return Math.max(state.exitCode, 1);\n }\n return state.exitCode;\n}\n", "/**\n * CommanderError class\n */\nexport class CommanderError extends Error {\n /**\n * Constructs the CommanderError class\n * @param {number} exitCode suggested exit code which could be used with process.exit\n * @param {string} code an id string representing the error\n * @param {string} message human-readable description of the error\n */\n constructor(exitCode, code, message) {\n super(message);\n // properly capture stack trace in Node.js\n Error.captureStackTrace(this, this.constructor);\n this.name = this.constructor.name;\n this.code = code;\n this.exitCode = exitCode;\n this.nestedError = undefined;\n }\n}\n\n/**\n * InvalidArgumentError class\n */\nexport class InvalidArgumentError extends CommanderError {\n /**\n * Constructs the InvalidArgumentError class\n * @param {string} [message] explanation of why argument is invalid\n */\n constructor(message) {\n super(1, 'commander.invalidArgument', message);\n // properly capture stack trace in Node.js\n Error.captureStackTrace(this, this.constructor);\n this.name = this.constructor.name;\n }\n}\n", "import { InvalidArgumentError } from './error.js';\n\nexport class Argument {\n /**\n * Initialize a new command argument with the given name and description.\n * The default is that the argument is required, and you can explicitly\n * indicate this with <> around the name. Put [] around the name for an optional argument.\n *\n * @param {string} name\n * @param {string} [description]\n */\n\n constructor(name, description) {\n this.description = description || '';\n this.variadic = false;\n this.parseArg = undefined;\n this.defaultValue = undefined;\n this.defaultValueDescription = undefined;\n this.argChoices = undefined;\n\n switch (name[0]) {\n case '<': // e.g. \n this.required = true;\n this._name = name.slice(1, -1);\n break;\n case '[': // e.g. [optional]\n this.required = false;\n this._name = name.slice(1, -1);\n break;\n default:\n this.required = true;\n this._name = name;\n break;\n }\n\n if (this._name.endsWith('...')) {\n this.variadic = true;\n this._name = this._name.slice(0, -3);\n }\n }\n\n /**\n * Return argument name.\n *\n * @return {string}\n */\n\n name() {\n return this._name;\n }\n\n /**\n * @package\n */\n\n _collectValue(value, previous) {\n if (previous === this.defaultValue || !Array.isArray(previous)) {\n return [value];\n }\n\n previous.push(value);\n return previous;\n }\n\n /**\n * Set the default value, and optionally supply the description to be displayed in the help.\n *\n * @param {*} value\n * @param {string} [description]\n * @return {Argument}\n */\n\n default(value, description) {\n this.defaultValue = value;\n this.defaultValueDescription = description;\n return this;\n }\n\n /**\n * Set the custom handler for processing CLI command arguments into argument values.\n *\n * @param {Function} [fn]\n * @return {Argument}\n */\n\n argParser(fn) {\n this.parseArg = fn;\n return this;\n }\n\n /**\n * Only allow argument value to be one of choices.\n *\n * @param {string[]} values\n * @return {Argument}\n */\n\n choices(values) {\n this.argChoices = values.slice();\n this.parseArg = (arg, previous) => {\n if (!this.argChoices.includes(arg)) {\n throw new InvalidArgumentError(\n `Allowed choices are ${this.argChoices.join(', ')}.`,\n );\n }\n if (this.variadic) {\n return this._collectValue(arg, previous);\n }\n return arg;\n };\n return this;\n }\n\n /**\n * Make argument required.\n *\n * @returns {Argument}\n */\n argRequired() {\n this.required = true;\n return this;\n }\n\n /**\n * Make argument optional.\n *\n * @returns {Argument}\n */\n argOptional() {\n this.required = false;\n return this;\n }\n}\n\n/**\n * Takes an argument and returns its human readable equivalent for help usage.\n *\n * @param {Argument} arg\n * @return {string}\n * @private\n */\n\nexport function humanReadableArgName(arg) {\n const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');\n\n return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']';\n}\n", "import { EventEmitter } from 'node:events';\nimport childProcess from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport process from 'node:process';\nimport { stripVTControlCharacters } from 'node:util';\n\nimport { Argument, humanReadableArgName } from './argument.js';\nimport { CommanderError } from './error.js';\nimport { Help } from './help.js';\nimport { Option, DualOptions } from './option.js';\nimport { suggestSimilar } from './suggestSimilar.js';\n\nexport class Command extends EventEmitter {\n /**\n * Initialize a new `Command`.\n *\n * @param {string} [name]\n */\n\n constructor(name) {\n super();\n /** @type {Command[]} */\n this.commands = [];\n /** @type {Option[]} */\n this.options = [];\n this.parent = null;\n this._allowUnknownOption = false;\n this._allowExcessArguments = false;\n /** @type {Argument[]} */\n this.registeredArguments = [];\n this._args = this.registeredArguments; // deprecated old name\n /** @type {string[]} */\n this.args = []; // cli args with options removed\n this.rawArgs = [];\n this.processedArgs = []; // like .args but after custom processing and collecting variadic\n this._scriptPath = null;\n this._name = name || '';\n this._optionValues = {};\n this._optionValueSources = {}; // default, env, cli etc\n this._storeOptionsAsProperties = false;\n this._actionHandler = null;\n this._executableHandler = false;\n this._executableFile = null; // custom name for executable\n this._executableDir = null; // custom search directory for subcommands\n this._defaultCommandName = null;\n this._exitCallback = null;\n this._aliases = [];\n this._combineFlagAndOptionalValue = true;\n this._description = '';\n this._summary = '';\n this._argsDescription = undefined; // legacy\n this._enablePositionalOptions = false;\n this._passThroughOptions = false;\n this._lifeCycleHooks = {}; // a hash of arrays\n /** @type {(boolean | string)} */\n this._showHelpAfterError = false;\n this._showSuggestionAfterError = true;\n this._savedState = null; // used in save/restoreStateBeforeParse\n\n // see configureOutput() for docs\n this._outputConfiguration = {\n writeOut: (str) => process.stdout.write(str),\n writeErr: (str) => process.stderr.write(str),\n outputError: (str, write) => write(str),\n getOutHelpWidth: () =>\n process.stdout.isTTY ? process.stdout.columns : undefined,\n getErrHelpWidth: () =>\n process.stderr.isTTY ? process.stderr.columns : undefined,\n getOutHasColors: () =>\n useColor() ?? (process.stdout.isTTY && process.stdout.hasColors?.()),\n getErrHasColors: () =>\n useColor() ?? (process.stderr.isTTY && process.stderr.hasColors?.()),\n stripColor: (str) => stripVTControlCharacters(str),\n };\n\n this._hidden = false;\n /** @type {(Option | null | undefined)} */\n this._helpOption = undefined; // Lazy created on demand. May be null if help option is disabled.\n this._addImplicitHelpCommand = undefined; // undecided whether true or false yet, not inherited\n /** @type {Command} */\n this._helpCommand = undefined; // lazy initialised, inherited\n this._helpConfiguration = {};\n /** @type {string | undefined} */\n this._helpGroupHeading = undefined; // soft initialised when added to parent\n /** @type {string | undefined} */\n this._defaultCommandGroup = undefined;\n /** @type {string | undefined} */\n this._defaultOptionGroup = undefined;\n }\n\n /**\n * Copy settings that are useful to have in common across root command and subcommands.\n *\n * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.)\n *\n * @param {Command} sourceCommand\n * @return {Command} `this` command for chaining\n */\n copyInheritedSettings(sourceCommand) {\n this._outputConfiguration = sourceCommand._outputConfiguration;\n this._helpOption = sourceCommand._helpOption;\n this._helpCommand = sourceCommand._helpCommand;\n this._helpConfiguration = sourceCommand._helpConfiguration;\n this._exitCallback = sourceCommand._exitCallback;\n this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;\n this._combineFlagAndOptionalValue =\n sourceCommand._combineFlagAndOptionalValue;\n this._allowExcessArguments = sourceCommand._allowExcessArguments;\n this._enablePositionalOptions = sourceCommand._enablePositionalOptions;\n this._showHelpAfterError = sourceCommand._showHelpAfterError;\n this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;\n\n return this;\n }\n\n /**\n * @returns {Command[]}\n * @private\n */\n\n _getCommandAndAncestors() {\n const result = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n for (let command = this; command; command = command.parent) {\n result.push(command);\n }\n return result;\n }\n\n /**\n * Define a command.\n *\n * There are two styles of command: pay attention to where to put the description.\n *\n * @example\n * // Command implemented using action handler (description is supplied separately to `.command`)\n * program\n * .command('clone [destination]')\n * .description('clone a repository into a newly created directory')\n * .action((source, destination) => {\n * console.log('clone command called');\n * });\n *\n * // Command implemented using separate executable file (description is second parameter to `.command`)\n * program\n * .command('start ', 'start named service')\n * .command('stop [service]', 'stop named service, or all if no name supplied');\n *\n * @param {string} nameAndArgs - command name and arguments, args are `` or `[optional]` and last may also be `variadic...`\n * @param {(object | string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)\n * @param {object} [execOpts] - configuration options (for executable)\n * @return {Command} returns new command for action handler, or `this` for executable command\n */\n\n command(nameAndArgs, actionOptsOrExecDesc, execOpts) {\n let desc = actionOptsOrExecDesc;\n let opts = execOpts;\n if (typeof desc === 'object' && desc !== null) {\n opts = desc;\n desc = null;\n }\n opts = opts || {};\n const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);\n\n const cmd = this.createCommand(name);\n if (desc) {\n cmd.description(desc);\n cmd._executableHandler = true;\n }\n if (opts.isDefault) this._defaultCommandName = cmd._name;\n cmd._hidden = !!(opts.noHelp || opts.hidden); // noHelp is deprecated old name for hidden\n cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor\n if (args) cmd.arguments(args);\n this._registerCommand(cmd);\n cmd.parent = this;\n cmd.copyInheritedSettings(this);\n\n if (desc) return this;\n return cmd;\n }\n\n /**\n * Factory routine to create a new unattached command.\n *\n * See .command() for creating an attached subcommand, which uses this routine to\n * create the command. You can override createCommand to customise subcommands.\n *\n * @param {string} [name]\n * @return {Command} new command\n */\n\n createCommand(name) {\n return new Command(name);\n }\n\n /**\n * You can customise the help with a subclass of Help by overriding createHelp,\n * or by overriding Help properties using configureHelp().\n *\n * @return {Help}\n */\n\n createHelp() {\n return Object.assign(new Help(), this.configureHelp());\n }\n\n /**\n * You can customise the help by overriding Help properties using configureHelp(),\n * or with a subclass of Help by overriding createHelp().\n *\n * @param {object} [configuration] - configuration options\n * @return {(Command | object)} `this` command for chaining, or stored configuration\n */\n\n configureHelp(configuration) {\n if (configuration === undefined) return this._helpConfiguration;\n\n this._helpConfiguration = configuration;\n return this;\n }\n\n /**\n * The default output goes to stdout and stderr. You can customise this for special\n * applications. You can also customise the display of errors by overriding outputError.\n *\n * The configuration properties are all functions:\n *\n * // change how output being written, defaults to stdout and stderr\n * writeOut(str)\n * writeErr(str)\n * // change how output being written for errors, defaults to writeErr\n * outputError(str, write) // used for displaying errors and not used for displaying help\n * // specify width for wrapping help\n * getOutHelpWidth()\n * getErrHelpWidth()\n * // color support, currently only used with Help\n * getOutHasColors()\n * getErrHasColors()\n * stripColor() // used to remove ANSI escape codes if output does not have colors\n *\n * @param {object} [configuration] - configuration options\n * @return {(Command | object)} `this` command for chaining, or stored configuration\n */\n\n configureOutput(configuration) {\n if (configuration === undefined) return this._outputConfiguration;\n\n this._outputConfiguration = {\n ...this._outputConfiguration,\n ...configuration,\n };\n return this;\n }\n\n /**\n * Display the help or a custom message after an error occurs.\n *\n * @param {(boolean|string)} [displayHelp]\n * @return {Command} `this` command for chaining\n */\n showHelpAfterError(displayHelp = true) {\n if (typeof displayHelp !== 'string') displayHelp = !!displayHelp;\n this._showHelpAfterError = displayHelp;\n return this;\n }\n\n /**\n * Display suggestion of similar commands for unknown commands, or options for unknown options.\n *\n * @param {boolean} [displaySuggestion]\n * @return {Command} `this` command for chaining\n */\n showSuggestionAfterError(displaySuggestion = true) {\n this._showSuggestionAfterError = !!displaySuggestion;\n return this;\n }\n\n /**\n * Add a prepared subcommand.\n *\n * See .command() for creating an attached subcommand which inherits settings from its parent.\n *\n * @param {Command} cmd - new subcommand\n * @param {object} [opts] - configuration options\n * @return {Command} `this` command for chaining\n */\n\n addCommand(cmd, opts) {\n if (!cmd._name) {\n throw new Error(`Command passed to .addCommand() must have a name\n- specify the name in Command constructor or using .name()`);\n }\n\n opts = opts || {};\n if (opts.isDefault) this._defaultCommandName = cmd._name;\n if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation\n\n this._registerCommand(cmd);\n cmd.parent = this;\n cmd._checkForBrokenPassThrough();\n\n return this;\n }\n\n /**\n * Factory routine to create a new unattached argument.\n *\n * See .argument() for creating an attached argument, which uses this routine to\n * create the argument. You can override createArgument to return a custom argument.\n *\n * @param {string} name\n * @param {string} [description]\n * @return {Argument} new argument\n */\n\n createArgument(name, description) {\n return new Argument(name, description);\n }\n\n /**\n * Define argument syntax for command.\n *\n * The default is that the argument is required, and you can explicitly\n * indicate this with <> around the name. Put [] around the name for an optional argument.\n *\n * @example\n * program.argument('');\n * program.argument('[output-file]');\n *\n * @param {string} name\n * @param {string} [description]\n * @param {(Function|*)} [parseArg] - custom argument processing function or default value\n * @param {*} [defaultValue]\n * @return {Command} `this` command for chaining\n */\n argument(name, description, parseArg, defaultValue) {\n const argument = this.createArgument(name, description);\n if (typeof parseArg === 'function') {\n argument.default(defaultValue).argParser(parseArg);\n } else {\n argument.default(parseArg);\n }\n this.addArgument(argument);\n return this;\n }\n\n /**\n * Define argument syntax for command, adding multiple at once (without descriptions).\n *\n * See also .argument().\n *\n * @example\n * program.arguments(' [env]');\n *\n * @param {string} names\n * @return {Command} `this` command for chaining\n */\n\n arguments(names) {\n names\n .trim()\n .split(/ +/)\n .forEach((detail) => {\n this.argument(detail);\n });\n return this;\n }\n\n /**\n * Define argument syntax for command, adding a prepared argument.\n *\n * @param {Argument} argument\n * @return {Command} `this` command for chaining\n */\n addArgument(argument) {\n const previousArgument = this.registeredArguments.slice(-1)[0];\n if (previousArgument?.variadic) {\n throw new Error(\n `only the last argument can be variadic '${previousArgument.name()}'`,\n );\n }\n if (\n argument.required &&\n argument.defaultValue !== undefined &&\n argument.parseArg === undefined\n ) {\n throw new Error(\n `a default value for a required argument is never used: '${argument.name()}'`,\n );\n }\n this.registeredArguments.push(argument);\n return this;\n }\n\n /**\n * Customise or override default help command. By default a help command is automatically added if your command has subcommands.\n *\n * @example\n * program.helpCommand('help [cmd]');\n * program.helpCommand('help [cmd]', 'show help');\n * program.helpCommand(false); // suppress default help command\n * program.helpCommand(true); // add help command even if no subcommands\n *\n * @param {string|boolean} enableOrNameAndArgs - enable with custom name and/or arguments, or boolean to override whether added\n * @param {string} [description] - custom description\n * @return {Command} `this` command for chaining\n */\n\n helpCommand(enableOrNameAndArgs, description) {\n if (typeof enableOrNameAndArgs === 'boolean') {\n this._addImplicitHelpCommand = enableOrNameAndArgs;\n if (enableOrNameAndArgs && this._defaultCommandGroup) {\n // make the command to store the group\n this._initCommandGroup(this._getHelpCommand());\n }\n return this;\n }\n\n const nameAndArgs = enableOrNameAndArgs ?? 'help [command]';\n const [, helpName, helpArgs] = nameAndArgs.match(/([^ ]+) *(.*)/);\n const helpDescription = description ?? 'display help for command';\n\n const helpCommand = this.createCommand(helpName);\n helpCommand.helpOption(false);\n if (helpArgs) helpCommand.arguments(helpArgs);\n if (helpDescription) helpCommand.description(helpDescription);\n\n this._addImplicitHelpCommand = true;\n this._helpCommand = helpCommand;\n // init group unless lazy create\n if (enableOrNameAndArgs || description) this._initCommandGroup(helpCommand);\n\n return this;\n }\n\n /**\n * Add prepared custom help command.\n *\n * @param {(Command|string|boolean)} helpCommand - custom help command, or deprecated enableOrNameAndArgs as for `.helpCommand()`\n * @param {string} [deprecatedDescription] - deprecated custom description used with custom name only\n * @return {Command} `this` command for chaining\n */\n addHelpCommand(helpCommand, deprecatedDescription) {\n // If not passed an object, call through to helpCommand for backwards compatibility,\n // as addHelpCommand was originally used like helpCommand is now.\n if (typeof helpCommand !== 'object') {\n this.helpCommand(helpCommand, deprecatedDescription);\n return this;\n }\n\n this._addImplicitHelpCommand = true;\n this._helpCommand = helpCommand;\n this._initCommandGroup(helpCommand);\n return this;\n }\n\n /**\n * Lazy create help command.\n *\n * @return {(Command|null)}\n * @package\n */\n _getHelpCommand() {\n const hasImplicitHelpCommand =\n this._addImplicitHelpCommand ??\n (this.commands.length &&\n !this._actionHandler &&\n !this._findCommand('help'));\n\n if (hasImplicitHelpCommand) {\n if (this._helpCommand === undefined) {\n this.helpCommand(undefined, undefined); // use default name and description\n }\n return this._helpCommand;\n }\n return null;\n }\n\n /**\n * Add hook for life cycle event.\n *\n * @param {string} event\n * @param {Function} listener\n * @return {Command} `this` command for chaining\n */\n\n hook(event, listener) {\n const allowedValues = ['preSubcommand', 'preAction', 'postAction'];\n if (!allowedValues.includes(event)) {\n throw new Error(`Unexpected value for event passed to hook : '${event}'.\nExpecting one of '${allowedValues.join(\"', '\")}'`);\n }\n if (this._lifeCycleHooks[event]) {\n this._lifeCycleHooks[event].push(listener);\n } else {\n this._lifeCycleHooks[event] = [listener];\n }\n return this;\n }\n\n /**\n * Register callback to use as replacement for calling process.exit.\n *\n * @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing\n * @return {Command} `this` command for chaining\n */\n\n exitOverride(fn) {\n if (fn) {\n this._exitCallback = fn;\n } else {\n this._exitCallback = (err) => {\n if (err.code !== 'commander.executeSubCommandAsync') {\n throw err;\n } else {\n // Async callback from spawn events, not useful to throw.\n }\n };\n }\n return this;\n }\n\n /**\n * Call process.exit, and _exitCallback if defined.\n *\n * @param {number} exitCode exit code for using with process.exit\n * @param {string} code an id string representing the error\n * @param {string} message human-readable description of the error\n * @return never\n * @private\n */\n\n _exit(exitCode, code, message) {\n if (this._exitCallback) {\n this._exitCallback(new CommanderError(exitCode, code, message));\n // Expecting this line is not reached.\n }\n process.exit(exitCode);\n }\n\n /**\n * Register callback `fn` for the command.\n *\n * @example\n * program\n * .command('serve')\n * .description('start service')\n * .action(function() {\n * // do work here\n * });\n *\n * @param {Function} fn\n * @return {Command} `this` command for chaining\n */\n\n action(fn) {\n const listener = (args) => {\n // The .action callback takes an extra parameter which is the command or options.\n const expectedArgsCount = this.registeredArguments.length;\n const actionArgs = args.slice(0, expectedArgsCount);\n if (this._storeOptionsAsProperties) {\n actionArgs[expectedArgsCount] = this; // backwards compatible \"options\"\n } else {\n actionArgs[expectedArgsCount] = this.opts();\n }\n actionArgs.push(this);\n\n return fn.apply(this, actionArgs);\n };\n this._actionHandler = listener;\n return this;\n }\n\n /**\n * Factory routine to create a new unattached option.\n *\n * See .option() for creating an attached option, which uses this routine to\n * create the option. You can override createOption to return a custom option.\n *\n * @param {string} flags\n * @param {string} [description]\n * @return {Option} new option\n */\n\n createOption(flags, description) {\n return new Option(flags, description);\n }\n\n /**\n * Wrap parseArgs to catch 'commander.invalidArgument'.\n *\n * @param {(Option | Argument)} target\n * @param {string} value\n * @param {*} previous\n * @param {string} invalidArgumentMessage\n * @private\n */\n\n _callParseArg(target, value, previous, invalidArgumentMessage) {\n try {\n return target.parseArg(value, previous);\n } catch (err) {\n if (err.code === 'commander.invalidArgument') {\n const message = `${invalidArgumentMessage} ${err.message}`;\n this.error(message, { exitCode: err.exitCode, code: err.code });\n }\n throw err;\n }\n }\n\n /**\n * Check for option flag conflicts.\n * Register option if no conflicts found, or throw on conflict.\n *\n * @param {Option} option\n * @private\n */\n\n _registerOption(option) {\n const matchingOption =\n (option.short && this._findOption(option.short)) ||\n (option.long && this._findOption(option.long));\n if (matchingOption) {\n const matchingFlag =\n option.long && this._findOption(option.long)\n ? option.long\n : option.short;\n throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'\n- already used by option '${matchingOption.flags}'`);\n }\n\n this._initOptionGroup(option);\n this.options.push(option);\n }\n\n /**\n * Check for command name and alias conflicts with existing commands.\n * Register command if no conflicts found, or throw on conflict.\n *\n * @param {Command} command\n * @private\n */\n\n _registerCommand(command) {\n const knownBy = (cmd) => {\n return [cmd.name()].concat(cmd.aliases());\n };\n\n const alreadyUsed = knownBy(command).find((name) =>\n this._findCommand(name),\n );\n if (alreadyUsed) {\n const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');\n const newCmd = knownBy(command).join('|');\n throw new Error(\n `cannot add command '${newCmd}' as already have command '${existingCmd}'`,\n );\n }\n\n this._initCommandGroup(command);\n this.commands.push(command);\n }\n\n /**\n * Add an option.\n *\n * @param {Option} option\n * @return {Command} `this` command for chaining\n */\n addOption(option) {\n this._registerOption(option);\n\n const oname = option.name();\n const name = option.attributeName();\n\n // store default value\n if (option.defaultValue !== undefined) {\n this.setOptionValueWithSource(name, option.defaultValue, 'default');\n }\n\n // handler for cli and env supplied values\n const handleOptionValue = (val, invalidValueMessage, valueSource) => {\n // val is null for optional option used without an optional-argument.\n // val is undefined for boolean and negated option.\n if (val == null && option.presetArg !== undefined) {\n val = option.presetArg;\n }\n\n // custom processing\n const oldValue = this.getOptionValue(name);\n if (val !== null && option.parseArg) {\n val = this._callParseArg(option, val, oldValue, invalidValueMessage);\n } else if (val !== null && option.variadic) {\n val = option._collectValue(val, oldValue);\n }\n\n // Fill-in appropriate missing values. Long winded but easy to follow.\n if (val == null) {\n if (option.negate) {\n val = false;\n } else if (option.isBoolean() || option.optional) {\n val = true;\n } else {\n val = ''; // not normal, parseArg might have failed or be a mock function for testing\n }\n }\n this.setOptionValueWithSource(name, val, valueSource);\n };\n\n this.on('option:' + oname, (val) => {\n const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;\n handleOptionValue(val, invalidValueMessage, 'cli');\n });\n\n if (option.envVar) {\n this.on('optionEnv:' + oname, (val) => {\n const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;\n handleOptionValue(val, invalidValueMessage, 'env');\n });\n }\n\n return this;\n }\n\n /**\n * Internal implementation shared by .option() and .requiredOption()\n *\n * @return {Command} `this` command for chaining\n * @private\n */\n _optionEx(config, flags, description, fn, defaultValue) {\n if (typeof flags === 'object' && flags instanceof Option) {\n throw new Error(\n 'To add an Option object use addOption() instead of option() or requiredOption()',\n );\n }\n const option = this.createOption(flags, description);\n option.makeOptionMandatory(!!config.mandatory);\n if (typeof fn === 'function') {\n option.default(defaultValue).argParser(fn);\n } else if (fn instanceof RegExp) {\n // deprecated\n const regex = fn;\n fn = (val, def) => {\n const m = regex.exec(val);\n return m ? m[0] : def;\n };\n option.default(defaultValue).argParser(fn);\n } else {\n option.default(fn);\n }\n\n return this.addOption(option);\n }\n\n /**\n * Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.\n *\n * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required\n * option-argument is indicated by `<>` and an optional option-argument by `[]`.\n *\n * See the README for more details, and see also addOption() and requiredOption().\n *\n * @example\n * program\n * .option('-p, --pepper', 'add pepper')\n * .option('--pt, --pizza-type ', 'type of pizza') // required option-argument\n * .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default\n * .option('-t, --tip ', 'add tip to purchase cost', parseFloat) // custom parse function\n *\n * @param {string} flags\n * @param {string} [description]\n * @param {(Function|*)} [parseArg] - custom option processing function or default value\n * @param {*} [defaultValue]\n * @return {Command} `this` command for chaining\n */\n\n option(flags, description, parseArg, defaultValue) {\n return this._optionEx({}, flags, description, parseArg, defaultValue);\n }\n\n /**\n * Add a required option which must have a value after parsing. This usually means\n * the option must be specified on the command line. (Otherwise the same as .option().)\n *\n * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.\n *\n * @param {string} flags\n * @param {string} [description]\n * @param {(Function|*)} [parseArg] - custom option processing function or default value\n * @param {*} [defaultValue]\n * @return {Command} `this` command for chaining\n */\n\n requiredOption(flags, description, parseArg, defaultValue) {\n return this._optionEx(\n { mandatory: true },\n flags,\n description,\n parseArg,\n defaultValue,\n );\n }\n\n /**\n * Alter parsing of short flags with optional values.\n *\n * @example\n * // for `.option('-f,--flag [value]'):\n * program.combineFlagAndOptionalValue(true); // `-f80` is treated like `--flag=80`, this is the default behaviour\n * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`\n *\n * @param {boolean} [combine] - if `true` or omitted, an optional value can be specified directly after the flag.\n * @return {Command} `this` command for chaining\n */\n combineFlagAndOptionalValue(combine = true) {\n this._combineFlagAndOptionalValue = !!combine;\n return this;\n }\n\n /**\n * Allow unknown options on the command line.\n *\n * @param {boolean} [allowUnknown] - if `true` or omitted, no error will be thrown for unknown options.\n * @return {Command} `this` command for chaining\n */\n allowUnknownOption(allowUnknown = true) {\n this._allowUnknownOption = !!allowUnknown;\n return this;\n }\n\n /**\n * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.\n *\n * @param {boolean} [allowExcess] - if `true` or omitted, no error will be thrown for excess arguments.\n * @return {Command} `this` command for chaining\n */\n allowExcessArguments(allowExcess = true) {\n this._allowExcessArguments = !!allowExcess;\n return this;\n }\n\n /**\n * Enable positional options. Positional means global options are specified before subcommands which lets\n * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.\n * The default behaviour is non-positional and global options may appear anywhere on the command line.\n *\n * @param {boolean} [positional]\n * @return {Command} `this` command for chaining\n */\n enablePositionalOptions(positional = true) {\n this._enablePositionalOptions = !!positional;\n return this;\n }\n\n /**\n * Pass through options that come after command-arguments rather than treat them as command-options,\n * so actual command-options come before command-arguments. Turning this on for a subcommand requires\n * positional options to have been enabled on the program (parent commands).\n * The default behaviour is non-positional and options may appear before or after command-arguments.\n *\n * @param {boolean} [passThrough] for unknown options.\n * @return {Command} `this` command for chaining\n */\n passThroughOptions(passThrough = true) {\n this._passThroughOptions = !!passThrough;\n this._checkForBrokenPassThrough();\n return this;\n }\n\n /**\n * @private\n */\n\n _checkForBrokenPassThrough() {\n if (\n this.parent &&\n this._passThroughOptions &&\n !this.parent._enablePositionalOptions\n ) {\n throw new Error(\n `passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`,\n );\n }\n }\n\n /**\n * Whether to store option values as properties on command object,\n * or store separately (specify false). In both cases the option values can be accessed using .opts().\n *\n * @param {boolean} [storeAsProperties=true]\n * @return {Command} `this` command for chaining\n */\n\n storeOptionsAsProperties(storeAsProperties = true) {\n if (this.options.length) {\n throw new Error('call .storeOptionsAsProperties() before adding options');\n }\n if (Object.keys(this._optionValues).length) {\n throw new Error(\n 'call .storeOptionsAsProperties() before setting option values',\n );\n }\n this._storeOptionsAsProperties = !!storeAsProperties;\n return this;\n }\n\n /**\n * Retrieve option value.\n *\n * @param {string} key\n * @return {object} value\n */\n\n getOptionValue(key) {\n if (this._storeOptionsAsProperties) {\n return this[key];\n }\n return this._optionValues[key];\n }\n\n /**\n * Store option value.\n *\n * @param {string} key\n * @param {object} value\n * @return {Command} `this` command for chaining\n */\n\n setOptionValue(key, value) {\n return this.setOptionValueWithSource(key, value, undefined);\n }\n\n /**\n * Store option value and where the value came from.\n *\n * @param {string} key\n * @param {object} value\n * @param {string} source - expected values are default/config/env/cli/implied\n * @return {Command} `this` command for chaining\n */\n\n setOptionValueWithSource(key, value, source) {\n if (this._storeOptionsAsProperties) {\n this[key] = value;\n } else {\n this._optionValues[key] = value;\n }\n this._optionValueSources[key] = source;\n return this;\n }\n\n /**\n * Get source of option value.\n * Expected values are default | config | env | cli | implied\n *\n * @param {string} key\n * @return {string}\n */\n\n getOptionValueSource(key) {\n return this._optionValueSources[key];\n }\n\n /**\n * Get source of option value. See also .optsWithGlobals().\n * Expected values are default | config | env | cli | implied\n *\n * @param {string} key\n * @return {string}\n */\n\n getOptionValueSourceWithGlobals(key) {\n // global overwrites local, like optsWithGlobals\n let source;\n this._getCommandAndAncestors().forEach((cmd) => {\n if (cmd.getOptionValueSource(key) !== undefined) {\n source = cmd.getOptionValueSource(key);\n }\n });\n return source;\n }\n\n /**\n * Get user arguments from implied or explicit arguments.\n * Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.\n *\n * @private\n */\n\n _prepareUserArgs(argv, parseOptions) {\n if (argv !== undefined && !Array.isArray(argv)) {\n throw new Error('first parameter to parse must be array or undefined');\n }\n parseOptions = parseOptions || {};\n\n // auto-detect argument conventions if nothing supplied\n if (argv === undefined && parseOptions.from === undefined) {\n if (process.versions?.electron) {\n parseOptions.from = 'electron';\n }\n // check node specific options for scenarios where user CLI args follow executable without scriptname\n const execArgv = process.execArgv ?? [];\n if (\n execArgv.includes('-e') ||\n execArgv.includes('--eval') ||\n execArgv.includes('-p') ||\n execArgv.includes('--print')\n ) {\n parseOptions.from = 'eval'; // internal usage, not documented\n }\n }\n\n // default to using process.argv\n if (argv === undefined) {\n argv = process.argv;\n }\n this.rawArgs = argv.slice();\n\n // extract the user args and scriptPath\n let userArgs;\n switch (parseOptions.from) {\n case undefined:\n case 'node':\n this._scriptPath = argv[1];\n userArgs = argv.slice(2);\n break;\n case 'electron':\n // @ts-ignore: because defaultApp is an unknown property\n if (process.defaultApp) {\n this._scriptPath = argv[1];\n userArgs = argv.slice(2);\n } else {\n userArgs = argv.slice(1);\n }\n break;\n case 'user':\n userArgs = argv.slice(0);\n break;\n case 'eval':\n userArgs = argv.slice(1);\n break;\n default:\n throw new Error(\n `unexpected parse option { from: '${parseOptions.from}' }`,\n );\n }\n\n // Find default name for program from arguments.\n if (!this._name && this._scriptPath)\n this.nameFromFilename(this._scriptPath);\n this._name = this._name || 'program';\n\n return userArgs;\n }\n\n /**\n * Parse `argv`, setting options and invoking commands when defined.\n *\n * Use parseAsync instead of parse if any of your action handlers are async.\n *\n * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n *\n * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n * - `'user'`: just user arguments\n *\n * @example\n * program.parse(); // parse process.argv and auto-detect electron and special node flags\n * program.parse(process.argv); // assume argv[0] is app and argv[1] is script\n * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n *\n * @param {string[]} [argv] - optional, defaults to process.argv\n * @param {object} [parseOptions] - optionally specify style of options with from: node/user/electron\n * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron'\n * @return {Command} `this` command for chaining\n */\n\n parse(argv, parseOptions) {\n this._prepareForParse();\n const userArgs = this._prepareUserArgs(argv, parseOptions);\n this._parseCommand([], userArgs);\n\n return this;\n }\n\n /**\n * Parse `argv`, setting options and invoking commands when defined.\n *\n * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n *\n * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n * - `'user'`: just user arguments\n *\n * @example\n * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags\n * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script\n * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n *\n * @param {string[]} [argv]\n * @param {object} [parseOptions]\n * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron'\n * @return {Promise}\n */\n\n async parseAsync(argv, parseOptions) {\n this._prepareForParse();\n const userArgs = this._prepareUserArgs(argv, parseOptions);\n await this._parseCommand([], userArgs);\n\n return this;\n }\n\n _prepareForParse() {\n // Save the state the first time, then restore the state before each subsequent parse.\n if (this._savedState === null) {\n // Do the special default of lone negated option to true, now that we have all the options.\n // Filter for negated options that have not been processed already.\n this.options\n .filter(\n (option) =>\n option.negate &&\n option.defaultValue === undefined &&\n this.getOptionValue(option.attributeName()) === undefined,\n )\n .forEach((option) => {\n // check for lone negated option: --no-foo without a --foo option\n const positiveLongFlag = option.long.replace(/^--no-/, '--');\n if (!this._findOption(positiveLongFlag)) {\n this.setOptionValueWithSource(\n option.attributeName(),\n true,\n 'default',\n );\n }\n });\n\n this.saveStateBeforeParse();\n } else {\n this.restoreStateBeforeParse();\n }\n }\n\n /**\n * Called the first time parse is called to save state and allow a restore before subsequent calls to parse.\n * Not usually called directly, but available for subclasses to save their custom state.\n *\n * This is called in a lazy way. Only commands used in parsing chain will have state saved.\n */\n saveStateBeforeParse() {\n this._savedState = {\n // name is stable if supplied by author, but may be unspecified for root command and deduced during parsing\n _name: this._name,\n // option values before parse have default values (including false for negated options)\n // shallow clones\n _optionValues: { ...this._optionValues },\n _optionValueSources: { ...this._optionValueSources },\n };\n }\n\n /**\n * Restore state before parse for calls after the first.\n * Not usually called directly, but available for subclasses to save their custom state.\n *\n * This is called in a lazy way. Only commands used in parsing chain will have state restored.\n */\n restoreStateBeforeParse() {\n if (this._storeOptionsAsProperties)\n throw new Error(`Can not call parse again when storeOptionsAsProperties is true.\n- either make a new Command for each call to parse, or stop storing options as properties`);\n\n // clear state from _prepareUserArgs\n this._name = this._savedState._name;\n this._scriptPath = null;\n this.rawArgs = [];\n // clear state from setOptionValueWithSource\n this._optionValues = { ...this._savedState._optionValues };\n this._optionValueSources = { ...this._savedState._optionValueSources };\n // clear state from _parseCommand\n this.args = [];\n // clear state from _processArguments\n this.processedArgs = [];\n }\n\n /**\n * Throw if expected executable is missing. Add lots of help for author.\n *\n * @param {string} executableFile\n * @param {string} executableDir\n * @param {string} subcommandName\n */\n _checkForMissingExecutable(executableFile, executableDir, subcommandName) {\n if (fs.existsSync(executableFile)) return;\n\n const executableDirMessage = executableDir\n ? `searched for local subcommand relative to directory '${executableDir}'`\n : 'no directory for search for local subcommand, use .executableDir() to supply a custom directory';\n const executableMissing = `'${executableFile}' does not exist\n - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead\n - if the default executable name is not suitable, use the executableFile option to supply a custom name or path\n - ${executableDirMessage}`;\n throw new Error(executableMissing);\n }\n\n /**\n * Execute a sub-command executable.\n *\n * @private\n */\n\n _executeSubCommand(subcommand, args) {\n args = args.slice();\n const sourceExt = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];\n\n function findFile(baseDir, baseName) {\n // Look for specified file\n const localBin = path.resolve(baseDir, baseName);\n if (fs.existsSync(localBin)) return localBin;\n\n // Stop looking if candidate already has an expected extension.\n if (sourceExt.includes(path.extname(baseName))) return undefined;\n\n // Try all the extensions.\n const foundExt = sourceExt.find((ext) =>\n fs.existsSync(`${localBin}${ext}`),\n );\n if (foundExt) return `${localBin}${foundExt}`;\n\n return undefined;\n }\n\n // Not checking for help first. Unlikely to have mandatory and executable, and can't robustly test for help flags in external command.\n this._checkForMissingMandatoryOptions();\n this._checkForConflictingOptions();\n\n // executableFile and executableDir might be full path, or just a name\n let executableFile =\n subcommand._executableFile || `${this._name}-${subcommand._name}`;\n let executableDir = this._executableDir || '';\n if (this._scriptPath) {\n let resolvedScriptPath; // resolve possible symlink for installed npm binary\n try {\n resolvedScriptPath = fs.realpathSync(this._scriptPath);\n } catch {\n resolvedScriptPath = this._scriptPath;\n }\n executableDir = path.resolve(\n path.dirname(resolvedScriptPath),\n executableDir,\n );\n }\n\n // Look for a local file in preference to a command in PATH.\n if (executableDir) {\n let localFile = findFile(executableDir, executableFile);\n\n // Legacy search using prefix of script name instead of command name\n if (!localFile && !subcommand._executableFile && this._scriptPath) {\n const legacyName = path.basename(\n this._scriptPath,\n path.extname(this._scriptPath),\n );\n if (legacyName !== this._name) {\n localFile = findFile(\n executableDir,\n `${legacyName}-${subcommand._name}`,\n );\n }\n }\n executableFile = localFile || executableFile;\n }\n\n const launchWithNode = sourceExt.includes(path.extname(executableFile));\n\n let proc;\n if (process.platform !== 'win32') {\n if (launchWithNode) {\n args.unshift(executableFile);\n // add executable arguments to spawn\n args = incrementNodeInspectorPort(process.execArgv).concat(args);\n\n proc = childProcess.spawn(process.argv[0], args, { stdio: 'inherit' });\n } else {\n proc = childProcess.spawn(executableFile, args, { stdio: 'inherit' });\n }\n } else {\n this._checkForMissingExecutable(\n executableFile,\n executableDir,\n subcommand._name,\n );\n args.unshift(executableFile);\n // add executable arguments to spawn\n args = incrementNodeInspectorPort(process.execArgv).concat(args);\n proc = childProcess.spawn(process.execPath, args, { stdio: 'inherit' });\n }\n\n if (!proc.killed) {\n // testing mainly to avoid leak warnings during unit tests with mocked spawn\n const signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];\n signals.forEach((signal) => {\n process.on(signal, () => {\n if (proc.killed === false && proc.exitCode === null) {\n // @ts-ignore because signals not typed to known strings\n proc.kill(signal);\n }\n });\n });\n }\n\n // By default terminate process when spawned process terminates.\n const exitCallback = this._exitCallback;\n proc.on('close', (code) => {\n code = code ?? 1; // code is null if spawned process terminated due to a signal\n if (!exitCallback) {\n process.exit(code);\n } else {\n exitCallback(\n new CommanderError(\n code,\n 'commander.executeSubCommandAsync',\n '(close)',\n ),\n );\n }\n });\n proc.on('error', (err) => {\n // @ts-ignore: because err.code is an unknown property\n if (err.code === 'ENOENT') {\n this._checkForMissingExecutable(\n executableFile,\n executableDir,\n subcommand._name,\n );\n // @ts-ignore: because err.code is an unknown property\n } else if (err.code === 'EACCES') {\n throw new Error(`'${executableFile}' not executable`);\n }\n if (!exitCallback) {\n process.exit(1);\n } else {\n const wrappedError = new CommanderError(\n 1,\n 'commander.executeSubCommandAsync',\n '(error)',\n );\n wrappedError.nestedError = err;\n exitCallback(wrappedError);\n }\n });\n\n // Store the reference to the child process\n this.runningCommand = proc;\n }\n\n /**\n * @private\n */\n\n _dispatchSubcommand(commandName, operands, unknown) {\n const subCommand = this._findCommand(commandName);\n if (!subCommand) this.help({ error: true });\n\n subCommand._prepareForParse();\n let promiseChain;\n promiseChain = this._chainOrCallSubCommandHook(\n promiseChain,\n subCommand,\n 'preSubcommand',\n );\n promiseChain = this._chainOrCall(promiseChain, () => {\n if (subCommand._executableHandler) {\n this._executeSubCommand(subCommand, operands.concat(unknown));\n } else {\n return subCommand._parseCommand(operands, unknown);\n }\n });\n return promiseChain;\n }\n\n /**\n * Invoke help directly if possible, or dispatch if necessary.\n * e.g. help foo\n *\n * @private\n */\n\n _dispatchHelpCommand(subcommandName) {\n if (!subcommandName) {\n this.help();\n }\n const subCommand = this._findCommand(subcommandName);\n if (subCommand && !subCommand._executableHandler) {\n subCommand.help();\n }\n\n // Fallback to parsing the help flag to invoke the help.\n return this._dispatchSubcommand(\n subcommandName,\n [],\n [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? '--help'],\n );\n }\n\n /**\n * Check this.args against expected this.registeredArguments.\n *\n * @private\n */\n\n _checkNumberOfArguments() {\n // too few\n this.registeredArguments.forEach((arg, i) => {\n if (arg.required && this.args[i] == null) {\n this.missingArgument(arg.name());\n }\n });\n // too many\n if (\n this.registeredArguments.length > 0 &&\n this.registeredArguments[this.registeredArguments.length - 1].variadic\n ) {\n return;\n }\n if (this.args.length > this.registeredArguments.length) {\n this._excessArguments(this.args);\n }\n }\n\n /**\n * Process this.args using this.registeredArguments and save as this.processedArgs!\n *\n * @private\n */\n\n _processArguments() {\n const myParseArg = (argument, value, previous) => {\n // Extra processing for nice error message on parsing failure.\n let parsedValue = value;\n if (value !== null && argument.parseArg) {\n const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;\n parsedValue = this._callParseArg(\n argument,\n value,\n previous,\n invalidValueMessage,\n );\n }\n return parsedValue;\n };\n\n this._checkNumberOfArguments();\n\n const processedArgs = [];\n this.registeredArguments.forEach((declaredArg, index) => {\n let value = declaredArg.defaultValue;\n if (declaredArg.variadic) {\n // Collect together remaining arguments for passing together as an array.\n if (index < this.args.length) {\n value = this.args.slice(index);\n if (declaredArg.parseArg) {\n value = value.reduce((processed, v) => {\n return myParseArg(declaredArg, v, processed);\n }, declaredArg.defaultValue);\n }\n } else if (value === undefined) {\n value = [];\n }\n } else if (index < this.args.length) {\n value = this.args[index];\n if (declaredArg.parseArg) {\n value = myParseArg(declaredArg, value, declaredArg.defaultValue);\n }\n }\n processedArgs[index] = value;\n });\n this.processedArgs = processedArgs;\n }\n\n /**\n * Once we have a promise we chain, but call synchronously until then.\n *\n * @param {(Promise|undefined)} promise\n * @param {Function} fn\n * @return {(Promise|undefined)}\n * @private\n */\n\n _chainOrCall(promise, fn) {\n // thenable\n if (promise?.then && typeof promise.then === 'function') {\n // already have a promise, chain callback\n return promise.then(() => fn());\n }\n // callback might return a promise\n return fn();\n }\n\n /**\n *\n * @param {(Promise|undefined)} promise\n * @param {string} event\n * @return {(Promise|undefined)}\n * @private\n */\n\n _chainOrCallHooks(promise, event) {\n let result = promise;\n const hooks = [];\n this._getCommandAndAncestors()\n .reverse()\n .filter((cmd) => cmd._lifeCycleHooks[event] !== undefined)\n .forEach((hookedCommand) => {\n hookedCommand._lifeCycleHooks[event].forEach((callback) => {\n hooks.push({ hookedCommand, callback });\n });\n });\n if (event === 'postAction') {\n hooks.reverse();\n }\n\n hooks.forEach((hookDetail) => {\n result = this._chainOrCall(result, () => {\n return hookDetail.callback(hookDetail.hookedCommand, this);\n });\n });\n return result;\n }\n\n /**\n *\n * @param {(Promise|undefined)} promise\n * @param {Command} subCommand\n * @param {string} event\n * @return {(Promise|undefined)}\n * @private\n */\n\n _chainOrCallSubCommandHook(promise, subCommand, event) {\n let result = promise;\n if (this._lifeCycleHooks[event] !== undefined) {\n this._lifeCycleHooks[event].forEach((hook) => {\n result = this._chainOrCall(result, () => {\n return hook(this, subCommand);\n });\n });\n }\n return result;\n }\n\n /**\n * Process arguments in context of this command.\n * Returns action result, in case it is a promise.\n *\n * @private\n */\n\n _parseCommand(operands, unknown) {\n const parsed = this.parseOptions(unknown);\n this._parseOptionsEnv(); // after cli, so parseArg not called on both cli and env\n this._parseOptionsImplied();\n operands = operands.concat(parsed.operands);\n unknown = parsed.unknown;\n this.args = operands.concat(unknown);\n\n if (operands && this._findCommand(operands[0])) {\n return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);\n }\n if (\n this._getHelpCommand() &&\n operands[0] === this._getHelpCommand().name()\n ) {\n return this._dispatchHelpCommand(operands[1]);\n }\n if (this._defaultCommandName) {\n this._outputHelpIfRequested(unknown); // Run the help for default command from parent rather than passing to default command\n return this._dispatchSubcommand(\n this._defaultCommandName,\n operands,\n unknown,\n );\n }\n if (\n this.commands.length &&\n this.args.length === 0 &&\n !this._actionHandler &&\n !this._defaultCommandName\n ) {\n // probably missing subcommand and no handler, user needs help (and exit)\n this.help({ error: true });\n }\n\n this._outputHelpIfRequested(parsed.unknown);\n this._checkForMissingMandatoryOptions();\n this._checkForConflictingOptions();\n\n // We do not always call this check to avoid masking a \"better\" error, like unknown command.\n const checkForUnknownOptions = () => {\n if (parsed.unknown.length > 0) {\n this.unknownOption(parsed.unknown[0]);\n }\n };\n\n const commandEvent = `command:${this.name()}`;\n if (this._actionHandler) {\n checkForUnknownOptions();\n this._processArguments();\n\n let promiseChain;\n promiseChain = this._chainOrCallHooks(promiseChain, 'preAction');\n promiseChain = this._chainOrCall(promiseChain, () =>\n this._actionHandler(this.processedArgs),\n );\n if (this.parent) {\n promiseChain = this._chainOrCall(promiseChain, () => {\n this.parent.emit(commandEvent, operands, unknown); // legacy\n });\n }\n promiseChain = this._chainOrCallHooks(promiseChain, 'postAction');\n return promiseChain;\n }\n if (this.parent?.listenerCount(commandEvent)) {\n checkForUnknownOptions();\n this._processArguments();\n this.parent.emit(commandEvent, operands, unknown); // legacy\n } else if (operands.length) {\n if (this._findCommand('*')) {\n // legacy default command\n return this._dispatchSubcommand('*', operands, unknown);\n }\n if (this.listenerCount('command:*')) {\n // skip option check, emit event for possible misspelling suggestion\n this.emit('command:*', operands, unknown);\n } else if (this.commands.length) {\n this.unknownCommand();\n } else {\n checkForUnknownOptions();\n this._processArguments();\n }\n } else if (this.commands.length) {\n checkForUnknownOptions();\n // This command has subcommands and nothing hooked up at this level, so display help (and exit).\n this.help({ error: true });\n } else {\n checkForUnknownOptions();\n this._processArguments();\n // fall through for caller to handle after calling .parse()\n }\n }\n\n /**\n * Find matching command.\n *\n * @private\n * @return {Command | undefined}\n */\n _findCommand(name) {\n if (!name) return undefined;\n return this.commands.find(\n (cmd) => cmd._name === name || cmd._aliases.includes(name),\n );\n }\n\n /**\n * Return an option matching `arg` if any.\n *\n * @param {string} arg\n * @return {Option}\n * @package\n */\n\n _findOption(arg) {\n return this.options.find((option) => option.is(arg));\n }\n\n /**\n * Display an error message if a mandatory option does not have a value.\n * Called after checking for help flags in leaf subcommand.\n *\n * @private\n */\n\n _checkForMissingMandatoryOptions() {\n // Walk up hierarchy so can call in subcommand after checking for displaying help.\n this._getCommandAndAncestors().forEach((cmd) => {\n cmd.options.forEach((anOption) => {\n if (\n anOption.mandatory &&\n cmd.getOptionValue(anOption.attributeName()) === undefined\n ) {\n cmd.missingMandatoryOptionValue(anOption);\n }\n });\n });\n }\n\n /**\n * Display an error message if conflicting options are used together in this.\n *\n * @private\n */\n _checkForConflictingLocalOptions() {\n const definedNonDefaultOptions = this.options.filter((option) => {\n const optionKey = option.attributeName();\n if (this.getOptionValue(optionKey) === undefined) {\n return false;\n }\n return this.getOptionValueSource(optionKey) !== 'default';\n });\n\n const optionsWithConflicting = definedNonDefaultOptions.filter(\n (option) => option.conflictsWith.length > 0,\n );\n\n optionsWithConflicting.forEach((option) => {\n const conflictingAndDefined = definedNonDefaultOptions.find((defined) =>\n option.conflictsWith.includes(defined.attributeName()),\n );\n if (conflictingAndDefined) {\n this._conflictingOption(option, conflictingAndDefined);\n }\n });\n }\n\n /**\n * Display an error message if conflicting options are used together.\n * Called after checking for help flags in leaf subcommand.\n *\n * @private\n */\n _checkForConflictingOptions() {\n // Walk up hierarchy so can call in subcommand after checking for displaying help.\n this._getCommandAndAncestors().forEach((cmd) => {\n cmd._checkForConflictingLocalOptions();\n });\n }\n\n /**\n * Parse options from `argv` removing known options,\n * and return argv split into operands and unknown arguments.\n *\n * Side effects: modifies command by storing options. Does not reset state if called again.\n *\n * Examples:\n *\n * argv => operands, unknown\n * --known kkk op => [op], []\n * op --known kkk => [op], []\n * sub --unknown uuu op => [sub], [--unknown uuu op]\n * sub -- --unknown uuu op => [sub --unknown uuu op], []\n *\n * @param {string[]} args\n * @return {{operands: string[], unknown: string[]}}\n */\n\n parseOptions(args) {\n const operands = []; // operands, not options or values\n const unknown = []; // first unknown option and remaining unknown args\n let dest = operands;\n\n function maybeOption(arg) {\n return arg.length > 1 && arg[0] === '-';\n }\n\n const negativeNumberArg = (arg) => {\n // return false if not a negative number\n if (!/^-(\\d+|\\d*\\.\\d+)(e[+-]?\\d+)?$/.test(arg)) return false;\n // negative number is ok unless digit used as an option in command hierarchy\n return !this._getCommandAndAncestors().some((cmd) =>\n cmd.options\n .map((opt) => opt.short)\n .some((short) => /^-\\d$/.test(short)),\n );\n };\n\n // parse options\n let activeVariadicOption = null;\n let activeGroup = null; // working through group of short options, like -abc\n let i = 0;\n while (i < args.length || activeGroup) {\n const arg = activeGroup ?? args[i++];\n activeGroup = null;\n\n // literal\n if (arg === '--') {\n if (dest === unknown) dest.push(arg);\n dest.push(...args.slice(i));\n break;\n }\n\n if (\n activeVariadicOption &&\n (!maybeOption(arg) || negativeNumberArg(arg))\n ) {\n this.emit(`option:${activeVariadicOption.name()}`, arg);\n continue;\n }\n activeVariadicOption = null;\n\n if (maybeOption(arg)) {\n const option = this._findOption(arg);\n // recognised option, call listener to assign value with possible custom processing\n if (option) {\n if (option.required) {\n const value = args[i++];\n if (value === undefined) this.optionMissingArgument(option);\n this.emit(`option:${option.name()}`, value);\n } else if (option.optional) {\n let value = null;\n // historical behaviour is optional value is following arg unless an option\n if (\n i < args.length &&\n (!maybeOption(args[i]) || negativeNumberArg(args[i]))\n ) {\n value = args[i++];\n }\n this.emit(`option:${option.name()}`, value);\n } else {\n // boolean flag\n this.emit(`option:${option.name()}`);\n }\n activeVariadicOption = option.variadic ? option : null;\n continue;\n }\n }\n\n // Look for combo options following single dash, eat first one if known.\n if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {\n const option = this._findOption(`-${arg[1]}`);\n if (option) {\n if (\n option.required ||\n (option.optional && this._combineFlagAndOptionalValue)\n ) {\n // option with value following in same argument\n this.emit(`option:${option.name()}`, arg.slice(2));\n } else {\n // boolean option\n this.emit(`option:${option.name()}`);\n // remove the processed option and keep processing group\n activeGroup = `-${arg.slice(2)}`;\n }\n continue;\n }\n }\n\n // Look for known long flag with value, like --foo=bar\n if (/^--[^=]+=/.test(arg)) {\n const index = arg.indexOf('=');\n const option = this._findOption(arg.slice(0, index));\n if (option && (option.required || option.optional)) {\n this.emit(`option:${option.name()}`, arg.slice(index + 1));\n continue;\n }\n }\n\n // Not a recognised option by this command.\n // Might be a command-argument, or subcommand option, or unknown option, or help command or option.\n\n // An unknown option means further arguments also classified as unknown so can be reprocessed by subcommands.\n // A negative number in a leaf command is not an unknown option.\n if (\n dest === operands &&\n maybeOption(arg) &&\n !(this.commands.length === 0 && negativeNumberArg(arg))\n ) {\n dest = unknown;\n }\n\n // If using positionalOptions, stop processing our options at subcommand.\n if (\n (this._enablePositionalOptions || this._passThroughOptions) &&\n operands.length === 0 &&\n unknown.length === 0\n ) {\n if (this._findCommand(arg)) {\n operands.push(arg);\n unknown.push(...args.slice(i));\n break;\n } else if (\n this._getHelpCommand() &&\n arg === this._getHelpCommand().name()\n ) {\n operands.push(arg, ...args.slice(i));\n break;\n } else if (this._defaultCommandName) {\n unknown.push(arg, ...args.slice(i));\n break;\n }\n }\n\n // If using passThroughOptions, stop processing options at first command-argument.\n if (this._passThroughOptions) {\n dest.push(arg, ...args.slice(i));\n break;\n }\n\n // add arg\n dest.push(arg);\n }\n\n return { operands, unknown };\n }\n\n /**\n * Return an object containing local option values as key-value pairs.\n *\n * @return {object}\n */\n opts() {\n if (this._storeOptionsAsProperties) {\n // Preserve original behaviour so backwards compatible when still using properties\n const result = {};\n const len = this.options.length;\n\n for (let i = 0; i < len; i++) {\n const key = this.options[i].attributeName();\n result[key] =\n key === this._versionOptionName ? this._version : this[key];\n }\n return result;\n }\n\n return this._optionValues;\n }\n\n /**\n * Return an object containing merged local and global option values as key-value pairs.\n *\n * @return {object}\n */\n optsWithGlobals() {\n // globals overwrite locals\n return this._getCommandAndAncestors().reduce(\n (combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()),\n {},\n );\n }\n\n /**\n * Display error message and exit (or call exitOverride).\n *\n * @param {string} message\n * @param {object} [errorOptions]\n * @param {string} [errorOptions.code] - an id string representing the error\n * @param {number} [errorOptions.exitCode] - used with process.exit\n */\n error(message, errorOptions) {\n // output handling\n this._outputConfiguration.outputError(\n `${message}\\n`,\n this._outputConfiguration.writeErr,\n );\n if (typeof this._showHelpAfterError === 'string') {\n this._outputConfiguration.writeErr(`${this._showHelpAfterError}\\n`);\n } else if (this._showHelpAfterError) {\n this._outputConfiguration.writeErr('\\n');\n this.outputHelp({ error: true });\n }\n\n // exit handling\n const config = errorOptions || {};\n const exitCode = config.exitCode || 1;\n const code = config.code || 'commander.error';\n this._exit(exitCode, code, message);\n }\n\n /**\n * Apply any option related environment variables, if option does\n * not have a value from cli or client code.\n *\n * @private\n */\n _parseOptionsEnv() {\n this.options.forEach((option) => {\n if (option.envVar && option.envVar in process.env) {\n const optionKey = option.attributeName();\n // Priority check. Do not overwrite cli or options from unknown source (client-code).\n if (\n this.getOptionValue(optionKey) === undefined ||\n ['default', 'config', 'env'].includes(\n this.getOptionValueSource(optionKey),\n )\n ) {\n if (option.required || option.optional) {\n // option can take a value\n // keep very simple, optional always takes value\n this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);\n } else {\n // boolean\n // keep very simple, only care that envVar defined and not the value\n this.emit(`optionEnv:${option.name()}`);\n }\n }\n }\n });\n }\n\n /**\n * Apply any implied option values, if option is undefined or default value.\n *\n * @private\n */\n _parseOptionsImplied() {\n const dualHelper = new DualOptions(this.options);\n const hasCustomOptionValue = (optionKey) => {\n return (\n this.getOptionValue(optionKey) !== undefined &&\n !['default', 'implied'].includes(this.getOptionValueSource(optionKey))\n );\n };\n this.options\n .filter(\n (option) =>\n option.implied !== undefined &&\n hasCustomOptionValue(option.attributeName()) &&\n dualHelper.valueFromOption(\n this.getOptionValue(option.attributeName()),\n option,\n ),\n )\n .forEach((option) => {\n Object.keys(option.implied)\n .filter((impliedKey) => !hasCustomOptionValue(impliedKey))\n .forEach((impliedKey) => {\n this.setOptionValueWithSource(\n impliedKey,\n option.implied[impliedKey],\n 'implied',\n );\n });\n });\n }\n\n /**\n * Argument `name` is missing.\n *\n * @param {string} name\n * @private\n */\n\n missingArgument(name) {\n const message = `error: missing required argument '${name}'`;\n this.error(message, { code: 'commander.missingArgument' });\n }\n\n /**\n * `Option` is missing an argument.\n *\n * @param {Option} option\n * @private\n */\n\n optionMissingArgument(option) {\n const message = `error: option '${option.flags}' argument missing`;\n this.error(message, { code: 'commander.optionMissingArgument' });\n }\n\n /**\n * `Option` does not have a value, and is a mandatory option.\n *\n * @param {Option} option\n * @private\n */\n\n missingMandatoryOptionValue(option) {\n const message = `error: required option '${option.flags}' not specified`;\n this.error(message, { code: 'commander.missingMandatoryOptionValue' });\n }\n\n /**\n * `Option` conflicts with another option.\n *\n * @param {Option} option\n * @param {Option} conflictingOption\n * @private\n */\n _conflictingOption(option, conflictingOption) {\n // The calling code does not know whether a negated option is the source of the\n // value, so do some work to take an educated guess.\n const findBestOptionFromValue = (option) => {\n const optionKey = option.attributeName();\n const optionValue = this.getOptionValue(optionKey);\n const negativeOption = this.options.find(\n (target) => target.negate && optionKey === target.attributeName(),\n );\n const positiveOption = this.options.find(\n (target) => !target.negate && optionKey === target.attributeName(),\n );\n if (\n negativeOption &&\n ((negativeOption.presetArg === undefined && optionValue === false) ||\n (negativeOption.presetArg !== undefined &&\n optionValue === negativeOption.presetArg))\n ) {\n return negativeOption;\n }\n return positiveOption || option;\n };\n\n const getErrorMessage = (option) => {\n const bestOption = findBestOptionFromValue(option);\n const optionKey = bestOption.attributeName();\n const source = this.getOptionValueSource(optionKey);\n if (source === 'env') {\n return `environment variable '${bestOption.envVar}'`;\n }\n return `option '${bestOption.flags}'`;\n };\n\n const message = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;\n this.error(message, { code: 'commander.conflictingOption' });\n }\n\n /**\n * Unknown option `flag`.\n *\n * @param {string} flag\n * @private\n */\n\n unknownOption(flag) {\n if (this._allowUnknownOption) return;\n let suggestion = '';\n\n if (flag.startsWith('--') && this._showSuggestionAfterError) {\n // Looping to pick up the global options too\n let candidateFlags = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let command = this;\n do {\n const moreFlags = command\n .createHelp()\n .visibleOptions(command)\n .filter((option) => option.long)\n .map((option) => option.long);\n candidateFlags = candidateFlags.concat(moreFlags);\n command = command.parent;\n } while (command && !command._enablePositionalOptions);\n suggestion = suggestSimilar(flag, candidateFlags);\n }\n\n const message = `error: unknown option '${flag}'${suggestion}`;\n this.error(message, { code: 'commander.unknownOption' });\n }\n\n /**\n * Excess arguments, more than expected.\n *\n * @param {string[]} receivedArgs\n * @private\n */\n\n _excessArguments(receivedArgs) {\n if (this._allowExcessArguments) return;\n\n const expected = this.registeredArguments.length;\n const s = expected === 1 ? '' : 's';\n const received = receivedArgs.length;\n const forSubcommand = this.parent ? ` for '${this.name()}'` : '';\n const details = receivedArgs.join(', ');\n const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${received}: ${details}.`;\n this.error(message, { code: 'commander.excessArguments' });\n }\n\n /**\n * Unknown command.\n *\n * @private\n */\n\n unknownCommand() {\n const unknownName = this.args[0];\n let suggestion = '';\n\n if (this._showSuggestionAfterError) {\n const candidateNames = [];\n this.createHelp()\n .visibleCommands(this)\n .forEach((command) => {\n candidateNames.push(command.name());\n // just visible alias\n if (command.alias()) candidateNames.push(command.alias());\n });\n suggestion = suggestSimilar(unknownName, candidateNames);\n }\n\n const message = `error: unknown command '${unknownName}'${suggestion}`;\n this.error(message, { code: 'commander.unknownCommand' });\n }\n\n /**\n * Get or set the program version.\n *\n * This method auto-registers the \"-V, --version\" option which will print the version number.\n *\n * You can optionally supply the flags and description to override the defaults.\n *\n * @param {string} [str]\n * @param {string} [flags]\n * @param {string} [description]\n * @return {(this | string | undefined)} `this` command for chaining, or version string if no arguments\n */\n\n version(str, flags, description) {\n if (str === undefined) return this._version;\n this._version = str;\n flags = flags || '-V, --version';\n description = description || 'output the version number';\n const versionOption = this.createOption(flags, description);\n this._versionOptionName = versionOption.attributeName();\n this._registerOption(versionOption);\n\n this.on('option:' + versionOption.name(), () => {\n this._outputConfiguration.writeOut(`${str}\\n`);\n this._exit(0, 'commander.version', str);\n });\n return this;\n }\n\n /**\n * Set the description.\n *\n * @param {string} [str]\n * @param {object} [argsDescription]\n * @return {(string|Command)}\n */\n description(str, argsDescription) {\n if (str === undefined && argsDescription === undefined)\n return this._description;\n this._description = str;\n if (argsDescription) {\n this._argsDescription = argsDescription;\n }\n return this;\n }\n\n /**\n * Set the summary. Used when listed as subcommand of parent.\n *\n * @param {string} [str]\n * @return {(string|Command)}\n */\n summary(str) {\n if (str === undefined) return this._summary;\n this._summary = str;\n return this;\n }\n\n /**\n * Set an alias for the command.\n *\n * You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.\n *\n * @param {string} [alias]\n * @return {(string|Command)}\n */\n\n alias(alias) {\n if (alias === undefined) return this._aliases[0]; // just return first, for backwards compatibility\n\n /** @type {Command} */\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let command = this;\n if (\n this.commands.length !== 0 &&\n this.commands[this.commands.length - 1]._executableHandler\n ) {\n // assume adding alias for last added executable subcommand, rather than this\n command = this.commands[this.commands.length - 1];\n }\n\n if (alias === command._name)\n throw new Error(\"Command alias can't be the same as its name\");\n const matchingCommand = this.parent?._findCommand(alias);\n if (matchingCommand) {\n // c.f. _registerCommand\n const existingCmd = [matchingCommand.name()]\n .concat(matchingCommand.aliases())\n .join('|');\n throw new Error(\n `cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`,\n );\n }\n\n command._aliases.push(alias);\n return this;\n }\n\n /**\n * Set aliases for the command.\n *\n * Only the first alias is shown in the auto-generated help.\n *\n * @param {string[]} [aliases]\n * @return {(string[]|Command)}\n */\n\n aliases(aliases) {\n // Getter for the array of aliases is the main reason for having aliases() in addition to alias().\n if (aliases === undefined) return this._aliases;\n\n aliases.forEach((alias) => this.alias(alias));\n return this;\n }\n\n /**\n * Set / get the command usage `str`.\n *\n * @param {string} [str]\n * @return {(string|Command)}\n */\n\n usage(str) {\n if (str === undefined) {\n if (this._usage) return this._usage;\n\n const args = this.registeredArguments.map((arg) => {\n return humanReadableArgName(arg);\n });\n return []\n .concat(\n this.options.length || this._helpOption !== null ? '[options]' : [],\n this.commands.length ? '[command]' : [],\n this.registeredArguments.length ? args : [],\n )\n .join(' ');\n }\n\n this._usage = str;\n return this;\n }\n\n /**\n * Get or set the name of the command.\n *\n * @param {string} [str]\n * @return {(string|Command)}\n */\n\n name(str) {\n if (str === undefined) return this._name;\n this._name = str;\n return this;\n }\n\n /**\n * Set/get the help group heading for this subcommand in parent command's help.\n *\n * @param {string} [heading]\n * @return {Command | string}\n */\n\n helpGroup(heading) {\n if (heading === undefined) return this._helpGroupHeading ?? '';\n this._helpGroupHeading = heading;\n return this;\n }\n\n /**\n * Set/get the default help group heading for subcommands added to this command.\n * (This does not override a group set directly on the subcommand using .helpGroup().)\n *\n * @example\n * program.commandsGroup('Development Commands:);\n * program.command('watch')...\n * program.command('lint')...\n * ...\n *\n * @param {string} [heading]\n * @returns {Command | string}\n */\n commandsGroup(heading) {\n if (heading === undefined) return this._defaultCommandGroup ?? '';\n this._defaultCommandGroup = heading;\n return this;\n }\n\n /**\n * Set/get the default help group heading for options added to this command.\n * (This does not override a group set directly on the option using .helpGroup().)\n *\n * @example\n * program\n * .optionsGroup('Development Options:')\n * .option('-d, --debug', 'output extra debugging')\n * .option('-p, --profile', 'output profiling information')\n *\n * @param {string} [heading]\n * @returns {Command | string}\n */\n optionsGroup(heading) {\n if (heading === undefined) return this._defaultOptionGroup ?? '';\n this._defaultOptionGroup = heading;\n return this;\n }\n\n /**\n * @param {Option} option\n * @private\n */\n _initOptionGroup(option) {\n if (this._defaultOptionGroup && !option.helpGroupHeading)\n option.helpGroup(this._defaultOptionGroup);\n }\n\n /**\n * @param {Command} cmd\n * @private\n */\n _initCommandGroup(cmd) {\n if (this._defaultCommandGroup && !cmd.helpGroup())\n cmd.helpGroup(this._defaultCommandGroup);\n }\n\n /**\n * Set the name of the command from script filename, such as process.argv[1],\n * or import.meta.filename.\n *\n * (Used internally and public although not documented in README.)\n *\n * @example\n * program.nameFromFilename(import.meta.filename);\n *\n * @param {string} filename\n * @return {Command}\n */\n\n nameFromFilename(filename) {\n this._name = path.basename(filename, path.extname(filename));\n\n return this;\n }\n\n /**\n * Get or set the directory for searching for executable subcommands of this command.\n *\n * @example\n * program.executableDir(import.meta.dirname);\n * // or\n * program.executableDir('subcommands');\n *\n * @param {string} [path]\n * @return {(string|null|Command)}\n */\n\n executableDir(path) {\n if (path === undefined) return this._executableDir;\n this._executableDir = path;\n return this;\n }\n\n /**\n * Return program help documentation.\n *\n * @param {{ error: boolean }} [contextOptions] - pass {error:true} to wrap for stderr instead of stdout\n * @return {string}\n */\n\n helpInformation(contextOptions) {\n const helper = this.createHelp();\n const context = this._getOutputContext(contextOptions);\n helper.prepareContext({\n error: context.error,\n helpWidth: context.helpWidth,\n outputHasColors: context.hasColors,\n });\n const text = helper.formatHelp(this, helper);\n if (context.hasColors) return text;\n return this._outputConfiguration.stripColor(text);\n }\n\n /**\n * @typedef HelpContext\n * @type {object}\n * @property {boolean} error\n * @property {number} helpWidth\n * @property {boolean} hasColors\n * @property {function} write - includes stripColor if needed\n *\n * @returns {HelpContext}\n * @private\n */\n\n _getOutputContext(contextOptions) {\n contextOptions = contextOptions || {};\n const error = !!contextOptions.error;\n let baseWrite;\n let hasColors;\n let helpWidth;\n if (error) {\n baseWrite = (str) => this._outputConfiguration.writeErr(str);\n hasColors = this._outputConfiguration.getErrHasColors();\n helpWidth = this._outputConfiguration.getErrHelpWidth();\n } else {\n baseWrite = (str) => this._outputConfiguration.writeOut(str);\n hasColors = this._outputConfiguration.getOutHasColors();\n helpWidth = this._outputConfiguration.getOutHelpWidth();\n }\n const write = (str) => {\n if (!hasColors) str = this._outputConfiguration.stripColor(str);\n return baseWrite(str);\n };\n return { error, write, hasColors, helpWidth };\n }\n\n /**\n * Output help information for this command.\n *\n * Outputs built-in help, and custom text added using `.addHelpText()`.\n *\n * @param {{ error: boolean } | Function} [contextOptions] - pass {error:true} to write to stderr instead of stdout\n */\n\n outputHelp(contextOptions) {\n let deprecatedCallback;\n if (typeof contextOptions === 'function') {\n deprecatedCallback = contextOptions;\n contextOptions = undefined;\n }\n\n const outputContext = this._getOutputContext(contextOptions);\n /** @type {HelpTextEventContext} */\n const eventContext = {\n error: outputContext.error,\n write: outputContext.write,\n command: this,\n };\n\n this._getCommandAndAncestors()\n .reverse()\n .forEach((command) => command.emit('beforeAllHelp', eventContext));\n this.emit('beforeHelp', eventContext);\n\n let helpInformation = this.helpInformation({ error: outputContext.error });\n if (deprecatedCallback) {\n helpInformation = deprecatedCallback(helpInformation);\n if (\n typeof helpInformation !== 'string' &&\n !Buffer.isBuffer(helpInformation)\n ) {\n throw new Error('outputHelp callback must return a string or a Buffer');\n }\n }\n outputContext.write(helpInformation);\n\n if (this._getHelpOption()?.long) {\n this.emit(this._getHelpOption().long); // deprecated\n }\n this.emit('afterHelp', eventContext);\n this._getCommandAndAncestors().forEach((command) =>\n command.emit('afterAllHelp', eventContext),\n );\n }\n\n /**\n * You can pass in flags and a description to customise the built-in help option.\n * Pass in false to disable the built-in help option.\n *\n * @example\n * program.helpOption('-?, --help' 'show help'); // customise\n * program.helpOption(false); // disable\n *\n * @param {(string | boolean)} flags\n * @param {string} [description]\n * @return {Command} `this` command for chaining\n */\n\n helpOption(flags, description) {\n // Support enabling/disabling built-in help option.\n if (typeof flags === 'boolean') {\n if (flags) {\n if (this._helpOption === null) this._helpOption = undefined; // reenable\n if (this._defaultOptionGroup) {\n // make the option to store the group\n this._initOptionGroup(this._getHelpOption());\n }\n } else {\n this._helpOption = null; // disable\n }\n return this;\n }\n\n // Customise flags and description.\n this._helpOption = this.createOption(\n flags ?? '-h, --help',\n description ?? 'display help for command',\n );\n // init group unless lazy create\n if (flags || description) this._initOptionGroup(this._helpOption);\n\n return this;\n }\n\n /**\n * Lazy create help option.\n * Returns null if has been disabled with .helpOption(false).\n *\n * @returns {(Option | null)} the help option\n * @package\n */\n _getHelpOption() {\n // Lazy create help option on demand.\n if (this._helpOption === undefined) {\n this.helpOption(undefined, undefined);\n }\n return this._helpOption;\n }\n\n /**\n * Supply your own option to use for the built-in help option.\n * This is an alternative to using helpOption() to customise the flags and description etc.\n *\n * @param {Option} option\n * @return {Command} `this` command for chaining\n */\n addHelpOption(option) {\n this._helpOption = option;\n this._initOptionGroup(option);\n return this;\n }\n\n /**\n * Output help information and exit.\n *\n * Outputs built-in help, and custom text added using `.addHelpText()`.\n *\n * @param {{ error: boolean }} [contextOptions] - pass {error:true} to write to stderr instead of stdout\n */\n\n help(contextOptions) {\n this.outputHelp(contextOptions);\n let exitCode = Number(process.exitCode ?? 0); // process.exitCode does allow a string or an integer, but we prefer just a number\n if (\n exitCode === 0 &&\n contextOptions &&\n typeof contextOptions !== 'function' &&\n contextOptions.error\n ) {\n exitCode = 1;\n }\n // message: do not have all displayed text available so only passing placeholder.\n this._exit(exitCode, 'commander.help', '(outputHelp)');\n }\n\n /**\n * // Do a little typing to coordinate emit and listener for the help text events.\n * @typedef HelpTextEventContext\n * @type {object}\n * @property {boolean} error\n * @property {Command} command\n * @property {function} write\n */\n\n /**\n * Add additional text to be displayed with the built-in help.\n *\n * Position is 'before' or 'after' to affect just this command,\n * and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.\n *\n * @param {string} position - before or after built-in help\n * @param {(string | Function)} text - string to add, or a function returning a string\n * @return {Command} `this` command for chaining\n */\n\n addHelpText(position, text) {\n const allowedValues = ['beforeAll', 'before', 'after', 'afterAll'];\n if (!allowedValues.includes(position)) {\n throw new Error(`Unexpected value for position to addHelpText.\nExpecting one of '${allowedValues.join(\"', '\")}'`);\n }\n\n const helpEvent = `${position}Help`;\n this.on(helpEvent, (/** @type {HelpTextEventContext} */ context) => {\n let helpStr;\n if (typeof text === 'function') {\n helpStr = text({ error: context.error, command: context.command });\n } else {\n helpStr = text;\n }\n // Ignore falsy value when nothing to output.\n if (helpStr) {\n context.write(`${helpStr}\\n`);\n }\n });\n return this;\n }\n\n /**\n * Output help information if help flags specified\n *\n * @param {Array} args - array of options to search for help flags\n * @private\n */\n\n _outputHelpIfRequested(args) {\n const helpOption = this._getHelpOption();\n const helpRequested = helpOption && args.find((arg) => helpOption.is(arg));\n if (helpRequested) {\n this.outputHelp();\n // (Do not have all displayed text available so only passing placeholder.)\n this._exit(0, 'commander.helpDisplayed', '(outputHelp)');\n }\n }\n}\n\n/**\n * Scan arguments and increment port number for inspect calls (to avoid conflicts when spawning new command).\n *\n * @param {string[]} args - array of arguments from node.execArgv\n * @returns {string[]}\n * @private\n */\n\nfunction incrementNodeInspectorPort(args) {\n // Testing for these options:\n // --inspect[=[host:]port]\n // --inspect-brk[=[host:]port]\n // --inspect-port=[host:]port\n return args.map((arg) => {\n if (!arg.startsWith('--inspect')) {\n return arg;\n }\n let debugOption;\n let debugHost = '127.0.0.1';\n let debugPort = '9229';\n let match;\n if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {\n // e.g. --inspect\n debugOption = match[1];\n } else if (\n (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null\n ) {\n debugOption = match[1];\n if (/^\\d+$/.test(match[3])) {\n // e.g. --inspect=1234\n debugPort = match[3];\n } else {\n // e.g. --inspect=localhost\n debugHost = match[3];\n }\n } else if (\n (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\\d+)$/)) !== null\n ) {\n // e.g. --inspect=localhost:1234\n debugOption = match[1];\n debugHost = match[3];\n debugPort = match[4];\n }\n\n if (debugOption && debugPort !== '0') {\n return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;\n }\n return arg;\n });\n}\n\n/**\n * Exported for using from tests, not otherwise used outside this file.\n *\n * @returns {boolean | undefined}\n * @package\n */\nexport function useColor() {\n // Test for common conventions.\n // NB: the observed behaviour is in combination with how author adds color! For example:\n // - we do not test NODE_DISABLE_COLORS, but util:styletext does\n // - we do test NO_COLOR, but Chalk does not\n //\n // References:\n // https://no-color.org\n // https://bixense.com/clicolors/\n // https://github.com/nodejs/node/blob/0a00217a5f67ef4a22384cfc80eb6dd9a917fdc1/lib/internal/tty.js#L109\n // https://github.com/chalk/supports-color/blob/c214314a14bcb174b12b3014b2b0a8de375029ae/index.js#L33\n // (https://force-color.org recent web page from 2023, does not match major javascript implementations)\n\n if (\n process.env.NO_COLOR ||\n process.env.FORCE_COLOR === '0' ||\n process.env.FORCE_COLOR === 'false'\n )\n return false;\n if (process.env.FORCE_COLOR || process.env.CLICOLOR_FORCE !== undefined)\n return true;\n return undefined;\n}\n", "import { humanReadableArgName } from './argument.js';\nimport { stripVTControlCharacters } from 'node:util';\n\n/**\n * TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`\n * https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types\n * @typedef { import(\"./argument.js\").Argument } Argument\n * @typedef { import(\"./command.js\").Command } Command\n * @typedef { import(\"./option.js\").Option } Option\n */\n\n// Although this is a class, methods are static in style to allow override using subclass or just functions.\nexport class Help {\n constructor() {\n this.helpWidth = undefined;\n this.minWidthToWrap = 40;\n this.sortSubcommands = false;\n this.sortOptions = false;\n this.showGlobalOptions = false;\n }\n\n /**\n * prepareContext is called by Commander after applying overrides from `Command.configureHelp()`\n * and just before calling `formatHelp()`.\n *\n * Commander just uses the helpWidth and the rest is provided for optional use by more complex subclasses.\n *\n * @param {{ error?: boolean, helpWidth?: number, outputHasColors?: boolean }} contextOptions\n */\n prepareContext(contextOptions) {\n this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;\n }\n\n /**\n * Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.\n *\n * @param {Command} cmd\n * @returns {Command[]}\n */\n\n visibleCommands(cmd) {\n const visibleCommands = cmd.commands.filter((cmd) => !cmd._hidden);\n const helpCommand = cmd._getHelpCommand();\n if (helpCommand && !helpCommand._hidden) {\n visibleCommands.push(helpCommand);\n }\n if (this.sortSubcommands) {\n visibleCommands.sort((a, b) => {\n // @ts-ignore: because overloaded return type\n return a.name().localeCompare(b.name());\n });\n }\n return visibleCommands;\n }\n\n /**\n * Compare options for sort.\n *\n * @param {Option} a\n * @param {Option} b\n * @returns {number}\n */\n compareOptions(a, b) {\n const getSortKey = (option) => {\n // WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated.\n return option.short\n ? option.short.replace(/^-/, '')\n : option.long.replace(/^--/, '');\n };\n return getSortKey(a).localeCompare(getSortKey(b));\n }\n\n /**\n * Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.\n *\n * @param {Command} cmd\n * @returns {Option[]}\n */\n\n visibleOptions(cmd) {\n const visibleOptions = cmd.options.filter((option) => !option.hidden);\n // Built-in help option.\n const helpOption = cmd._getHelpOption();\n if (helpOption && !helpOption.hidden) {\n // Automatically hide conflicting flags. Bit dubious but a historical behaviour that is convenient for single-command programs.\n const removeShort = helpOption.short && cmd._findOption(helpOption.short);\n const removeLong = helpOption.long && cmd._findOption(helpOption.long);\n if (!removeShort && !removeLong) {\n visibleOptions.push(helpOption); // no changes needed\n } else if (helpOption.long && !removeLong) {\n visibleOptions.push(\n cmd.createOption(helpOption.long, helpOption.description),\n );\n } else if (helpOption.short && !removeShort) {\n visibleOptions.push(\n cmd.createOption(helpOption.short, helpOption.description),\n );\n }\n }\n if (this.sortOptions) {\n visibleOptions.sort(this.compareOptions);\n }\n return visibleOptions;\n }\n\n /**\n * Get an array of the visible global options. (Not including help.)\n *\n * @param {Command} cmd\n * @returns {Option[]}\n */\n\n visibleGlobalOptions(cmd) {\n if (!this.showGlobalOptions) return [];\n\n const globalOptions = [];\n for (\n let ancestorCmd = cmd.parent;\n ancestorCmd;\n ancestorCmd = ancestorCmd.parent\n ) {\n const visibleOptions = ancestorCmd.options.filter(\n (option) => !option.hidden,\n );\n globalOptions.push(...visibleOptions);\n }\n if (this.sortOptions) {\n globalOptions.sort(this.compareOptions);\n }\n return globalOptions;\n }\n\n /**\n * Get an array of the arguments if any have a description.\n *\n * @param {Command} cmd\n * @returns {Argument[]}\n */\n\n visibleArguments(cmd) {\n // Side effect! Apply the legacy descriptions before the arguments are displayed.\n if (cmd._argsDescription) {\n cmd.registeredArguments.forEach((argument) => {\n argument.description =\n argument.description || cmd._argsDescription[argument.name()] || '';\n });\n }\n\n // If there are any arguments with a description then return all the arguments.\n if (cmd.registeredArguments.find((argument) => argument.description)) {\n return cmd.registeredArguments;\n }\n return [];\n }\n\n /**\n * Get the command term to show in the list of subcommands.\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n subcommandTerm(cmd) {\n // Legacy. Ignores custom usage string, and nested commands.\n const args = cmd.registeredArguments\n .map((arg) => humanReadableArgName(arg))\n .join(' ');\n return (\n cmd._name +\n (cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +\n (cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option\n (args ? ' ' + args : '')\n );\n }\n\n /**\n * Get the option term to show in the list of options.\n *\n * @param {Option} option\n * @returns {string}\n */\n\n optionTerm(option) {\n return option.flags;\n }\n\n /**\n * Get the argument term to show in the list of arguments.\n *\n * @param {Argument} argument\n * @returns {string}\n */\n\n argumentTerm(argument) {\n return argument.name();\n }\n\n /**\n * Get the longest command term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestSubcommandTermLength(cmd, helper) {\n return helper.visibleCommands(cmd).reduce((max, command) => {\n return Math.max(\n max,\n this.displayWidth(\n helper.styleSubcommandTerm(helper.subcommandTerm(command)),\n ),\n );\n }, 0);\n }\n\n /**\n * Get the longest option term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestOptionTermLength(cmd, helper) {\n return helper.visibleOptions(cmd).reduce((max, option) => {\n return Math.max(\n max,\n this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),\n );\n }, 0);\n }\n\n /**\n * Get the longest global option term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestGlobalOptionTermLength(cmd, helper) {\n return helper.visibleGlobalOptions(cmd).reduce((max, option) => {\n return Math.max(\n max,\n this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),\n );\n }, 0);\n }\n\n /**\n * Get the longest argument term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n longestArgumentTermLength(cmd, helper) {\n return helper.visibleArguments(cmd).reduce((max, argument) => {\n return Math.max(\n max,\n this.displayWidth(\n helper.styleArgumentTerm(helper.argumentTerm(argument)),\n ),\n );\n }, 0);\n }\n\n /**\n * Get the command usage to be displayed at the top of the built-in help.\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n commandUsage(cmd) {\n // Usage\n let cmdName = cmd._name;\n if (cmd._aliases[0]) {\n cmdName = cmdName + '|' + cmd._aliases[0];\n }\n let ancestorCmdNames = '';\n for (\n let ancestorCmd = cmd.parent;\n ancestorCmd;\n ancestorCmd = ancestorCmd.parent\n ) {\n ancestorCmdNames = ancestorCmd.name() + ' ' + ancestorCmdNames;\n }\n return ancestorCmdNames + cmdName + ' ' + cmd.usage();\n }\n\n /**\n * Get the description for the command.\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n commandDescription(cmd) {\n // @ts-ignore: because overloaded return type\n return cmd.description();\n }\n\n /**\n * Get the subcommand summary to show in the list of subcommands.\n * (Fallback to description for backwards compatibility.)\n *\n * @param {Command} cmd\n * @returns {string}\n */\n\n subcommandDescription(cmd) {\n // @ts-ignore: because overloaded return type\n return cmd.summary() || cmd.description();\n }\n\n /**\n * Get the option description to show in the list of options.\n *\n * @param {Option} option\n * @return {string}\n */\n\n optionDescription(option) {\n const extraInfo = [];\n\n if (option.argChoices) {\n extraInfo.push(\n // use stringify to match the display of the default value\n `choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,\n );\n }\n if (option.defaultValue !== undefined) {\n // default for boolean and negated more for programmer than end user,\n // but show true/false for boolean option as may be for hand-rolled env or config processing.\n const showDefault =\n option.required ||\n option.optional ||\n (option.isBoolean() && typeof option.defaultValue === 'boolean');\n if (showDefault) {\n extraInfo.push(\n `default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`,\n );\n }\n }\n // preset for boolean and negated are more for programmer than end user\n if (option.presetArg !== undefined && option.optional) {\n extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);\n }\n if (option.envVar !== undefined) {\n extraInfo.push(`env: ${option.envVar}`);\n }\n if (extraInfo.length > 0) {\n const extraDescription = `(${extraInfo.join(', ')})`;\n if (option.description) {\n return `${option.description} ${extraDescription}`;\n }\n return extraDescription;\n }\n\n return option.description;\n }\n\n /**\n * Get the argument description to show in the list of arguments.\n *\n * @param {Argument} argument\n * @return {string}\n */\n\n argumentDescription(argument) {\n const extraInfo = [];\n if (argument.argChoices) {\n extraInfo.push(\n // use stringify to match the display of the default value\n `choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,\n );\n }\n if (argument.defaultValue !== undefined) {\n extraInfo.push(\n `default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`,\n );\n }\n if (extraInfo.length > 0) {\n const extraDescription = `(${extraInfo.join(', ')})`;\n if (argument.description) {\n return `${argument.description} ${extraDescription}`;\n }\n return extraDescription;\n }\n return argument.description;\n }\n\n /**\n * Format a list of items, given a heading and an array of formatted items.\n *\n * @param {string} heading\n * @param {string[]} items\n * @param {Help} helper\n * @returns string[]\n */\n formatItemList(heading, items, helper) {\n if (items.length === 0) return [];\n\n return [helper.styleTitle(heading), ...items, ''];\n }\n\n /**\n * Group items by their help group heading.\n *\n * @param {Command[] | Option[]} unsortedItems\n * @param {Command[] | Option[]} visibleItems\n * @param {Function} getGroup\n * @returns {Map}\n */\n groupItems(unsortedItems, visibleItems, getGroup) {\n const result = new Map();\n // Add groups in order of appearance in unsortedItems.\n unsortedItems.forEach((item) => {\n const group = getGroup(item);\n if (!result.has(group)) result.set(group, []);\n });\n // Add items in order of appearance in visibleItems.\n visibleItems.forEach((item) => {\n const group = getGroup(item);\n if (!result.has(group)) {\n result.set(group, []);\n }\n result.get(group).push(item);\n });\n return result;\n }\n\n /**\n * Generate the built-in help text.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {string}\n */\n\n formatHelp(cmd, helper) {\n const termWidth = helper.padWidth(cmd, helper);\n const helpWidth = helper.helpWidth ?? 80; // in case prepareContext() was not called\n\n function callFormatItem(term, description) {\n return helper.formatItem(term, termWidth, description, helper);\n }\n\n // Usage\n let output = [\n `${helper.styleTitle('Usage:')} ${helper.styleUsage(helper.commandUsage(cmd))}`,\n '',\n ];\n\n // Description\n const commandDescription = helper.commandDescription(cmd);\n if (commandDescription.length > 0) {\n output = output.concat([\n helper.boxWrap(\n helper.styleCommandDescription(commandDescription),\n helpWidth,\n ),\n '',\n ]);\n }\n\n // Arguments\n const argumentList = helper.visibleArguments(cmd).map((argument) => {\n return callFormatItem(\n helper.styleArgumentTerm(helper.argumentTerm(argument)),\n helper.styleArgumentDescription(helper.argumentDescription(argument)),\n );\n });\n output = output.concat(\n this.formatItemList('Arguments:', argumentList, helper),\n );\n\n // Options\n const optionGroups = this.groupItems(\n cmd.options,\n helper.visibleOptions(cmd),\n (option) => option.helpGroupHeading ?? 'Options:',\n );\n optionGroups.forEach((options, group) => {\n const optionList = options.map((option) => {\n return callFormatItem(\n helper.styleOptionTerm(helper.optionTerm(option)),\n helper.styleOptionDescription(helper.optionDescription(option)),\n );\n });\n output = output.concat(this.formatItemList(group, optionList, helper));\n });\n\n if (helper.showGlobalOptions) {\n const globalOptionList = helper\n .visibleGlobalOptions(cmd)\n .map((option) => {\n return callFormatItem(\n helper.styleOptionTerm(helper.optionTerm(option)),\n helper.styleOptionDescription(helper.optionDescription(option)),\n );\n });\n output = output.concat(\n this.formatItemList('Global Options:', globalOptionList, helper),\n );\n }\n\n // Commands\n const commandGroups = this.groupItems(\n cmd.commands,\n helper.visibleCommands(cmd),\n (sub) => sub.helpGroup() || 'Commands:',\n );\n commandGroups.forEach((commands, group) => {\n const commandList = commands.map((sub) => {\n return callFormatItem(\n helper.styleSubcommandTerm(helper.subcommandTerm(sub)),\n helper.styleSubcommandDescription(helper.subcommandDescription(sub)),\n );\n });\n output = output.concat(this.formatItemList(group, commandList, helper));\n });\n\n return output.join('\\n');\n }\n\n /**\n * Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.\n *\n * @param {string} str\n * @returns {number}\n */\n displayWidth(str) {\n return stripVTControlCharacters(str).length;\n }\n\n /**\n * Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.\n *\n * @param {string} str\n * @returns {string}\n */\n styleTitle(str) {\n return str;\n }\n\n styleUsage(str) {\n // Usage has lots of parts the user might like to color separately! Assume default usage string which is formed like:\n // command subcommand [options] [command] [bar]\n return str\n .split(' ')\n .map((word) => {\n if (word === '[options]') return this.styleOptionText(word);\n if (word === '[command]') return this.styleSubcommandText(word);\n if (word[0] === '[' || word[0] === '<')\n return this.styleArgumentText(word);\n return this.styleCommandText(word); // Restrict to initial words?\n })\n .join(' ');\n }\n styleCommandDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleOptionDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleSubcommandDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleArgumentDescription(str) {\n return this.styleDescriptionText(str);\n }\n styleDescriptionText(str) {\n return str;\n }\n styleOptionTerm(str) {\n return this.styleOptionText(str);\n }\n styleSubcommandTerm(str) {\n // This is very like usage with lots of parts! Assume default string which is formed like:\n // subcommand [options] [bar]\n return str\n .split(' ')\n .map((word) => {\n if (word === '[options]') return this.styleOptionText(word);\n if (word[0] === '[' || word[0] === '<')\n return this.styleArgumentText(word);\n return this.styleSubcommandText(word); // Restrict to initial words?\n })\n .join(' ');\n }\n styleArgumentTerm(str) {\n return this.styleArgumentText(str);\n }\n styleOptionText(str) {\n return str;\n }\n styleArgumentText(str) {\n return str;\n }\n styleSubcommandText(str) {\n return str;\n }\n styleCommandText(str) {\n return str;\n }\n\n /**\n * Calculate the pad width from the maximum term length.\n *\n * @param {Command} cmd\n * @param {Help} helper\n * @returns {number}\n */\n\n padWidth(cmd, helper) {\n return Math.max(\n helper.longestOptionTermLength(cmd, helper),\n helper.longestGlobalOptionTermLength(cmd, helper),\n helper.longestSubcommandTermLength(cmd, helper),\n helper.longestArgumentTermLength(cmd, helper),\n );\n }\n\n /**\n * Detect manually wrapped and indented strings by checking for line break followed by whitespace.\n *\n * @param {string} str\n * @returns {boolean}\n */\n preformatted(str) {\n return /\\n[^\\S\\r\\n]/.test(str);\n }\n\n /**\n * Format the \"item\", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.\n *\n * So \"TTT\", 5, \"DDD DDDD DD DDD\" might be formatted for this.helpWidth=17 like so:\n * TTT DDD DDDD\n * DD DDD\n *\n * @param {string} term\n * @param {number} termWidth\n * @param {string} description\n * @param {Help} helper\n * @returns {string}\n */\n formatItem(term, termWidth, description, helper) {\n const itemIndent = 2;\n const itemIndentStr = ' '.repeat(itemIndent);\n if (!description) return itemIndentStr + term;\n\n // Pad the term out to a consistent width, so descriptions are aligned.\n const paddedTerm = term.padEnd(\n termWidth + term.length - helper.displayWidth(term),\n );\n\n // Format the description.\n const spacerWidth = 2; // between term and description\n const helpWidth = this.helpWidth ?? 80; // in case prepareContext() was not called\n const remainingWidth = helpWidth - termWidth - spacerWidth - itemIndent;\n let formattedDescription;\n if (\n remainingWidth < this.minWidthToWrap ||\n helper.preformatted(description)\n ) {\n formattedDescription = description;\n } else {\n const wrappedDescription = helper.boxWrap(description, remainingWidth);\n formattedDescription = wrappedDescription.replace(\n /\\n/g,\n '\\n' + ' '.repeat(termWidth + spacerWidth),\n );\n }\n\n // Construct and overall indent.\n return (\n itemIndentStr +\n paddedTerm +\n ' '.repeat(spacerWidth) +\n formattedDescription.replace(/\\n/g, `\\n${itemIndentStr}`)\n );\n }\n\n /**\n * Wrap a string at whitespace, preserving existing line breaks.\n * Wrapping is skipped if the width is less than `minWidthToWrap`.\n *\n * @param {string} str\n * @param {number} width\n * @returns {string}\n */\n boxWrap(str, width) {\n if (width < this.minWidthToWrap) return str;\n\n const rawLines = str.split(/\\r\\n|\\n/);\n // split up text by whitespace\n const chunkPattern = /[\\s]*[^\\s]+/g;\n const wrappedLines = [];\n rawLines.forEach((line) => {\n const chunks = line.match(chunkPattern);\n if (chunks === null) {\n wrappedLines.push('');\n return;\n }\n\n let sumChunks = [chunks.shift()];\n let sumWidth = this.displayWidth(sumChunks[0]);\n chunks.forEach((chunk) => {\n const visibleWidth = this.displayWidth(chunk);\n // Accumulate chunks while they fit into width.\n if (sumWidth + visibleWidth <= width) {\n sumChunks.push(chunk);\n sumWidth += visibleWidth;\n return;\n }\n wrappedLines.push(sumChunks.join(''));\n\n const nextChunk = chunk.trimStart(); // trim space at line break\n sumChunks = [nextChunk];\n sumWidth = this.displayWidth(nextChunk);\n });\n wrappedLines.push(sumChunks.join(''));\n });\n\n return wrappedLines.join('\\n');\n }\n}\n", "import { InvalidArgumentError } from './error.js';\n\nexport class Option {\n /**\n * Initialize a new `Option` with the given `flags` and `description`.\n *\n * @param {string} flags\n * @param {string} [description]\n */\n\n constructor(flags, description) {\n this.flags = flags;\n this.description = description || '';\n\n this.required = flags.includes('<'); // A value must be supplied when the option is specified.\n this.optional = flags.includes('['); // A value is optional when the option is specified.\n // variadic test ignores et al which might be used to describe custom splitting of single argument\n this.variadic = /\\w\\.\\.\\.[>\\]]$/.test(flags); // The option can take multiple values.\n this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.\n const optionFlags = splitOptionFlags(flags);\n this.short = optionFlags.shortFlag; // May be a short flag, undefined, or even a long flag (if option has two long flags).\n this.long = optionFlags.longFlag;\n this.negate = false;\n if (this.long) {\n this.negate = this.long.startsWith('--no-');\n }\n this.defaultValue = undefined;\n this.defaultValueDescription = undefined;\n this.presetArg = undefined;\n this.envVar = undefined;\n this.parseArg = undefined;\n this.hidden = false;\n this.argChoices = undefined;\n this.conflictsWith = [];\n this.implied = undefined;\n this.helpGroupHeading = undefined; // soft initialised when option added to command\n }\n\n /**\n * Set the default value, and optionally supply the description to be displayed in the help.\n *\n * @param {*} value\n * @param {string} [description]\n * @return {Option}\n */\n\n default(value, description) {\n this.defaultValue = value;\n this.defaultValueDescription = description;\n return this;\n }\n\n /**\n * Preset to use when option used without option-argument, especially optional but also boolean and negated.\n * The custom processing (parseArg) is called.\n *\n * @example\n * new Option('--color').default('GREYSCALE').preset('RGB');\n * new Option('--donate [amount]').preset('20').argParser(parseFloat);\n *\n * @param {*} arg\n * @return {Option}\n */\n\n preset(arg) {\n this.presetArg = arg;\n return this;\n }\n\n /**\n * Add option name(s) that conflict with this option.\n * An error will be displayed if conflicting options are found during parsing.\n *\n * @example\n * new Option('--rgb').conflicts('cmyk');\n * new Option('--js').conflicts(['ts', 'jsx']);\n *\n * @param {(string | string[])} names\n * @return {Option}\n */\n\n conflicts(names) {\n this.conflictsWith = this.conflictsWith.concat(names);\n return this;\n }\n\n /**\n * Specify implied option values for when this option is set and the implied options are not.\n *\n * The custom processing (parseArg) is not called on the implied values.\n *\n * @example\n * program\n * .addOption(new Option('--log', 'write logging information to file'))\n * .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));\n *\n * @param {object} impliedOptionValues\n * @return {Option}\n */\n implies(impliedOptionValues) {\n let newImplied = impliedOptionValues;\n if (typeof impliedOptionValues === 'string') {\n // string is not documented, but easy mistake and we can do what user probably intended.\n newImplied = { [impliedOptionValues]: true };\n }\n this.implied = Object.assign(this.implied || {}, newImplied);\n return this;\n }\n\n /**\n * Set environment variable to check for option value.\n *\n * An environment variable is only used if when processed the current option value is\n * undefined, or the source of the current value is 'default' or 'config' or 'env'.\n *\n * @param {string} name\n * @return {Option}\n */\n\n env(name) {\n this.envVar = name;\n return this;\n }\n\n /**\n * Set the custom handler for processing CLI option arguments into option values.\n *\n * @param {Function} [fn]\n * @return {Option}\n */\n\n argParser(fn) {\n this.parseArg = fn;\n return this;\n }\n\n /**\n * Whether the option is mandatory and must have a value after parsing.\n *\n * @param {boolean} [mandatory=true]\n * @return {Option}\n */\n\n makeOptionMandatory(mandatory = true) {\n this.mandatory = !!mandatory;\n return this;\n }\n\n /**\n * Hide option in help.\n *\n * @param {boolean} [hide=true]\n * @return {Option}\n */\n\n hideHelp(hide = true) {\n this.hidden = !!hide;\n return this;\n }\n\n /**\n * @package\n */\n\n _collectValue(value, previous) {\n if (previous === this.defaultValue || !Array.isArray(previous)) {\n return [value];\n }\n\n previous.push(value);\n return previous;\n }\n\n /**\n * Only allow option value to be one of choices.\n *\n * @param {string[]} values\n * @return {Option}\n */\n\n choices(values) {\n this.argChoices = values.slice();\n this.parseArg = (arg, previous) => {\n if (!this.argChoices.includes(arg)) {\n throw new InvalidArgumentError(\n `Allowed choices are ${this.argChoices.join(', ')}.`,\n );\n }\n if (this.variadic) {\n return this._collectValue(arg, previous);\n }\n return arg;\n };\n return this;\n }\n\n /**\n * Return option name.\n *\n * @return {string}\n */\n\n name() {\n if (this.long) {\n return this.long.replace(/^--/, '');\n }\n return this.short.replace(/^-/, '');\n }\n\n /**\n * Return option name, in a camelcase format that can be used\n * as an object attribute key.\n *\n * @return {string}\n */\n\n attributeName() {\n if (this.negate) {\n return camelcase(this.name().replace(/^no-/, ''));\n }\n return camelcase(this.name());\n }\n\n /**\n * Set the help group heading.\n *\n * @param {string} heading\n * @return {Option}\n */\n helpGroup(heading) {\n this.helpGroupHeading = heading;\n return this;\n }\n\n /**\n * Check if `arg` matches the short or long flag.\n *\n * @param {string} arg\n * @return {boolean}\n * @package\n */\n\n is(arg) {\n return this.short === arg || this.long === arg;\n }\n\n /**\n * Return whether a boolean option.\n *\n * Options are one of boolean, negated, required argument, or optional argument.\n *\n * @return {boolean}\n * @package\n */\n\n isBoolean() {\n return !this.required && !this.optional && !this.negate;\n }\n}\n\n/**\n * This class is to make it easier to work with dual options, without changing the existing\n * implementation. We support separate dual options for separate positive and negative options,\n * like `--build` and `--no-build`, which share a single option value. This works nicely for some\n * use cases, but is tricky for others where we want separate behaviours despite\n * the single shared option value.\n */\nexport class DualOptions {\n /**\n * @param {Option[]} options\n */\n constructor(options) {\n this.positiveOptions = new Map();\n this.negativeOptions = new Map();\n this.dualOptions = new Set();\n options.forEach((option) => {\n if (option.negate) {\n this.negativeOptions.set(option.attributeName(), option);\n } else {\n this.positiveOptions.set(option.attributeName(), option);\n }\n });\n this.negativeOptions.forEach((value, key) => {\n if (this.positiveOptions.has(key)) {\n this.dualOptions.add(key);\n }\n });\n }\n\n /**\n * Did the value come from the option, and not from possible matching dual option?\n *\n * @param {*} value\n * @param {Option} option\n * @returns {boolean}\n */\n valueFromOption(value, option) {\n const optionKey = option.attributeName();\n if (!this.dualOptions.has(optionKey)) return true;\n\n // Use the value to deduce if (probably) came from the option.\n const preset = this.negativeOptions.get(optionKey).presetArg;\n const negativeValue = preset !== undefined ? preset : false;\n return option.negate === (negativeValue === value);\n }\n}\n\n/**\n * Convert string from kebab-case to camelCase.\n *\n * @param {string} str\n * @return {string}\n * @private\n */\n\nfunction camelcase(str) {\n return str.split('-').reduce((str, word) => {\n return str + word[0].toUpperCase() + word.slice(1);\n });\n}\n\n/**\n * Split the short and long flag out of something like '-m,--mixed '\n *\n * @private\n */\n\nfunction splitOptionFlags(flags) {\n let shortFlag;\n let longFlag;\n // short flag, single dash and single character\n const shortFlagExp = /^-[^-]$/;\n // long flag, double dash and at least one character\n const longFlagExp = /^--[^-]/;\n\n const flagParts = flags.split(/[ |,]+/).concat('guard');\n // Normal is short and/or long.\n if (shortFlagExp.test(flagParts[0])) shortFlag = flagParts.shift();\n if (longFlagExp.test(flagParts[0])) longFlag = flagParts.shift();\n // Long then short. Rarely used but fine.\n if (!shortFlag && shortFlagExp.test(flagParts[0]))\n shortFlag = flagParts.shift();\n // Allow two long flags, like '--ws, --workspace'\n // This is the supported way to have a shortish option flag.\n if (!shortFlag && longFlagExp.test(flagParts[0])) {\n shortFlag = longFlag;\n longFlag = flagParts.shift();\n }\n\n // Check for unprocessed flag. Fail noisily rather than silently ignore.\n if (flagParts[0].startsWith('-')) {\n const unsupportedFlag = flagParts[0];\n const baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;\n if (/^-[^-][^-]/.test(unsupportedFlag))\n throw new Error(\n `${baseError}\n- a short flag is a single dash and a single character\n - either use a single dash and a single character (for a short flag)\n - or use a double dash for a long option (and can have two, like '--ws, --workspace')`,\n );\n if (shortFlagExp.test(unsupportedFlag))\n throw new Error(`${baseError}\n- too many short flags`);\n if (longFlagExp.test(unsupportedFlag))\n throw new Error(`${baseError}\n- too many long flags`);\n\n throw new Error(`${baseError}\n- unrecognised flag format`);\n }\n if (shortFlag === undefined && longFlag === undefined)\n throw new Error(\n `option creation failed due to no flags found in '${flags}'.`,\n );\n\n return { shortFlag, longFlag };\n}\n", "const maxDistance = 3;\n\nfunction editDistance(a, b) {\n // https://en.wikipedia.org/wiki/Damerau\u2013Levenshtein_distance\n // Calculating optimal string alignment distance, no substring is edited more than once.\n // (Simple implementation.)\n\n // Quick early exit, return worst case.\n if (Math.abs(a.length - b.length) > maxDistance)\n return Math.max(a.length, b.length);\n\n // distance between prefix substrings of a and b\n const d = [];\n\n // pure deletions turn a into empty string\n for (let i = 0; i <= a.length; i++) {\n d[i] = [i];\n }\n // pure insertions turn empty string into b\n for (let j = 0; j <= b.length; j++) {\n d[0][j] = j;\n }\n\n // fill matrix\n for (let j = 1; j <= b.length; j++) {\n for (let i = 1; i <= a.length; i++) {\n let cost;\n if (a[i - 1] === b[j - 1]) {\n cost = 0;\n } else {\n cost = 1;\n }\n d[i][j] = Math.min(\n d[i - 1][j] + 1, // deletion\n d[i][j - 1] + 1, // insertion\n d[i - 1][j - 1] + cost, // substitution\n );\n // transposition\n if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);\n }\n }\n }\n\n return d[a.length][b.length];\n}\n\n/**\n * Find close matches, restricted to same number of edits.\n *\n * @param {string} word\n * @param {string[]} candidates\n * @returns {string}\n */\n\nexport function suggestSimilar(word, candidates) {\n if (!candidates || candidates.length === 0) return '';\n // remove possible duplicates\n candidates = Array.from(new Set(candidates));\n\n const searchingOptions = word.startsWith('--');\n if (searchingOptions) {\n word = word.slice(2);\n candidates = candidates.map((candidate) => candidate.slice(2));\n }\n\n let similar = [];\n let bestDistance = maxDistance;\n const minSimilarity = 0.4;\n candidates.forEach((candidate) => {\n if (candidate.length <= 1) return; // no one character guesses\n\n const distance = editDistance(word, candidate);\n const length = Math.max(word.length, candidate.length);\n const similarity = (length - distance) / length;\n if (similarity > minSimilarity) {\n if (distance < bestDistance) {\n // better edit distance, throw away previous worse matches\n bestDistance = distance;\n similar = [candidate];\n } else if (distance === bestDistance) {\n similar.push(candidate);\n }\n }\n });\n\n similar.sort((a, b) => a.localeCompare(b));\n if (searchingOptions) {\n similar = similar.map((candidate) => `--${candidate}`);\n }\n\n if (similar.length > 1) {\n return `\\n(Did you mean one of ${similar.join(', ')}?)`;\n }\n if (similar.length === 1) {\n return `\\n(Did you mean ${similar[0]}?)`;\n }\n return '';\n}\n", "import { Argument } from './lib/argument.js';\nimport { Command } from './lib/command.js';\nimport { CommanderError, InvalidArgumentError } from './lib/error.js';\nimport { Help } from './lib/help.js';\nimport { Option } from './lib/option.js';\n\nexport const program = new Command();\n\nexport const createCommand = (name) => new Command(name);\nexport const createOption = (flags, description) =>\n new Option(flags, description);\nexport const createArgument = (name, description) =>\n new Argument(name, description);\n\n/**\n * Expose classes\n */\n\nexport { Command, Option, Argument, Help };\nexport { CommanderError, InvalidArgumentError };\nexport { InvalidArgumentError as InvalidOptionArgumentError }; // Deprecated\n", "// Generated by scripts/generate-bidi-data.ts. Do not edit by hand.\n// Source: https://www.unicode.org/Public/17.0.0/ucd/extracted/DerivedBidiClass.txt\n// SHA-256: 4867b4b7f0731ed1bfcd34cc6251211ff1542541fce0734b6fbda139ee80b3a4\n// Source: https://www.unicode.org/Public/17.0.0/ucd/extracted/DerivedGeneralCategory.txt\n// SHA-256: d62e5bab70ca74f099343f71224fa051cb1fdd61a1ab45c0488c44cfc0b6102e\n\nexport const UNICODE_BIDI_VERSION = '17.0.0';\nexport const UNICODE_BIDI_SHA256 = '4867b4b7f0731ed1bfcd34cc6251211ff1542541fce0734b6fbda139ee80b3a4';\nexport const UNICODE_GENERAL_CATEGORY_SHA256 = 'd62e5bab70ca74f099343f71224fa051cb1fdd61a1ab45c0488c44cfc0b6102e';\n\nexport const RTL_BIDI_RANGES: ReadonlyArray = [\n 0x590, 0x590,\n 0x5be, 0x5be,\n 0x5c0, 0x5c0,\n 0x5c3, 0x5c3,\n 0x5c6, 0x5c6,\n 0x5c8, 0x5ff,\n 0x608, 0x608,\n 0x60b, 0x60b,\n 0x60d, 0x60d,\n 0x61b, 0x64a,\n 0x66d, 0x66f,\n 0x671, 0x6d5,\n 0x6e5, 0x6e6,\n 0x6ee, 0x6ef,\n 0x6fa, 0x710,\n 0x712, 0x72f,\n 0x74b, 0x7a5,\n 0x7b1, 0x7ea,\n 0x7f4, 0x7f5,\n 0x7fa, 0x7fc,\n 0x7fe, 0x815,\n 0x81a, 0x81a,\n 0x824, 0x824,\n 0x828, 0x828,\n 0x82e, 0x858,\n 0x85c, 0x88f,\n 0x892, 0x896,\n 0x8a0, 0x8c9,\n 0x200f, 0x200f,\n 0xfb1d, 0xfb1d,\n 0xfb1f, 0xfb28,\n 0xfb2a, 0xfbc2,\n 0xfbd3, 0xfd3d,\n 0xfd50, 0xfd8f,\n 0xfd92, 0xfdc7,\n 0xfdf0, 0xfdfc,\n 0xfe70, 0xfefe,\n 0x10800, 0x1091e,\n 0x10920, 0x10a00,\n 0x10a04, 0x10a04,\n 0x10a07, 0x10a0b,\n 0x10a10, 0x10a37,\n 0x10a3b, 0x10a3e,\n 0x10a40, 0x10ae4,\n 0x10ae7, 0x10b38,\n 0x10b40, 0x10d23,\n 0x10d28, 0x10d2f,\n 0x10d3a, 0x10d3f,\n 0x10d4a, 0x10d68,\n 0x10d6f, 0x10e5f,\n 0x10e7f, 0x10eaa,\n 0x10ead, 0x10ecf,\n 0x10ed9, 0x10ef9,\n 0x10f00, 0x10f45,\n 0x10f51, 0x10f81,\n 0x10f86, 0x10fff,\n 0x1e800, 0x1e8cf,\n 0x1e8d7, 0x1e943,\n 0x1e94b, 0x1eeef,\n 0x1eef2, 0x1efff\n];\n\nexport const NON_STRONG_BIDI_RANGES: ReadonlyArray = [\n 0x0, 0x40,\n 0x5b, 0x60,\n 0x7b, 0xa9,\n 0xab, 0xb4,\n 0xb6, 0xb9,\n 0xbb, 0xbf,\n 0xd7, 0xd7,\n 0xf7, 0xf7,\n 0x2b9, 0x2ba,\n 0x2c2, 0x2cf,\n 0x2d2, 0x2df,\n 0x2e5, 0x2ed,\n 0x2ef, 0x36f,\n 0x374, 0x375,\n 0x37e, 0x37e,\n 0x384, 0x385,\n 0x387, 0x387,\n 0x3f6, 0x3f6,\n 0x483, 0x489,\n 0x58a, 0x58a,\n 0x58d, 0x58f,\n 0x591, 0x5bd,\n 0x5bf, 0x5bf,\n 0x5c1, 0x5c2,\n 0x5c4, 0x5c5,\n 0x5c7, 0x5c7,\n 0x600, 0x607,\n 0x609, 0x60a,\n 0x60c, 0x60c,\n 0x60e, 0x61a,\n 0x64b, 0x66c,\n 0x670, 0x670,\n 0x6d6, 0x6e4,\n 0x6e7, 0x6ed,\n 0x6f0, 0x6f9,\n 0x711, 0x711,\n 0x730, 0x74a,\n 0x7a6, 0x7b0,\n 0x7eb, 0x7f3,\n 0x7f6, 0x7f9,\n 0x7fd, 0x7fd,\n 0x816, 0x819,\n 0x81b, 0x823,\n 0x825, 0x827,\n 0x829, 0x82d,\n 0x859, 0x85b,\n 0x890, 0x891,\n 0x897, 0x89f,\n 0x8ca, 0x902,\n 0x93a, 0x93a,\n 0x93c, 0x93c,\n 0x941, 0x948,\n 0x94d, 0x94d,\n 0x951, 0x957,\n 0x962, 0x963,\n 0x981, 0x981,\n 0x9bc, 0x9bc,\n 0x9c1, 0x9c4,\n 0x9cd, 0x9cd,\n 0x9e2, 0x9e3,\n 0x9f2, 0x9f3,\n 0x9fb, 0x9fb,\n 0x9fe, 0x9fe,\n 0xa01, 0xa02,\n 0xa3c, 0xa3c,\n 0xa41, 0xa42,\n 0xa47, 0xa48,\n 0xa4b, 0xa4d,\n 0xa51, 0xa51,\n 0xa70, 0xa71,\n 0xa75, 0xa75,\n 0xa81, 0xa82,\n 0xabc, 0xabc,\n 0xac1, 0xac5,\n 0xac7, 0xac8,\n 0xacd, 0xacd,\n 0xae2, 0xae3,\n 0xaf1, 0xaf1,\n 0xafa, 0xaff,\n 0xb01, 0xb01,\n 0xb3c, 0xb3c,\n 0xb3f, 0xb3f,\n 0xb41, 0xb44,\n 0xb4d, 0xb4d,\n 0xb55, 0xb56,\n 0xb62, 0xb63,\n 0xb82, 0xb82,\n 0xbc0, 0xbc0,\n 0xbcd, 0xbcd,\n 0xbf3, 0xbfa,\n 0xc00, 0xc00,\n 0xc04, 0xc04,\n 0xc3c, 0xc3c,\n 0xc3e, 0xc40,\n 0xc46, 0xc48,\n 0xc4a, 0xc4d,\n 0xc55, 0xc56,\n 0xc62, 0xc63,\n 0xc78, 0xc7e,\n 0xc81, 0xc81,\n 0xcbc, 0xcbc,\n 0xccc, 0xccd,\n 0xce2, 0xce3,\n 0xd00, 0xd01,\n 0xd3b, 0xd3c,\n 0xd41, 0xd44,\n 0xd4d, 0xd4d,\n 0xd62, 0xd63,\n 0xd81, 0xd81,\n 0xdca, 0xdca,\n 0xdd2, 0xdd4,\n 0xdd6, 0xdd6,\n 0xe31, 0xe31,\n 0xe34, 0xe3a,\n 0xe3f, 0xe3f,\n 0xe47, 0xe4e,\n 0xeb1, 0xeb1,\n 0xeb4, 0xebc,\n 0xec8, 0xece,\n 0xf18, 0xf19,\n 0xf35, 0xf35,\n 0xf37, 0xf37,\n 0xf39, 0xf3d,\n 0xf71, 0xf7e,\n 0xf80, 0xf84,\n 0xf86, 0xf87,\n 0xf8d, 0xf97,\n 0xf99, 0xfbc,\n 0xfc6, 0xfc6,\n 0x102d, 0x1030,\n 0x1032, 0x1037,\n 0x1039, 0x103a,\n 0x103d, 0x103e,\n 0x1058, 0x1059,\n 0x105e, 0x1060,\n 0x1071, 0x1074,\n 0x1082, 0x1082,\n 0x1085, 0x1086,\n 0x108d, 0x108d,\n 0x109d, 0x109d,\n 0x135d, 0x135f,\n 0x1390, 0x1399,\n 0x1400, 0x1400,\n 0x1680, 0x1680,\n 0x169b, 0x169c,\n 0x1712, 0x1714,\n 0x1732, 0x1733,\n 0x1752, 0x1753,\n 0x1772, 0x1773,\n 0x17b4, 0x17b5,\n 0x17b7, 0x17bd,\n 0x17c6, 0x17c6,\n 0x17c9, 0x17d3,\n 0x17db, 0x17db,\n 0x17dd, 0x17dd,\n 0x17f0, 0x17f9,\n 0x1800, 0x180f,\n 0x1885, 0x1886,\n 0x18a9, 0x18a9,\n 0x1920, 0x1922,\n 0x1927, 0x1928,\n 0x1932, 0x1932,\n 0x1939, 0x193b,\n 0x1940, 0x1940,\n 0x1944, 0x1945,\n 0x19de, 0x19ff,\n 0x1a17, 0x1a18,\n 0x1a1b, 0x1a1b,\n 0x1a56, 0x1a56,\n 0x1a58, 0x1a5e,\n 0x1a60, 0x1a60,\n 0x1a62, 0x1a62,\n 0x1a65, 0x1a6c,\n 0x1a73, 0x1a7c,\n 0x1a7f, 0x1a7f,\n 0x1ab0, 0x1add,\n 0x1ae0, 0x1aeb,\n 0x1b00, 0x1b03,\n 0x1b34, 0x1b34,\n 0x1b36, 0x1b3a,\n 0x1b3c, 0x1b3c,\n 0x1b42, 0x1b42,\n 0x1b6b, 0x1b73,\n 0x1b80, 0x1b81,\n 0x1ba2, 0x1ba5,\n 0x1ba8, 0x1ba9,\n 0x1bab, 0x1bad,\n 0x1be6, 0x1be6,\n 0x1be8, 0x1be9,\n 0x1bed, 0x1bed,\n 0x1bef, 0x1bf1,\n 0x1c2c, 0x1c33,\n 0x1c36, 0x1c37,\n 0x1cd0, 0x1cd2,\n 0x1cd4, 0x1ce0,\n 0x1ce2, 0x1ce8,\n 0x1ced, 0x1ced,\n 0x1cf4, 0x1cf4,\n 0x1cf8, 0x1cf9,\n 0x1dc0, 0x1dff,\n 0x1fbd, 0x1fbd,\n 0x1fbf, 0x1fc1,\n 0x1fcd, 0x1fcf,\n 0x1fdd, 0x1fdf,\n 0x1fed, 0x1fef,\n 0x1ffd, 0x1ffe,\n 0x2000, 0x200d,\n 0x2010, 0x2070,\n 0x2074, 0x207e,\n 0x2080, 0x208e,\n 0x20a0, 0x20f0,\n 0x2100, 0x2101,\n 0x2103, 0x2106,\n 0x2108, 0x2109,\n 0x2114, 0x2114,\n 0x2116, 0x2118,\n 0x211e, 0x2123,\n 0x2125, 0x2125,\n 0x2127, 0x2127,\n 0x2129, 0x2129,\n 0x212e, 0x212e,\n 0x213a, 0x213b,\n 0x2140, 0x2144,\n 0x214a, 0x214d,\n 0x2150, 0x215f,\n 0x2189, 0x218b,\n 0x2190, 0x2335,\n 0x237b, 0x2394,\n 0x2396, 0x2429,\n 0x2440, 0x244a,\n 0x2460, 0x249b,\n 0x24ea, 0x26ab,\n 0x26ad, 0x27ff,\n 0x2900, 0x2b73,\n 0x2b76, 0x2bff,\n 0x2ce5, 0x2cea,\n 0x2cef, 0x2cf1,\n 0x2cf9, 0x2cff,\n 0x2d7f, 0x2d7f,\n 0x2de0, 0x2e5d,\n 0x2e80, 0x2e99,\n 0x2e9b, 0x2ef3,\n 0x2f00, 0x2fd5,\n 0x2ff0, 0x3004,\n 0x3008, 0x3020,\n 0x302a, 0x302d,\n 0x3030, 0x3030,\n 0x3036, 0x3037,\n 0x303d, 0x303f,\n 0x3099, 0x309c,\n 0x30a0, 0x30a0,\n 0x30fb, 0x30fb,\n 0x31c0, 0x31e5,\n 0x31ef, 0x31ef,\n 0x321d, 0x321e,\n 0x3250, 0x325f,\n 0x327c, 0x327e,\n 0x32b1, 0x32bf,\n 0x32cc, 0x32cf,\n 0x3377, 0x337a,\n 0x33de, 0x33df,\n 0x33ff, 0x33ff,\n 0x4dc0, 0x4dff,\n 0xa490, 0xa4c6,\n 0xa60d, 0xa60f,\n 0xa66f, 0xa67f,\n 0xa69e, 0xa69f,\n 0xa6f0, 0xa6f1,\n 0xa700, 0xa721,\n 0xa788, 0xa788,\n 0xa802, 0xa802,\n 0xa806, 0xa806,\n 0xa80b, 0xa80b,\n 0xa825, 0xa826,\n 0xa828, 0xa82c,\n 0xa838, 0xa839,\n 0xa874, 0xa877,\n 0xa8c4, 0xa8c5,\n 0xa8e0, 0xa8f1,\n 0xa8ff, 0xa8ff,\n 0xa926, 0xa92d,\n 0xa947, 0xa951,\n 0xa980, 0xa982,\n 0xa9b3, 0xa9b3,\n 0xa9b6, 0xa9b9,\n 0xa9bc, 0xa9bd,\n 0xa9e5, 0xa9e5,\n 0xaa29, 0xaa2e,\n 0xaa31, 0xaa32,\n 0xaa35, 0xaa36,\n 0xaa43, 0xaa43,\n 0xaa4c, 0xaa4c,\n 0xaa7c, 0xaa7c,\n 0xaab0, 0xaab0,\n 0xaab2, 0xaab4,\n 0xaab7, 0xaab8,\n 0xaabe, 0xaabf,\n 0xaac1, 0xaac1,\n 0xaaec, 0xaaed,\n 0xaaf6, 0xaaf6,\n 0xab6a, 0xab6b,\n 0xabe5, 0xabe5,\n 0xabe8, 0xabe8,\n 0xabed, 0xabed,\n 0xfb1e, 0xfb1e,\n 0xfb29, 0xfb29,\n 0xfbc3, 0xfbd2,\n 0xfd3e, 0xfd4f,\n 0xfd90, 0xfd91,\n 0xfdc8, 0xfdef,\n 0xfdfd, 0xfe19,\n 0xfe20, 0xfe52,\n 0xfe54, 0xfe66,\n 0xfe68, 0xfe6b,\n 0xfeff, 0xfeff,\n 0xff01, 0xff20,\n 0xff3b, 0xff40,\n 0xff5b, 0xff65,\n 0xffe0, 0xffe6,\n 0xffe8, 0xffee,\n 0xfff0, 0xffff,\n 0x10101, 0x10101,\n 0x10140, 0x1018c,\n 0x10190, 0x1019c,\n 0x101a0, 0x101a0,\n 0x101fd, 0x101fd,\n 0x102e0, 0x102fb,\n 0x10376, 0x1037a,\n 0x1091f, 0x1091f,\n 0x10a01, 0x10a03,\n 0x10a05, 0x10a06,\n 0x10a0c, 0x10a0f,\n 0x10a38, 0x10a3a,\n 0x10a3f, 0x10a3f,\n 0x10ae5, 0x10ae6,\n 0x10b39, 0x10b3f,\n 0x10d24, 0x10d27,\n 0x10d30, 0x10d39,\n 0x10d40, 0x10d49,\n 0x10d69, 0x10d6e,\n 0x10e60, 0x10e7e,\n 0x10eab, 0x10eac,\n 0x10ed0, 0x10ed8,\n 0x10efa, 0x10eff,\n 0x10f46, 0x10f50,\n 0x10f82, 0x10f85,\n 0x11001, 0x11001,\n 0x11038, 0x11046,\n 0x11052, 0x11065,\n 0x11070, 0x11070,\n 0x11073, 0x11074,\n 0x1107f, 0x11081,\n 0x110b3, 0x110b6,\n 0x110b9, 0x110ba,\n 0x110c2, 0x110c2,\n 0x11100, 0x11102,\n 0x11127, 0x1112b,\n 0x1112d, 0x11134,\n 0x11173, 0x11173,\n 0x11180, 0x11181,\n 0x111b6, 0x111be,\n 0x111c9, 0x111cc,\n 0x111cf, 0x111cf,\n 0x1122f, 0x11231,\n 0x11234, 0x11234,\n 0x11236, 0x11237,\n 0x1123e, 0x1123e,\n 0x11241, 0x11241,\n 0x112df, 0x112df,\n 0x112e3, 0x112ea,\n 0x11300, 0x11301,\n 0x1133b, 0x1133c,\n 0x11340, 0x11340,\n 0x11366, 0x1136c,\n 0x11370, 0x11374,\n 0x113bb, 0x113c0,\n 0x113ce, 0x113ce,\n 0x113d0, 0x113d0,\n 0x113d2, 0x113d2,\n 0x113e1, 0x113e2,\n 0x11438, 0x1143f,\n 0x11442, 0x11444,\n 0x11446, 0x11446,\n 0x1145e, 0x1145e,\n 0x114b3, 0x114b8,\n 0x114ba, 0x114ba,\n 0x114bf, 0x114c0,\n 0x114c2, 0x114c3,\n 0x115b2, 0x115b5,\n 0x115bc, 0x115bd,\n 0x115bf, 0x115c0,\n 0x115dc, 0x115dd,\n 0x11633, 0x1163a,\n 0x1163d, 0x1163d,\n 0x1163f, 0x11640,\n 0x11660, 0x1166c,\n 0x116ab, 0x116ab,\n 0x116ad, 0x116ad,\n 0x116b0, 0x116b5,\n 0x116b7, 0x116b7,\n 0x1171d, 0x1171d,\n 0x1171f, 0x1171f,\n 0x11722, 0x11725,\n 0x11727, 0x1172b,\n 0x1182f, 0x11837,\n 0x11839, 0x1183a,\n 0x1193b, 0x1193c,\n 0x1193e, 0x1193e,\n 0x11943, 0x11943,\n 0x119d4, 0x119d7,\n 0x119da, 0x119db,\n 0x119e0, 0x119e0,\n 0x11a01, 0x11a06,\n 0x11a09, 0x11a0a,\n 0x11a33, 0x11a38,\n 0x11a3b, 0x11a3e,\n 0x11a47, 0x11a47,\n 0x11a51, 0x11a56,\n 0x11a59, 0x11a5b,\n 0x11a8a, 0x11a96,\n 0x11a98, 0x11a99,\n 0x11b60, 0x11b60,\n 0x11b62, 0x11b64,\n 0x11b66, 0x11b66,\n 0x11c30, 0x11c36,\n 0x11c38, 0x11c3d,\n 0x11c92, 0x11ca7,\n 0x11caa, 0x11cb0,\n 0x11cb2, 0x11cb3,\n 0x11cb5, 0x11cb6,\n 0x11d31, 0x11d36,\n 0x11d3a, 0x11d3a,\n 0x11d3c, 0x11d3d,\n 0x11d3f, 0x11d45,\n 0x11d47, 0x11d47,\n 0x11d90, 0x11d91,\n 0x11d95, 0x11d95,\n 0x11d97, 0x11d97,\n 0x11ef3, 0x11ef4,\n 0x11f00, 0x11f01,\n 0x11f36, 0x11f3a,\n 0x11f40, 0x11f40,\n 0x11f42, 0x11f42,\n 0x11f5a, 0x11f5a,\n 0x11fd5, 0x11ff1,\n 0x13440, 0x13440,\n 0x13447, 0x13455,\n 0x1611e, 0x16129,\n 0x1612d, 0x1612f,\n 0x16af0, 0x16af4,\n 0x16b30, 0x16b36,\n 0x16f4f, 0x16f4f,\n 0x16f8f, 0x16f92,\n 0x16fe2, 0x16fe2,\n 0x16fe4, 0x16fe4,\n 0x1bc9d, 0x1bc9e,\n 0x1bca0, 0x1bca3,\n 0x1cc00, 0x1ccd5,\n 0x1ccf0, 0x1ccfc,\n 0x1cd00, 0x1ceb3,\n 0x1ceba, 0x1ced0,\n 0x1cee0, 0x1cef0,\n 0x1cf00, 0x1cf2d,\n 0x1cf30, 0x1cf46,\n 0x1d167, 0x1d169,\n 0x1d173, 0x1d182,\n 0x1d185, 0x1d18b,\n 0x1d1aa, 0x1d1ad,\n 0x1d1e9, 0x1d1ea,\n 0x1d200, 0x1d245,\n 0x1d300, 0x1d356,\n 0x1d6c1, 0x1d6c1,\n 0x1d6db, 0x1d6db,\n 0x1d6fb, 0x1d6fb,\n 0x1d715, 0x1d715,\n 0x1d735, 0x1d735,\n 0x1d74f, 0x1d74f,\n 0x1d76f, 0x1d76f,\n 0x1d789, 0x1d789,\n 0x1d7a9, 0x1d7a9,\n 0x1d7c3, 0x1d7c3,\n 0x1d7ce, 0x1d7ff,\n 0x1da00, 0x1da36,\n 0x1da3b, 0x1da6c,\n 0x1da75, 0x1da75,\n 0x1da84, 0x1da84,\n 0x1da9b, 0x1da9f,\n 0x1daa1, 0x1daaf,\n 0x1e000, 0x1e006,\n 0x1e008, 0x1e018,\n 0x1e01b, 0x1e021,\n 0x1e023, 0x1e024,\n 0x1e026, 0x1e02a,\n 0x1e08f, 0x1e08f,\n 0x1e130, 0x1e136,\n 0x1e2ae, 0x1e2ae,\n 0x1e2ec, 0x1e2ef,\n 0x1e2ff, 0x1e2ff,\n 0x1e4ec, 0x1e4ef,\n 0x1e5ee, 0x1e5ef,\n 0x1e6e3, 0x1e6e3,\n 0x1e6e6, 0x1e6e6,\n 0x1e6ee, 0x1e6ef,\n 0x1e6f5, 0x1e6f5,\n 0x1e8d0, 0x1e8d6,\n 0x1e944, 0x1e94a,\n 0x1eef0, 0x1eef1,\n 0x1f000, 0x1f02b,\n 0x1f030, 0x1f093,\n 0x1f0a0, 0x1f0ae,\n 0x1f0b1, 0x1f0bf,\n 0x1f0c1, 0x1f0cf,\n 0x1f0d1, 0x1f0f5,\n 0x1f100, 0x1f10f,\n 0x1f12f, 0x1f12f,\n 0x1f16a, 0x1f16f,\n 0x1f1ad, 0x1f1ad,\n 0x1f260, 0x1f265,\n 0x1f300, 0x1f6d8,\n 0x1f6dc, 0x1f6ec,\n 0x1f6f0, 0x1f6fc,\n 0x1f700, 0x1f7d9,\n 0x1f7e0, 0x1f7eb,\n 0x1f7f0, 0x1f7f0,\n 0x1f800, 0x1f80b,\n 0x1f810, 0x1f847,\n 0x1f850, 0x1f859,\n 0x1f860, 0x1f887,\n 0x1f890, 0x1f8ad,\n 0x1f8b0, 0x1f8bb,\n 0x1f8c0, 0x1f8c1,\n 0x1f8d0, 0x1f8d8,\n 0x1f900, 0x1fa57,\n 0x1fa60, 0x1fa6d,\n 0x1fa70, 0x1fa7c,\n 0x1fa80, 0x1fa8a,\n 0x1fa8e, 0x1fac6,\n 0x1fac8, 0x1fac8,\n 0x1facd, 0x1fadc,\n 0x1fadf, 0x1faea,\n 0x1faef, 0x1faf8,\n 0x1fb00, 0x1fb92,\n 0x1fb94, 0x1fbfa,\n 0x1fffe, 0x1ffff,\n 0x2fffe, 0x2ffff,\n 0x3fffe, 0x3ffff,\n 0x4fffe, 0x4ffff,\n 0x5fffe, 0x5ffff,\n 0x6fffe, 0x6ffff,\n 0x7fffe, 0x7ffff,\n 0x8fffe, 0x8ffff,\n 0x9fffe, 0x9ffff,\n 0xafffe, 0xaffff,\n 0xbfffe, 0xbffff,\n 0xcfffe, 0xcffff,\n 0xdfffe, 0xe0fff,\n 0xefffe, 0xeffff,\n 0xffffe, 0xfffff,\n 0x10fffe, 0x10ffff\n];\n\nexport const NATURAL_LETTER_RANGES: ReadonlyArray = [\n 0x41, 0x5a,\n 0x61, 0x7a,\n 0xaa, 0xaa,\n 0xb5, 0xb5,\n 0xba, 0xba,\n 0xc0, 0xd6,\n 0xd8, 0xf6,\n 0xf8, 0x2c1,\n 0x2c6, 0x2d1,\n 0x2e0, 0x2e4,\n 0x2ec, 0x2ec,\n 0x2ee, 0x2ee,\n 0x370, 0x374,\n 0x376, 0x377,\n 0x37a, 0x37d,\n 0x37f, 0x37f,\n 0x386, 0x386,\n 0x388, 0x38a,\n 0x38c, 0x38c,\n 0x38e, 0x3a1,\n 0x3a3, 0x3f5,\n 0x3f7, 0x481,\n 0x48a, 0x52f,\n 0x531, 0x556,\n 0x559, 0x559,\n 0x560, 0x588,\n 0x5d0, 0x5ea,\n 0x5ef, 0x5f2,\n 0x620, 0x64a,\n 0x66e, 0x66f,\n 0x671, 0x6d3,\n 0x6d5, 0x6d5,\n 0x6e5, 0x6e6,\n 0x6ee, 0x6ef,\n 0x6fa, 0x6fc,\n 0x6ff, 0x6ff,\n 0x710, 0x710,\n 0x712, 0x72f,\n 0x74d, 0x7a5,\n 0x7b1, 0x7b1,\n 0x7ca, 0x7ea,\n 0x7f4, 0x7f5,\n 0x7fa, 0x7fa,\n 0x800, 0x815,\n 0x81a, 0x81a,\n 0x824, 0x824,\n 0x828, 0x828,\n 0x840, 0x858,\n 0x860, 0x86a,\n 0x870, 0x887,\n 0x889, 0x88f,\n 0x8a0, 0x8c9,\n 0x904, 0x939,\n 0x93d, 0x93d,\n 0x950, 0x950,\n 0x958, 0x961,\n 0x971, 0x980,\n 0x985, 0x98c,\n 0x98f, 0x990,\n 0x993, 0x9a8,\n 0x9aa, 0x9b0,\n 0x9b2, 0x9b2,\n 0x9b6, 0x9b9,\n 0x9bd, 0x9bd,\n 0x9ce, 0x9ce,\n 0x9dc, 0x9dd,\n 0x9df, 0x9e1,\n 0x9f0, 0x9f1,\n 0x9fc, 0x9fc,\n 0xa05, 0xa0a,\n 0xa0f, 0xa10,\n 0xa13, 0xa28,\n 0xa2a, 0xa30,\n 0xa32, 0xa33,\n 0xa35, 0xa36,\n 0xa38, 0xa39,\n 0xa59, 0xa5c,\n 0xa5e, 0xa5e,\n 0xa72, 0xa74,\n 0xa85, 0xa8d,\n 0xa8f, 0xa91,\n 0xa93, 0xaa8,\n 0xaaa, 0xab0,\n 0xab2, 0xab3,\n 0xab5, 0xab9,\n 0xabd, 0xabd,\n 0xad0, 0xad0,\n 0xae0, 0xae1,\n 0xaf9, 0xaf9,\n 0xb05, 0xb0c,\n 0xb0f, 0xb10,\n 0xb13, 0xb28,\n 0xb2a, 0xb30,\n 0xb32, 0xb33,\n 0xb35, 0xb39,\n 0xb3d, 0xb3d,\n 0xb5c, 0xb5d,\n 0xb5f, 0xb61,\n 0xb71, 0xb71,\n 0xb83, 0xb83,\n 0xb85, 0xb8a,\n 0xb8e, 0xb90,\n 0xb92, 0xb95,\n 0xb99, 0xb9a,\n 0xb9c, 0xb9c,\n 0xb9e, 0xb9f,\n 0xba3, 0xba4,\n 0xba8, 0xbaa,\n 0xbae, 0xbb9,\n 0xbd0, 0xbd0,\n 0xc05, 0xc0c,\n 0xc0e, 0xc10,\n 0xc12, 0xc28,\n 0xc2a, 0xc39,\n 0xc3d, 0xc3d,\n 0xc58, 0xc5a,\n 0xc5c, 0xc5d,\n 0xc60, 0xc61,\n 0xc80, 0xc80,\n 0xc85, 0xc8c,\n 0xc8e, 0xc90,\n 0xc92, 0xca8,\n 0xcaa, 0xcb3,\n 0xcb5, 0xcb9,\n 0xcbd, 0xcbd,\n 0xcdc, 0xcde,\n 0xce0, 0xce1,\n 0xcf1, 0xcf2,\n 0xd04, 0xd0c,\n 0xd0e, 0xd10,\n 0xd12, 0xd3a,\n 0xd3d, 0xd3d,\n 0xd4e, 0xd4e,\n 0xd54, 0xd56,\n 0xd5f, 0xd61,\n 0xd7a, 0xd7f,\n 0xd85, 0xd96,\n 0xd9a, 0xdb1,\n 0xdb3, 0xdbb,\n 0xdbd, 0xdbd,\n 0xdc0, 0xdc6,\n 0xe01, 0xe30,\n 0xe32, 0xe33,\n 0xe40, 0xe46,\n 0xe81, 0xe82,\n 0xe84, 0xe84,\n 0xe86, 0xe8a,\n 0xe8c, 0xea3,\n 0xea5, 0xea5,\n 0xea7, 0xeb0,\n 0xeb2, 0xeb3,\n 0xebd, 0xebd,\n 0xec0, 0xec4,\n 0xec6, 0xec6,\n 0xedc, 0xedf,\n 0xf00, 0xf00,\n 0xf40, 0xf47,\n 0xf49, 0xf6c,\n 0xf88, 0xf8c,\n 0x1000, 0x102a,\n 0x103f, 0x103f,\n 0x1050, 0x1055,\n 0x105a, 0x105d,\n 0x1061, 0x1061,\n 0x1065, 0x1066,\n 0x106e, 0x1070,\n 0x1075, 0x1081,\n 0x108e, 0x108e,\n 0x10a0, 0x10c5,\n 0x10c7, 0x10c7,\n 0x10cd, 0x10cd,\n 0x10d0, 0x10fa,\n 0x10fc, 0x1248,\n 0x124a, 0x124d,\n 0x1250, 0x1256,\n 0x1258, 0x1258,\n 0x125a, 0x125d,\n 0x1260, 0x1288,\n 0x128a, 0x128d,\n 0x1290, 0x12b0,\n 0x12b2, 0x12b5,\n 0x12b8, 0x12be,\n 0x12c0, 0x12c0,\n 0x12c2, 0x12c5,\n 0x12c8, 0x12d6,\n 0x12d8, 0x1310,\n 0x1312, 0x1315,\n 0x1318, 0x135a,\n 0x1380, 0x138f,\n 0x13a0, 0x13f5,\n 0x13f8, 0x13fd,\n 0x1401, 0x166c,\n 0x166f, 0x167f,\n 0x1681, 0x169a,\n 0x16a0, 0x16ea,\n 0x16f1, 0x16f8,\n 0x1700, 0x1711,\n 0x171f, 0x1731,\n 0x1740, 0x1751,\n 0x1760, 0x176c,\n 0x176e, 0x1770,\n 0x1780, 0x17b3,\n 0x17d7, 0x17d7,\n 0x17dc, 0x17dc,\n 0x1820, 0x1878,\n 0x1880, 0x1884,\n 0x1887, 0x18a8,\n 0x18aa, 0x18aa,\n 0x18b0, 0x18f5,\n 0x1900, 0x191e,\n 0x1950, 0x196d,\n 0x1970, 0x1974,\n 0x1980, 0x19ab,\n 0x19b0, 0x19c9,\n 0x1a00, 0x1a16,\n 0x1a20, 0x1a54,\n 0x1aa7, 0x1aa7,\n 0x1b05, 0x1b33,\n 0x1b45, 0x1b4c,\n 0x1b83, 0x1ba0,\n 0x1bae, 0x1baf,\n 0x1bba, 0x1be5,\n 0x1c00, 0x1c23,\n 0x1c4d, 0x1c4f,\n 0x1c5a, 0x1c7d,\n 0x1c80, 0x1c8a,\n 0x1c90, 0x1cba,\n 0x1cbd, 0x1cbf,\n 0x1ce9, 0x1cec,\n 0x1cee, 0x1cf3,\n 0x1cf5, 0x1cf6,\n 0x1cfa, 0x1cfa,\n 0x1d00, 0x1dbf,\n 0x1e00, 0x1f15,\n 0x1f18, 0x1f1d,\n 0x1f20, 0x1f45,\n 0x1f48, 0x1f4d,\n 0x1f50, 0x1f57,\n 0x1f59, 0x1f59,\n 0x1f5b, 0x1f5b,\n 0x1f5d, 0x1f5d,\n 0x1f5f, 0x1f7d,\n 0x1f80, 0x1fb4,\n 0x1fb6, 0x1fbc,\n 0x1fbe, 0x1fbe,\n 0x1fc2, 0x1fc4,\n 0x1fc6, 0x1fcc,\n 0x1fd0, 0x1fd3,\n 0x1fd6, 0x1fdb,\n 0x1fe0, 0x1fec,\n 0x1ff2, 0x1ff4,\n 0x1ff6, 0x1ffc,\n 0x2071, 0x2071,\n 0x207f, 0x207f,\n 0x2090, 0x209c,\n 0x2102, 0x2102,\n 0x2107, 0x2107,\n 0x210a, 0x2113,\n 0x2115, 0x2115,\n 0x2119, 0x211d,\n 0x2124, 0x2124,\n 0x2126, 0x2126,\n 0x2128, 0x2128,\n 0x212a, 0x212d,\n 0x212f, 0x2139,\n 0x213c, 0x213f,\n 0x2145, 0x2149,\n 0x214e, 0x214e,\n 0x2183, 0x2184,\n 0x2c00, 0x2ce4,\n 0x2ceb, 0x2cee,\n 0x2cf2, 0x2cf3,\n 0x2d00, 0x2d25,\n 0x2d27, 0x2d27,\n 0x2d2d, 0x2d2d,\n 0x2d30, 0x2d67,\n 0x2d6f, 0x2d6f,\n 0x2d80, 0x2d96,\n 0x2da0, 0x2da6,\n 0x2da8, 0x2dae,\n 0x2db0, 0x2db6,\n 0x2db8, 0x2dbe,\n 0x2dc0, 0x2dc6,\n 0x2dc8, 0x2dce,\n 0x2dd0, 0x2dd6,\n 0x2dd8, 0x2dde,\n 0x2e2f, 0x2e2f,\n 0x3005, 0x3006,\n 0x3031, 0x3035,\n 0x303b, 0x303c,\n 0x3041, 0x3096,\n 0x309d, 0x309f,\n 0x30a1, 0x30fa,\n 0x30fc, 0x30ff,\n 0x3105, 0x312f,\n 0x3131, 0x318e,\n 0x31a0, 0x31bf,\n 0x31f0, 0x31ff,\n 0x3400, 0x4dbf,\n 0x4e00, 0xa48c,\n 0xa4d0, 0xa4fd,\n 0xa500, 0xa60c,\n 0xa610, 0xa61f,\n 0xa62a, 0xa62b,\n 0xa640, 0xa66e,\n 0xa67f, 0xa69d,\n 0xa6a0, 0xa6e5,\n 0xa717, 0xa71f,\n 0xa722, 0xa788,\n 0xa78b, 0xa7dc,\n 0xa7f1, 0xa801,\n 0xa803, 0xa805,\n 0xa807, 0xa80a,\n 0xa80c, 0xa822,\n 0xa840, 0xa873,\n 0xa882, 0xa8b3,\n 0xa8f2, 0xa8f7,\n 0xa8fb, 0xa8fb,\n 0xa8fd, 0xa8fe,\n 0xa90a, 0xa925,\n 0xa930, 0xa946,\n 0xa960, 0xa97c,\n 0xa984, 0xa9b2,\n 0xa9cf, 0xa9cf,\n 0xa9e0, 0xa9e4,\n 0xa9e6, 0xa9ef,\n 0xa9fa, 0xa9fe,\n 0xaa00, 0xaa28,\n 0xaa40, 0xaa42,\n 0xaa44, 0xaa4b,\n 0xaa60, 0xaa76,\n 0xaa7a, 0xaa7a,\n 0xaa7e, 0xaaaf,\n 0xaab1, 0xaab1,\n 0xaab5, 0xaab6,\n 0xaab9, 0xaabd,\n 0xaac0, 0xaac0,\n 0xaac2, 0xaac2,\n 0xaadb, 0xaadd,\n 0xaae0, 0xaaea,\n 0xaaf2, 0xaaf4,\n 0xab01, 0xab06,\n 0xab09, 0xab0e,\n 0xab11, 0xab16,\n 0xab20, 0xab26,\n 0xab28, 0xab2e,\n 0xab30, 0xab5a,\n 0xab5c, 0xab69,\n 0xab70, 0xabe2,\n 0xac00, 0xd7a3,\n 0xd7b0, 0xd7c6,\n 0xd7cb, 0xd7fb,\n 0xf900, 0xfa6d,\n 0xfa70, 0xfad9,\n 0xfb00, 0xfb06,\n 0xfb13, 0xfb17,\n 0xfb1d, 0xfb1d,\n 0xfb1f, 0xfb28,\n 0xfb2a, 0xfb36,\n 0xfb38, 0xfb3c,\n 0xfb3e, 0xfb3e,\n 0xfb40, 0xfb41,\n 0xfb43, 0xfb44,\n 0xfb46, 0xfbb1,\n 0xfbd3, 0xfd3d,\n 0xfd50, 0xfd8f,\n 0xfd92, 0xfdc7,\n 0xfdf0, 0xfdfb,\n 0xfe70, 0xfe74,\n 0xfe76, 0xfefc,\n 0xff21, 0xff3a,\n 0xff41, 0xff5a,\n 0xff66, 0xffbe,\n 0xffc2, 0xffc7,\n 0xffca, 0xffcf,\n 0xffd2, 0xffd7,\n 0xffda, 0xffdc,\n 0x10000, 0x1000b,\n 0x1000d, 0x10026,\n 0x10028, 0x1003a,\n 0x1003c, 0x1003d,\n 0x1003f, 0x1004d,\n 0x10050, 0x1005d,\n 0x10080, 0x100fa,\n 0x10280, 0x1029c,\n 0x102a0, 0x102d0,\n 0x10300, 0x1031f,\n 0x1032d, 0x10340,\n 0x10342, 0x10349,\n 0x10350, 0x10375,\n 0x10380, 0x1039d,\n 0x103a0, 0x103c3,\n 0x103c8, 0x103cf,\n 0x10400, 0x1049d,\n 0x104b0, 0x104d3,\n 0x104d8, 0x104fb,\n 0x10500, 0x10527,\n 0x10530, 0x10563,\n 0x10570, 0x1057a,\n 0x1057c, 0x1058a,\n 0x1058c, 0x10592,\n 0x10594, 0x10595,\n 0x10597, 0x105a1,\n 0x105a3, 0x105b1,\n 0x105b3, 0x105b9,\n 0x105bb, 0x105bc,\n 0x105c0, 0x105f3,\n 0x10600, 0x10736,\n 0x10740, 0x10755,\n 0x10760, 0x10767,\n 0x10780, 0x10785,\n 0x10787, 0x107b0,\n 0x107b2, 0x107ba,\n 0x10800, 0x10805,\n 0x10808, 0x10808,\n 0x1080a, 0x10835,\n 0x10837, 0x10838,\n 0x1083c, 0x1083c,\n 0x1083f, 0x10855,\n 0x10860, 0x10876,\n 0x10880, 0x1089e,\n 0x108e0, 0x108f2,\n 0x108f4, 0x108f5,\n 0x10900, 0x10915,\n 0x10920, 0x10939,\n 0x10940, 0x10959,\n 0x10980, 0x109b7,\n 0x109be, 0x109bf,\n 0x10a00, 0x10a00,\n 0x10a10, 0x10a13,\n 0x10a15, 0x10a17,\n 0x10a19, 0x10a35,\n 0x10a60, 0x10a7c,\n 0x10a80, 0x10a9c,\n 0x10ac0, 0x10ac7,\n 0x10ac9, 0x10ae4,\n 0x10b00, 0x10b35,\n 0x10b40, 0x10b55,\n 0x10b60, 0x10b72,\n 0x10b80, 0x10b91,\n 0x10c00, 0x10c48,\n 0x10c80, 0x10cb2,\n 0x10cc0, 0x10cf2,\n 0x10d00, 0x10d23,\n 0x10d4a, 0x10d65,\n 0x10d6f, 0x10d85,\n 0x10e80, 0x10ea9,\n 0x10eb0, 0x10eb1,\n 0x10ec2, 0x10ec7,\n 0x10f00, 0x10f1c,\n 0x10f27, 0x10f27,\n 0x10f30, 0x10f45,\n 0x10f70, 0x10f81,\n 0x10fb0, 0x10fc4,\n 0x10fe0, 0x10ff6,\n 0x11003, 0x11037,\n 0x11071, 0x11072,\n 0x11075, 0x11075,\n 0x11083, 0x110af,\n 0x110d0, 0x110e8,\n 0x11103, 0x11126,\n 0x11144, 0x11144,\n 0x11147, 0x11147,\n 0x11150, 0x11172,\n 0x11176, 0x11176,\n 0x11183, 0x111b2,\n 0x111c1, 0x111c4,\n 0x111da, 0x111da,\n 0x111dc, 0x111dc,\n 0x11200, 0x11211,\n 0x11213, 0x1122b,\n 0x1123f, 0x11240,\n 0x11280, 0x11286,\n 0x11288, 0x11288,\n 0x1128a, 0x1128d,\n 0x1128f, 0x1129d,\n 0x1129f, 0x112a8,\n 0x112b0, 0x112de,\n 0x11305, 0x1130c,\n 0x1130f, 0x11310,\n 0x11313, 0x11328,\n 0x1132a, 0x11330,\n 0x11332, 0x11333,\n 0x11335, 0x11339,\n 0x1133d, 0x1133d,\n 0x11350, 0x11350,\n 0x1135d, 0x11361,\n 0x11380, 0x11389,\n 0x1138b, 0x1138b,\n 0x1138e, 0x1138e,\n 0x11390, 0x113b5,\n 0x113b7, 0x113b7,\n 0x113d1, 0x113d1,\n 0x113d3, 0x113d3,\n 0x11400, 0x11434,\n 0x11447, 0x1144a,\n 0x1145f, 0x11461,\n 0x11480, 0x114af,\n 0x114c4, 0x114c5,\n 0x114c7, 0x114c7,\n 0x11580, 0x115ae,\n 0x115d8, 0x115db,\n 0x11600, 0x1162f,\n 0x11644, 0x11644,\n 0x11680, 0x116aa,\n 0x116b8, 0x116b8,\n 0x11700, 0x1171a,\n 0x11740, 0x11746,\n 0x11800, 0x1182b,\n 0x118a0, 0x118df,\n 0x118ff, 0x11906,\n 0x11909, 0x11909,\n 0x1190c, 0x11913,\n 0x11915, 0x11916,\n 0x11918, 0x1192f,\n 0x1193f, 0x1193f,\n 0x11941, 0x11941,\n 0x119a0, 0x119a7,\n 0x119aa, 0x119d0,\n 0x119e1, 0x119e1,\n 0x119e3, 0x119e3,\n 0x11a00, 0x11a00,\n 0x11a0b, 0x11a32,\n 0x11a3a, 0x11a3a,\n 0x11a50, 0x11a50,\n 0x11a5c, 0x11a89,\n 0x11a9d, 0x11a9d,\n 0x11ab0, 0x11af8,\n 0x11bc0, 0x11be0,\n 0x11c00, 0x11c08,\n 0x11c0a, 0x11c2e,\n 0x11c40, 0x11c40,\n 0x11c72, 0x11c8f,\n 0x11d00, 0x11d06,\n 0x11d08, 0x11d09,\n 0x11d0b, 0x11d30,\n 0x11d46, 0x11d46,\n 0x11d60, 0x11d65,\n 0x11d67, 0x11d68,\n 0x11d6a, 0x11d89,\n 0x11d98, 0x11d98,\n 0x11db0, 0x11ddb,\n 0x11ee0, 0x11ef2,\n 0x11f02, 0x11f02,\n 0x11f04, 0x11f10,\n 0x11f12, 0x11f33,\n 0x11fb0, 0x11fb0,\n 0x12000, 0x12399,\n 0x12480, 0x12543,\n 0x12f90, 0x12ff0,\n 0x13000, 0x1342f,\n 0x13441, 0x13446,\n 0x13460, 0x143fa,\n 0x14400, 0x14646,\n 0x16100, 0x1611d,\n 0x16800, 0x16a38,\n 0x16a40, 0x16a5e,\n 0x16a70, 0x16abe,\n 0x16ad0, 0x16aed,\n 0x16b00, 0x16b2f,\n 0x16b40, 0x16b43,\n 0x16b63, 0x16b77,\n 0x16b7d, 0x16b8f,\n 0x16d40, 0x16d6c,\n 0x16e40, 0x16e7f,\n 0x16ea0, 0x16eb8,\n 0x16ebb, 0x16ed3,\n 0x16f00, 0x16f4a,\n 0x16f50, 0x16f50,\n 0x16f93, 0x16f9f,\n 0x16fe0, 0x16fe1,\n 0x16fe3, 0x16fe3,\n 0x16ff2, 0x16ff3,\n 0x17000, 0x18cd5,\n 0x18cff, 0x18d1e,\n 0x18d80, 0x18df2,\n 0x1aff0, 0x1aff3,\n 0x1aff5, 0x1affb,\n 0x1affd, 0x1affe,\n 0x1b000, 0x1b122,\n 0x1b132, 0x1b132,\n 0x1b150, 0x1b152,\n 0x1b155, 0x1b155,\n 0x1b164, 0x1b167,\n 0x1b170, 0x1b2fb,\n 0x1bc00, 0x1bc6a,\n 0x1bc70, 0x1bc7c,\n 0x1bc80, 0x1bc88,\n 0x1bc90, 0x1bc99,\n 0x1d400, 0x1d454,\n 0x1d456, 0x1d49c,\n 0x1d49e, 0x1d49f,\n 0x1d4a2, 0x1d4a2,\n 0x1d4a5, 0x1d4a6,\n 0x1d4a9, 0x1d4ac,\n 0x1d4ae, 0x1d4b9,\n 0x1d4bb, 0x1d4bb,\n 0x1d4bd, 0x1d4c3,\n 0x1d4c5, 0x1d505,\n 0x1d507, 0x1d50a,\n 0x1d50d, 0x1d514,\n 0x1d516, 0x1d51c,\n 0x1d51e, 0x1d539,\n 0x1d53b, 0x1d53e,\n 0x1d540, 0x1d544,\n 0x1d546, 0x1d546,\n 0x1d54a, 0x1d550,\n 0x1d552, 0x1d6a5,\n 0x1d6a8, 0x1d6c0,\n 0x1d6c2, 0x1d6da,\n 0x1d6dc, 0x1d6fa,\n 0x1d6fc, 0x1d714,\n 0x1d716, 0x1d734,\n 0x1d736, 0x1d74e,\n 0x1d750, 0x1d76e,\n 0x1d770, 0x1d788,\n 0x1d78a, 0x1d7a8,\n 0x1d7aa, 0x1d7c2,\n 0x1d7c4, 0x1d7cb,\n 0x1df00, 0x1df1e,\n 0x1df25, 0x1df2a,\n 0x1e030, 0x1e06d,\n 0x1e100, 0x1e12c,\n 0x1e137, 0x1e13d,\n 0x1e14e, 0x1e14e,\n 0x1e290, 0x1e2ad,\n 0x1e2c0, 0x1e2eb,\n 0x1e4d0, 0x1e4eb,\n 0x1e5d0, 0x1e5ed,\n 0x1e5f0, 0x1e5f0,\n 0x1e6c0, 0x1e6de,\n 0x1e6e0, 0x1e6e2,\n 0x1e6e4, 0x1e6e5,\n 0x1e6e7, 0x1e6ed,\n 0x1e6f0, 0x1e6f4,\n 0x1e6fe, 0x1e6ff,\n 0x1e7e0, 0x1e7e6,\n 0x1e7e8, 0x1e7eb,\n 0x1e7ed, 0x1e7ee,\n 0x1e7f0, 0x1e7fe,\n 0x1e800, 0x1e8c4,\n 0x1e900, 0x1e943,\n 0x1e94b, 0x1e94b,\n 0x1ee00, 0x1ee03,\n 0x1ee05, 0x1ee1f,\n 0x1ee21, 0x1ee22,\n 0x1ee24, 0x1ee24,\n 0x1ee27, 0x1ee27,\n 0x1ee29, 0x1ee32,\n 0x1ee34, 0x1ee37,\n 0x1ee39, 0x1ee39,\n 0x1ee3b, 0x1ee3b,\n 0x1ee42, 0x1ee42,\n 0x1ee47, 0x1ee47,\n 0x1ee49, 0x1ee49,\n 0x1ee4b, 0x1ee4b,\n 0x1ee4d, 0x1ee4f,\n 0x1ee51, 0x1ee52,\n 0x1ee54, 0x1ee54,\n 0x1ee57, 0x1ee57,\n 0x1ee59, 0x1ee59,\n 0x1ee5b, 0x1ee5b,\n 0x1ee5d, 0x1ee5d,\n 0x1ee5f, 0x1ee5f,\n 0x1ee61, 0x1ee62,\n 0x1ee64, 0x1ee64,\n 0x1ee67, 0x1ee6a,\n 0x1ee6c, 0x1ee72,\n 0x1ee74, 0x1ee77,\n 0x1ee79, 0x1ee7c,\n 0x1ee7e, 0x1ee7e,\n 0x1ee80, 0x1ee89,\n 0x1ee8b, 0x1ee9b,\n 0x1eea1, 0x1eea3,\n 0x1eea5, 0x1eea9,\n 0x1eeab, 0x1eebb,\n 0x20000, 0x2a6df,\n 0x2a700, 0x2b81d,\n 0x2b820, 0x2cead,\n 0x2ceb0, 0x2ebe0,\n 0x2ebf0, 0x2ee5d,\n 0x2f800, 0x2fa1d,\n 0x30000, 0x3134a,\n 0x31350, 0x33479\n];\n", "import type { Direction } from './types.js';\nimport {\n NON_STRONG_BIDI_RANGES,\n NATURAL_LETTER_RANGES,\n RTL_BIDI_RANGES,\n UNICODE_BIDI_SHA256,\n UNICODE_GENERAL_CATEGORY_SHA256,\n UNICODE_BIDI_VERSION\n} from './generated/bidi-ranges.js';\n\nfunction isInRanges(codePoint: number, ranges: ReadonlyArray): boolean {\n let low = 0;\n let high = ranges.length / 2 - 1;\n while (low <= high) {\n const middle = (low + high) >> 1;\n const start = ranges[middle * 2]!;\n const end = ranges[middle * 2 + 1]!;\n if (codePoint < start) high = middle - 1;\n else if (codePoint > end) low = middle + 1;\n else return true;\n }\n return false;\n}\n\nexport function isRtlCodePoint(codePoint: number): boolean {\n return isInRanges(codePoint, RTL_BIDI_RANGES);\n}\n\n/** Returns the Unicode Bidi_Class strong direction, including LRM/RLM/ALM. */\nexport function classifyBidiStrongCharacter(character: string): Direction {\n const codePoint = character.codePointAt(0);\n if (codePoint === undefined || isInRanges(codePoint, NON_STRONG_BIDI_RANGES)) return 'neutral';\n return isRtlCodePoint(codePoint) ? 'rtl' : 'ltr';\n}\n\n/** Classifies natural-language letters while leaving numbers and punctuation neutral. */\nexport function classifyCharacter(character: string): Direction {\n const codePoint = character.codePointAt(0);\n if (codePoint === undefined) return 'neutral';\n return isInRanges(codePoint, NATURAL_LETTER_RANGES) ? classifyBidiStrongCharacter(character) : 'neutral';\n}\n\nexport const UNICODE_DATA_VERSION = UNICODE_BIDI_VERSION;\nexport const UNICODE_DATA_SHA256 = UNICODE_BIDI_SHA256;\nexport const UNICODE_LETTER_DATA_SHA256 = UNICODE_GENERAL_CATEGORY_SHA256;\n", "/**\n * Validate and clamp a numeric option without allowing NaN or infinities to\n * poison direction comparisons. Finite values retain the historical\n * clamping behavior; non-finite values are caller errors.\n */\nexport function boundedNumberOption(\n name: string,\n value: number | undefined,\n defaultValue: number,\n minimum: number,\n maximum: number\n): number {\n const resolved = value ?? defaultValue;\n if (!Number.isFinite(resolved)) {\n throw new RangeError(`${name} must be a finite number.`);\n }\n return Math.min(maximum, Math.max(minimum, resolved));\n}\n", "/**\n * The default paragraph grammar follows the complete Unicode 17\n * Bidi_Class=Paragraph_Separator set. CRLF is listed before CR and LF so it\n * is consumed as one separator. U+2028 is intentionally absent: Unicode\n * classifies it as a line separator (WS), not a paragraph separator (B).\n */\nexport const DEFAULT_PARAGRAPH_SEPARATOR_SOURCE =\n '\\\\r\\\\n|\\\\n|\\\\r|\\\\u0085|[\\\\u001C-\\\\u001E]|\\\\u2029';\n\nexport function isDefaultParagraphBoundaryCharacter(character: string): boolean {\n if (character.length !== 1) return false;\n const codeUnit = character.charCodeAt(0);\n return codeUnit === 0x0a\n || codeUnit === 0x0d\n || codeUnit === 0x85\n || (codeUnit >= 0x1c && codeUnit <= 0x1e)\n || codeUnit === 0x2029;\n}\n", "import { classifyBidiStrongCharacter, classifyCharacter } from './classify.js';\nimport { boundedNumberOption } from './options.js';\nimport { DEFAULT_PARAGRAPH_SEPARATOR_SOURCE } from './paragraph.js';\nimport type {\n DetectionOptions,\n Direction,\n ParagraphAnalysis,\n StrongCharacterCounts,\n TextAnalysis\n} from './types.js';\n\nexport interface TechnicalTokenRange {\n text: string;\n start: number;\n end: number;\n kind: 'code' | 'url' | 'email' | 'path' | 'version' | 'hash' | 'identifier' | 'number' | 'command' | 'math' | 'html';\n}\n\nconst DEFAULT_OPTIONS: Required = {\n strategy: 'content-majority',\n fallback: 'neutral',\n inheritedDirection: 'ltr',\n minimumStrongCharacters: 1,\n majorityThreshold: 0.5,\n excludeTechnicalTokens: true,\n technicalIdentifiers: []\n};\n\nexport const DEFAULT_TECHNICAL_IDENTIFIERS = Object.freeze([\n 'ai', 'api', 'anthropic', 'chatgpt', 'claude', 'cli', 'codex', 'copilot', 'cursor',\n 'deepseek', 'electron', 'gemini', 'github', 'gitlab', 'grok', 'huggingface',\n 'javascript', 'json', 'llama', 'markdown', 'mistral', 'node', 'npm', 'openai',\n 'python', 'qwen', 'react', 'rust', 'svelte', 'typescript', 'url', 'version',\n 'vscode', 'vue', 'web', 'webpack', 'yaml',\n 'angular', 'astro', 'chrome', 'docker', 'esbuild', 'eslint', 'firefox',\n 'kubernetes', 'kubectl', 'nuxt', 'playwright', 'pnpm', 'preact', 'remix',\n 'rollup', 'safari', 'stencil', 'storybook', 'tailwind', 'turbopack', 'vite',\n 'vitest'\n] as const);\nconst KNOWN_TECHNICAL_TOKENS = new Set(DEFAULT_TECHNICAL_IDENTIFIERS);\nconst CUSTOM_TECHNICAL_IDENTIFIER_CACHE = new WeakMap>();\n\nfunction normalizeOptions(options: DetectionOptions = {}): Required {\n const strategy = options.strategy ?? DEFAULT_OPTIONS.strategy;\n const majorityStrategy = strategy === 'content-majority'\n || strategy === 'semantic-dominant'\n || strategy === 'majority';\n return {\n strategy,\n fallback: options.fallback ?? options.inheritedDirection ?? DEFAULT_OPTIONS.fallback,\n inheritedDirection: options.inheritedDirection ?? DEFAULT_OPTIONS.inheritedDirection,\n minimumStrongCharacters: boundedNumberOption(\n 'minimumStrongCharacters',\n options.minimumStrongCharacters,\n DEFAULT_OPTIONS.minimumStrongCharacters,\n 1,\n Number.POSITIVE_INFINITY\n ),\n majorityThreshold: boundedNumberOption(\n 'majorityThreshold',\n options.majorityThreshold,\n DEFAULT_OPTIONS.majorityThreshold,\n 0.5,\n 1\n ),\n // Compatibility/strict first-strong modes must see the real first strong\n // character (including a leading technical identifier), like dir=\"auto\".\n excludeTechnicalTokens: options.excludeTechnicalTokens ?? majorityStrategy,\n technicalIdentifiers: options.technicalIdentifiers ?? DEFAULT_OPTIONS.technicalIdentifiers\n };\n}\n\nfunction addRange(\n ranges: TechnicalTokenRange[],\n text: string,\n start: number,\n end: number,\n kind: TechnicalTokenRange['kind']\n): void {\n if (end > start) ranges.push({ text: text.slice(start, end), start, end, kind });\n}\n\nfunction addMatches(\n text: string,\n ranges: TechnicalTokenRange[],\n expression: RegExp,\n kind: TechnicalTokenRange['kind'],\n group = 0\n): void {\n expression.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = expression.exec(text)) !== null) {\n const value = match[group];\n if (value === undefined) continue;\n const start = match.index + match[0].indexOf(value);\n addRange(ranges, text, start, start + value.length, kind);\n }\n}\n\n/**\n * Adds `$...$`, `$$...$$`, and `\\(...\\)` math ranges in one forward pass.\n * A combined lazy regular expression restarts its search after every unmatched\n * `\\(` opener, which makes adversarial input quadratic.\n */\nfunction addMathRanges(text: string, ranges: TechnicalTokenRange[]): void {\n let i = 0;\n let scanned = -1;\n while (i < text.length) {\n const p = text[i] === '\\\\' && text[i + 1] === '(';\n const d = text[i] === '$'\n ? (text[i + 1] === '$' ? '$$' : '$')\n : (p && i >= scanned ? '\\\\)' : '');\n if (!d) { i++; continue; }\n\n let e = i + (p ? 2 : d.length);\n while (e < text.length\n && text[e] !== '\\r'\n && text[e] !== '\\n'\n && !text.startsWith(d, e)) e++;\n\n if (text.startsWith(d, e) && (d !== '$' || e > i + 1)) {\n addRange(ranges, text, i, e + d.length, 'math');\n i = e + d.length;\n } else {\n if (p) scanned = e;\n i++;\n }\n }\n}\n\nfunction trimTechnicalPunctuation(value: string): string {\n let end = value.length;\n while (end > 0 && /[.,;:!?\u060C\u061B\u061F\u3002\u0964\u06D4]/u.test(value[end - 1]!)) end -= 1;\n return end === value.length ? value : value.slice(0, end);\n}\n\nfunction addValidatedMatches(\n text: string,\n ranges: TechnicalTokenRange[],\n expression: RegExp,\n kind: TechnicalTokenRange['kind'],\n validate: (value: string) => boolean,\n group = 0\n): void {\n expression.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = expression.exec(text)) !== null) {\n const value = match[group];\n if (value === undefined || !validate(value)) continue;\n const start = match.index + match[0].indexOf(value);\n addRange(ranges, text, start, start + value.length, kind);\n }\n}\n\nfunction addNormalizedMatches(\n text: string,\n ranges: TechnicalTokenRange[],\n expression: RegExp,\n kind: TechnicalTokenRange['kind'],\n normalize: (value: string) => string,\n group = 0\n): void {\n expression.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = expression.exec(text)) !== null) {\n const original = match[group];\n if (original === undefined) continue;\n const value = normalize(original);\n if (!value) continue;\n const start = match.index + match[0].indexOf(original);\n addRange(ranges, text, start, start + value.length, kind);\n }\n}\n\nfunction isIpv4(value: string): boolean {\n const parts = value.split('.');\n return parts.length === 4 && parts.every((part) => /^\\d{1,3}$/u.test(part) && Number(part) <= 255);\n}\n\nfunction isIpv6(value: string): boolean {\n if (!/^[0-9A-F:]+$/iu.test(value) || !value.includes(':')) return false;\n const compression = value.indexOf('::');\n if (compression !== value.lastIndexOf('::')) return false;\n const sides = compression >= 0 ? value.split('::') : [value];\n const groups = sides.flatMap((side) => side ? side.split(':') : []);\n if (!groups.every((group) => /^[0-9A-F]{1,4}$/iu.test(group))) return false;\n return compression >= 0 ? groups.length < 8 : groups.length === 8;\n}\n\nfunction addCodeRanges(text: string, ranges: TechnicalTokenRange[]): void {\n let fence: { marker: '`' | '~'; length: number; start: number } | undefined;\n const closedFences: Array<{ start: number; end: number }> = [];\n let lineStart = 0;\n while (lineStart < text.length) {\n let lineEnd = lineStart;\n while (lineEnd < text.length && text[lineEnd] !== '\\r' && text[lineEnd] !== '\\n') lineEnd += 1;\n let nextLine = lineEnd;\n if (text[nextLine] === '\\r') nextLine += 1;\n if (text[nextLine] === '\\n') nextLine += 1;\n const line = text.slice(lineStart, lineEnd);\n if (!fence) {\n const openerMatch = /^ {0,3}(`{3,}|~{3,})(.*)$/u.exec(line);\n const opener = openerMatch?.[1];\n const info = openerMatch?.[2] ?? '';\n if (opener && !(opener[0] === '`' && info.includes('`'))) fence = {\n marker: opener[0] as '`' | '~',\n length: opener.length,\n start: lineStart\n };\n } else {\n const closer = /^ {0,3}(`+|~+)[ \\t]*$/u.exec(line)?.[1];\n if (closer?.[0] === fence.marker && closer.length >= fence.length) {\n closedFences.push({ start: fence.start, end: nextLine });\n fence = undefined;\n }\n }\n lineStart = nextLine;\n }\n // Decide once over the union of all closed spans. Scanning each fence's\n // complementary text separately would be quadratic and would mistake code\n // inside a second standalone fence for prose outside the first.\n let fenceIndex = 0;\n let utf16Index = 0;\n let hasOutsideNaturalText = false;\n for (const character of text) {\n while (fenceIndex < closedFences.length && utf16Index >= closedFences[fenceIndex]!.end) {\n fenceIndex += 1;\n }\n const span = closedFences[fenceIndex];\n const insideFence = span !== undefined && utf16Index >= span.start && utf16Index < span.end;\n if (!insideFence && classifyCharacter(character) !== 'neutral') {\n hasOutsideNaturalText = true;\n break;\n }\n utf16Index += character.length;\n }\n // Standalone fenced code keeps its historical raw-text direction evidence.\n // Parser-aware Markdown adapters force code blocks LTR. Excluding complete\n // fences is useful when surrounding prose\u2014not code literals\u2014must decide the\n // containing raw block's natural direction.\n if (hasOutsideNaturalText) {\n for (const span of closedFences) addRange(ranges, text, span.start, span.end, 'code');\n }\n\n const lineExpression = /[^\\r\\n]*/gu;\n let lineMatch: RegExpExecArray | null;\n while ((lineMatch = lineExpression.exec(text)) !== null) {\n const line = lineMatch[0];\n const lineStart = lineMatch.index;\n const runs: Array<{ start: number; length: number }> = [];\n for (let index = 0; index < line.length;) {\n if (line[index] !== '`') {\n index += 1;\n continue;\n }\n const start = index;\n while (index < line.length && line[index] === '`') index += 1;\n runs.push({ start, length: index - start });\n }\n const suffixMaximum = new Array(runs.length + 1).fill(0);\n for (let index = runs.length - 1; index >= 0; index -= 1) {\n suffixMaximum[index] = Math.max(runs[index]!.length, suffixMaximum[index + 1]!);\n }\n let runIndex = 0;\n let cursor = runs[0]?.start ?? 0;\n while (runIndex < runs.length) {\n const opener = runs[runIndex]!;\n const openerEnd = opener.start + opener.length;\n if (cursor >= openerEnd) {\n runIndex += 1;\n cursor = runs[runIndex]?.start ?? 0;\n continue;\n }\n const available = openerEnd - cursor;\n const delimiterLength = Math.min(\n available,\n Math.max(Math.floor(available / 2), suffixMaximum[runIndex + 1]!)\n );\n if (delimiterLength === 0) {\n runIndex += 1;\n cursor = runs[runIndex]?.start ?? 0;\n continue;\n }\n let closingRunIndex = runIndex;\n let closingStart = cursor + delimiterLength;\n if (available - delimiterLength < delimiterLength) {\n closingRunIndex += 1;\n while (closingRunIndex < runs.length\n && runs[closingRunIndex]!.length < delimiterLength) closingRunIndex += 1;\n if (closingRunIndex >= runs.length) {\n runIndex += 1;\n cursor = runs[runIndex]?.start ?? 0;\n continue;\n }\n closingStart = runs[closingRunIndex]!.start;\n }\n const end = closingStart + delimiterLength;\n addRange(ranges, text, lineStart + cursor, lineStart + end, 'code');\n runIndex = closingRunIndex;\n cursor = end;\n }\n if (lineMatch[0].length === 0) lineExpression.lastIndex += 1;\n }\n}\n\nfunction customTechnicalIdentifiers(values: readonly string[]): ReadonlySet {\n const cacheable = Object.isFrozen(values);\n const cached = cacheable ? CUSTOM_TECHNICAL_IDENTIFIER_CACHE.get(values) : undefined;\n if (cached) return cached;\n const identifiers = new Set();\n for (const value of values) {\n if (/^[A-Za-z][A-Za-z0-9_.-]*$/u.test(value)) identifiers.add(value.toLowerCase());\n }\n if (cacheable) CUSTOM_TECHNICAL_IDENTIFIER_CACHE.set(values, identifiers);\n return identifiers;\n}\n\n/**\n * Acronyms are short. A longer all-capital word is emphasized prose, not an\n * identifier, and must keep deciding the natural-language base direction.\n */\nconst ACRONYM_MAXIMUM_LENGTH = 5;\n\nfunction isKnownTechnicalWord(value: string, custom: ReadonlySet): boolean {\n const normalized = value.toLowerCase();\n return KNOWN_TECHNICAL_TOKENS.has(normalized) || custom.has(normalized);\n}\n\n/**\n * Reports whether capitals are the block's prose style rather than an\n * identifier signal. `PLEASE READ THIS WARNING` is emphasized natural language;\n * the same `API` token inside mixed-case prose is an acronym. Deciding this per\n * block keeps the rule deterministic and needs no dictionary or language model.\n */\nfunction usesUppercaseProse(text: string): boolean {\n const words = text.match(/\\b[A-Za-z]{2,}\\b/gu);\n if (words === null || words.length < 2) return false;\n let capitalized = 0;\n let hasLongCapitalizedWord = false;\n // Every candidate is alphabetic, so \"contains no lowercase\" means all-capital.\n for (const word of words) {\n if (/[a-z]/u.test(word)) continue;\n capitalized += 1;\n if (word.length > ACRONYM_MAXIMUM_LENGTH) hasLongCapitalizedWord = true;\n }\n // `HTTP API` is an acronym sequence, not proof of an uppercase prose style.\n // Requiring one long word keeps that short technical phrase excluded while\n // still recognizing natural-language emphasis such as `PLEASE READ THIS`.\n return hasLongCapitalizedWord && capitalized * 2 > words.length;\n}\n\n/**\n * Only tokens starting with an ASCII letter reach this test, so every false\n * exclusion removes LTR evidence and never RTL evidence. An over-broad rule\n * therefore biases mixed blocks toward RTL \u2014 the mirror of the failure this\n * project exists to fix \u2014 which is why the hyphen is not a signal on its own.\n */\nfunction isTechnicalIdentifier(\n token: string,\n custom: ReadonlySet,\n uppercaseProse: boolean\n): boolean {\n if (isKnownTechnicalWord(token, custom)) return true;\n // A hyphenated token is technical when a segment is itself a known technical\n // word (`react-markdown`, `web-app`), not merely because it is hyphenated.\n if (token.includes('-')\n && token.split('-').some((segment) => segment !== '' && isKnownTechnicalWord(segment, custom))) {\n return true;\n }\n // Digits, underscores, and dots are structural identifier syntax.\n return /[0-9_.]/u.test(token)\n || /[a-z][A-Z]/u.test(token)\n || (!uppercaseProse\n && token.length <= ACRONYM_MAXIMUM_LENGTH\n && /^[A-Z]{2,}$/u.test(token));\n}\n\n/** Finds ranges that should not decide the natural-language base direction. */\nexport function findTechnicalTokenRanges(\n text: string,\n technicalIdentifiers: readonly string[] = []\n): TechnicalTokenRange[] {\n const ranges: TechnicalTokenRange[] = [];\n addCodeRanges(text, ranges);\n addMatches(text, ranges, /<\\/?[A-Za-z][^<>\\r\\n]*>/gu, 'html');\n addMathRanges(text, ranges);\n\n const urls = /\\b(?:https?|ftp):\\/\\/[^\\s<>{}\"']+/giu;\n let urlMatch: RegExpExecArray | null;\n while ((urlMatch = urls.exec(text)) !== null) {\n let value = urlMatch[0];\n value = trimTechnicalPunctuation(value);\n for (const [open, close] of [['(', ')'], ['[', ']'], ['{', '}']] as const) {\n if (!value.endsWith(close)) continue;\n let balance = 0;\n for (const character of value) {\n if (character === open) balance += 1;\n else if (character === close) balance -= 1;\n }\n if (balance >= 0) continue;\n let end = value.length;\n while (balance < 0 && end > 0 && value[end - 1] === close) {\n balance += 1;\n end -= 1;\n }\n if (end !== value.length) value = value.slice(0, end);\n }\n addRange(ranges, text, urlMatch.index, urlMatch.index + value.length, 'url');\n }\n addMatches(text, ranges, /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/giu, 'email');\n addNormalizedMatches(\n text,\n ranges,\n /(?()\\x5B\\x5D{}]+/gu,\n 'path',\n trimTechnicalPunctuation\n );\n addMatches(text, ranges, /\\b(?:[A-Za-z0-9_.-]+[\\\\/])+(?:[A-Za-z0-9_.-]+)\\b/gu, 'path');\n addMatches(text, ranges, /(?))/gu, 'identifier');\n\n const words = /\\b[A-Za-z][A-Za-z0-9_.-]*\\b/gu;\n const customIdentifiers = customTechnicalIdentifiers(technicalIdentifiers);\n const uppercaseProse = usesUppercaseProse(text);\n let match: RegExpExecArray | null;\n while ((match = words.exec(text)) !== null) {\n const token = match[0];\n if (isTechnicalIdentifier(token, customIdentifiers, uppercaseProse)) {\n addRange(ranges, text, match.index, match.index + token.length, 'identifier');\n }\n }\n\n ranges.sort((a, b) => a.start - b.start || b.end - a.end);\n const merged: TechnicalTokenRange[] = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end) {\n previous.end = Math.max(previous.end, range.end);\n previous.text = text.slice(previous.start, previous.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged;\n}\n\nexport function countStrongCharacters(\n text: string,\n options: DetectionOptions = {}\n): StrongCharacterCounts & { firstStrong: Direction; technicalTokens: TechnicalTokenRange[] } {\n const normalized = normalizeOptions(options);\n return countStrongCharactersNormalized(text, normalized);\n}\n\nfunction countStrongCharactersNormalized(\n text: string,\n normalized: Required\n): StrongCharacterCounts & { firstStrong: Direction; technicalTokens: TechnicalTokenRange[] } {\n const technicalTokens = normalized.excludeTechnicalTokens\n ? findTechnicalTokenRanges(text, normalized.technicalIdentifiers)\n : [];\n let ltr = 0;\n let rtl = 0;\n let firstStrong: Direction = 'neutral';\n let index = 0;\n let technicalIndex = 0;\n const classify = normalized.strategy === 'first-strong' || normalized.strategy === 'strict-uax9'\n ? classifyBidiStrongCharacter\n : classifyCharacter;\n\n for (const character of text) {\n // Technical ranges are sorted and merged, so advance one cursor instead\n // of rescanning every range for every code point. This keeps detection\n // linear even for long transcripts containing many URLs/identifiers.\n while (technicalIndex < technicalTokens.length && index >= technicalTokens[technicalIndex]!.end) {\n technicalIndex += 1;\n }\n const technicalRange = technicalTokens[technicalIndex];\n const isTechnical = technicalRange !== undefined\n && index >= technicalRange.start\n && index < technicalRange.end;\n if (!isTechnical) {\n const direction = classify(character);\n if (direction === 'ltr') ltr += 1;\n if (direction === 'rtl') rtl += 1;\n if (firstStrong === 'neutral' && direction !== 'neutral') firstStrong = direction;\n }\n index += character.length;\n }\n\n return { ltr, rtl, total: ltr + rtl, firstStrong, technicalTokens };\n}\n\nfunction fallbackDirection(options: Required): Direction {\n return options.fallback;\n}\n\nfunction directionFromCounts(\n counts: StrongCharacterCounts & { firstStrong: Direction },\n normalized: Required\n): Direction {\n if (normalized.strategy === 'ltr' || normalized.strategy === 'rtl') return normalized.strategy;\n if (normalized.strategy === 'inherit') return normalized.inheritedDirection;\n if (counts.total < normalized.minimumStrongCharacters) return fallbackDirection(normalized);\n\n if (normalized.strategy === 'first-strong' || normalized.strategy === 'strict-uax9') {\n return counts.firstStrong === 'neutral' ? fallbackDirection(normalized) : counts.firstStrong;\n }\n\n if (counts.rtl > counts.ltr && counts.rtl / counts.total >= normalized.majorityThreshold) return 'rtl';\n if (counts.ltr > counts.rtl && counts.ltr / counts.total >= normalized.majorityThreshold) return 'ltr';\n return counts.firstStrong === 'neutral' ? fallbackDirection(normalized) : counts.firstStrong;\n}\n\nexport function detectDirection(text: string, options: DetectionOptions = {}): Direction {\n const normalized = normalizeOptions(options);\n if (normalized.strategy === 'ltr' || normalized.strategy === 'rtl') return normalized.strategy;\n if (normalized.strategy === 'inherit') return normalized.inheritedDirection;\n return directionFromCounts(countStrongCharactersNormalized(text, normalized), normalized);\n}\n\nfunction confidenceFor(counts: StrongCharacterCounts, direction: Direction): number {\n if (counts.total === 0 || direction === 'neutral') return 0;\n const matching = direction === 'rtl' ? counts.rtl : counts.ltr;\n return Number((matching / counts.total).toFixed(4));\n}\n\nfunction firstBidiStrongCharacter(text: string): Direction {\n for (const character of text) {\n const direction = classifyBidiStrongCharacter(character);\n if (direction !== 'neutral') return direction;\n }\n return 'neutral';\n}\n\nfunction splitParagraphs(text: string): Array<{ text: string; start: number; end: number }> {\n const paragraphs: Array<{ text: string; start: number; end: number }> = [];\n const separator = new RegExp(DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, 'gu');\n let start = 0;\n let match: RegExpExecArray | null;\n\n while ((match = separator.exec(text)) !== null) {\n paragraphs.push({ text: text.slice(start, match.index), start, end: match.index });\n start = match.index + match[0].length;\n }\n paragraphs.push({ text: text.slice(start), start, end: text.length });\n return paragraphs;\n}\n\nexport function analyzeParagraph(text: string, start = 0, options: DetectionOptions = {}): ParagraphAnalysis {\n const normalized = normalizeOptions(options);\n const countsWithFirst = countStrongCharactersNormalized(text, normalized);\n const counts: StrongCharacterCounts = {\n ltr: countsWithFirst.ltr,\n rtl: countsWithFirst.rtl,\n total: countsWithFirst.total\n };\n const direction = directionFromCounts(countsWithFirst, normalized);\n return {\n text,\n start,\n end: start + text.length,\n direction,\n firstStrong: countsWithFirst.firstStrong,\n confidence: confidenceFor(counts, direction),\n counts\n };\n}\n\nexport function analyzeText(text: string, options: DetectionOptions = {}): TextAnalysis {\n const normalized = normalizeOptions(options);\n const countsWithFirst = countStrongCharactersNormalized(text, normalized);\n const counts: StrongCharacterCounts = {\n ltr: countsWithFirst.ltr,\n rtl: countsWithFirst.rtl,\n total: countsWithFirst.total\n };\n const direction = directionFromCounts(countsWithFirst, normalized);\n const rawCountsWithFirst = countStrongCharactersNormalized(text, normalizeOptions({\n ...normalized,\n strategy: 'content-majority',\n excludeTechnicalTokens: false\n }));\n const rawCounts: StrongCharacterCounts = {\n ltr: rawCountsWithFirst.ltr,\n rtl: rawCountsWithFirst.rtl,\n total: rawCountsWithFirst.total\n };\n const split = splitParagraphs(text);\n const paragraphs = split.length === 1\n ? [{\n text,\n start: 0,\n end: text.length,\n direction,\n firstStrong: countsWithFirst.firstStrong,\n confidence: confidenceFor(counts, direction),\n counts\n }]\n : split.map((paragraph) => analyzeParagraph(paragraph.text, paragraph.start, normalized));\n return {\n text,\n direction,\n firstStrong: countsWithFirst.firstStrong,\n rawFirstStrong: firstBidiStrongCharacter(text),\n confidence: confidenceFor(counts, direction),\n counts,\n rawCounts,\n paragraphs,\n mixed: rawCounts.ltr > 0 && rawCounts.rtl > 0\n };\n}\n", "import type {\n BidiControlFinding,\n BidiControlRisk,\n BidiControlSanitizationGroup,\n BidiSecurityFinding,\n BidiSecurityMode,\n BidiSecurityReport,\n BidiSecuritySeverity\n} from './types.js';\n\nconst UAX9_PARAGRAPH_SEPARATOR = new RegExp(\n `\\\\r\\\\n|\\\\n|\\\\r|\\\\u0085|[${String.fromCodePoint(0x1c)}-${String.fromCodePoint(0x1e)}]|\\\\u2029`,\n 'gu'\n);\n\nconst CONTROL_METADATA = new Map>([\n [0x061c, { name: 'ARABIC LETTER MARK', risk: 'low', category: 'mark' }],\n [0x200e, { name: 'LEFT-TO-RIGHT MARK', risk: 'low', category: 'mark' }],\n [0x200f, { name: 'RIGHT-TO-LEFT MARK', risk: 'low', category: 'mark' }],\n [0x202a, { name: 'LEFT-TO-RIGHT EMBEDDING', risk: 'high', category: 'embedding' }],\n [0x202b, { name: 'RIGHT-TO-LEFT EMBEDDING', risk: 'high', category: 'embedding' }],\n [0x202c, { name: 'POP DIRECTIONAL FORMATTING', risk: 'medium', category: 'pop' }],\n [0x202d, { name: 'LEFT-TO-RIGHT OVERRIDE', risk: 'high', category: 'override' }],\n [0x202e, { name: 'RIGHT-TO-LEFT OVERRIDE', risk: 'high', category: 'override' }],\n [0x2066, { name: 'LEFT-TO-RIGHT ISOLATE', risk: 'medium', category: 'isolate' }],\n [0x2067, { name: 'RIGHT-TO-LEFT ISOLATE', risk: 'medium', category: 'isolate' }],\n [0x2068, { name: 'FIRST STRONG ISOLATE', risk: 'medium', category: 'isolate' }],\n [0x2069, { name: 'POP DIRECTIONAL ISOLATE', risk: 'medium', category: 'pop' }],\n [0x206a, { name: 'INHIBIT SYMMETRIC SWAPPING', risk: 'medium', category: 'deprecated' }],\n [0x206b, { name: 'ACTIVATE SYMMETRIC SWAPPING', risk: 'medium', category: 'deprecated' }],\n [0x206c, { name: 'INHIBIT ARABIC FORM SHAPING', risk: 'medium', category: 'deprecated' }],\n [0x206d, { name: 'ACTIVATE ARABIC FORM SHAPING', risk: 'medium', category: 'deprecated' }],\n [0x206e, { name: 'NATIONAL DIGIT SHAPES', risk: 'medium', category: 'deprecated' }],\n [0x206f, { name: 'NOMINAL DIGIT SHAPES', risk: 'medium', category: 'deprecated' }]\n]);\n\nconst REMEDIATION = 'Remove the control unless a documented plain-text protocol requires it; prefer semantic markup and isolation.';\n\nfunction severityForRisk(risk: BidiControlRisk): BidiSecuritySeverity {\n if (risk === 'high') return 'high';\n if (risk === 'medium') return 'warning';\n return 'info';\n}\n\nfunction rangeFor(control: BidiControlFinding): BidiSecurityFinding['sourceRange'] {\n return {\n utf16: { start: control.index, end: control.end },\n codePoint: { start: control.codePointIndex, end: control.codePointIndex + 1 }\n };\n}\n\nfunction codeForControl(control: BidiControlFinding): string {\n if (control.category === 'override') return 'BIDI_OVERRIDE_CONTROL';\n if (control.category === 'embedding') return 'BIDI_EMBEDDING_CONTROL';\n if (control.category === 'isolate') return 'BIDI_ISOLATE_CONTROL';\n if (control.category === 'mark') return 'BIDI_DIRECTIONAL_MARK';\n if (control.category === 'deprecated') return 'BIDI_DEPRECATED_CONTROL';\n return 'BIDI_POP_CONTROL';\n}\n\nfunction controlFinding(control: BidiControlFinding): BidiSecurityFinding {\n return {\n code: codeForControl(control),\n severity: severityForRisk(control.risk),\n message: `${control.name} (${control.codePoint}) is invisible and changes bidirectional interpretation.`,\n sourceRange: rangeFor(control),\n remediation: REMEDIATION,\n control\n };\n}\n\nexport function findBidiControls(text: string): BidiControlFinding[] {\n const findings: BidiControlFinding[] = [];\n let utf16Index = 0;\n let codePointIndex = 0;\n\n for (const character of text) {\n const codePoint = character.codePointAt(0)!;\n const metadata = CONTROL_METADATA.get(codePoint);\n if (metadata) {\n findings.push({\n character,\n codePoint: `U+${codePoint.toString(16).toUpperCase().padStart(4, '0')}`,\n index: utf16Index,\n end: utf16Index + character.length,\n codePointIndex,\n ...metadata\n });\n }\n utf16Index += character.length;\n codePointIndex += 1;\n }\n return findings;\n}\n\nexport function visibleBidiControls(text: string): string {\n const namesByCodePoint = new Map([...CONTROL_METADATA].map(([codePoint, metadata]) => [codePoint, metadata.name]));\n let result = '';\n for (const character of text) {\n const codePoint = character.codePointAt(0)!;\n const name = namesByCodePoint.get(codePoint);\n result += name ? `\u27E6${name}\u27E7` : character;\n }\n return result;\n}\n\nexport function highestControlRisk(findings: readonly BidiControlFinding[]): BidiControlRisk | null {\n if (findings.some((finding) => finding.risk === 'high')) return 'high';\n if (findings.some((finding) => finding.risk === 'medium')) return 'medium';\n if (findings.some((finding) => finding.risk === 'low')) return 'low';\n return null;\n}\n\ninterface FormattingFrame {\n kind: 'embedding' | 'isolate';\n control: BidiControlFinding;\n}\n\nfunction lastFrameIndex(stack: readonly FormattingFrame[], kind: FormattingFrame['kind']): number {\n for (let index = stack.length - 1; index >= 0; index -= 1) {\n if (stack[index]?.kind === kind) return index;\n }\n return -1;\n}\n\nfunction balanceParagraph(\n controls: readonly BidiControlFinding[],\n boundary: 'paragraph' | 'text'\n): BidiSecurityFinding[] {\n const findings: BidiSecurityFinding[] = [];\n const stack: FormattingFrame[] = [];\n\n for (const control of controls) {\n const codePoint = control.codePoint;\n if (codePoint === 'U+202A' || codePoint === 'U+202B' || codePoint === 'U+202D' || codePoint === 'U+202E') {\n stack.push({ kind: 'embedding', control });\n continue;\n }\n if (codePoint === 'U+2066' || codePoint === 'U+2067' || codePoint === 'U+2068') {\n stack.push({ kind: 'isolate', control });\n continue;\n }\n if (codePoint === 'U+202C') {\n const isolateIndex = lastFrameIndex(stack, 'isolate');\n const embeddingIndex = lastFrameIndex(stack, 'embedding');\n if (embeddingIndex <= isolateIndex) {\n findings.push({\n code: 'BIDI_UNMATCHED_PDF',\n severity: 'high',\n message: 'POP DIRECTIONAL FORMATTING has no matching active embedding or override.',\n sourceRange: rangeFor(control),\n remediation: 'Remove the unmatched PDF or add the intended opener within the same isolate.',\n control\n });\n } else {\n stack.splice(embeddingIndex, 1);\n }\n continue;\n }\n if (codePoint === 'U+2069') {\n const isolateIndex = lastFrameIndex(stack, 'isolate');\n if (isolateIndex < 0) {\n findings.push({\n code: 'BIDI_UNMATCHED_PDI',\n severity: 'high',\n message: 'POP DIRECTIONAL ISOLATE has no matching isolate opener.',\n sourceRange: rangeFor(control),\n remediation: 'Remove the unmatched PDI or add the intended LRI, RLI, or FSI opener.',\n control\n });\n } else {\n const crossing = stack.slice(isolateIndex + 1).filter((frame) => frame.kind === 'embedding');\n for (const frame of crossing) {\n findings.push({\n code: 'BIDI_FORMAT_CROSSES_ISOLATE_BOUNDARY',\n severity: 'high',\n message: `${frame.control.name} is not closed before the containing isolate ends.`,\n sourceRange: rangeFor(frame.control),\n remediation: 'Close the embedding or override with PDF before PDI.',\n control: frame.control\n });\n }\n stack.splice(isolateIndex);\n }\n }\n }\n\n for (const frame of stack) {\n findings.push({\n code: frame.kind === 'isolate' ? 'BIDI_UNCLOSED_ISOLATE' : 'BIDI_UNCLOSED_EMBEDDING',\n severity: 'high',\n message: `${frame.control.name} is not terminated before ${boundary === 'paragraph' ? 'the paragraph boundary' : 'the end of the text'}.`,\n sourceRange: rangeFor(frame.control),\n remediation: frame.kind === 'isolate'\n ? 'Add the matching PDI or remove the isolate opener.'\n : 'Add the matching PDF or remove the embedding/override opener.',\n control: frame.control\n });\n }\n return findings;\n}\n\n/**\n * Bidi formatting state is paragraph-scoped under UAX #9. A PDF/PDI after a\n * line or paragraph separator must not close an opener from the preceding\n * paragraph, so balance each paragraph independently.\n */\nfunction balanceFindings(text: string, controls: readonly BidiControlFinding[]): BidiSecurityFinding[] {\n const findings: BidiSecurityFinding[] = [];\n // UAX #9 paragraph separators are CR, LF, NEL, U+001C..U+001E, and\n // U+2029. Keep the security scope aligned with the pinned Unicode data.\n let controlIndex = 0;\n\n for (const match of text.matchAll(UAX9_PARAGRAPH_SEPARATOR)) {\n const paragraphControls: BidiControlFinding[] = [];\n while (controlIndex < controls.length && controls[controlIndex]!.index < match.index) {\n paragraphControls.push(controls[controlIndex]!);\n controlIndex += 1;\n }\n findings.push(...balanceParagraph(paragraphControls, 'paragraph'));\n }\n\n findings.push(...balanceParagraph(controls.slice(controlIndex), 'text'));\n return findings;\n}\n\nfunction isAsciiIdentifierCharacter(value: string | undefined): boolean {\n return value !== undefined && /^[A-Za-z0-9_$]$/u.test(value);\n}\n\nfunction invisibleCharacterFindings(text: string): BidiSecurityFinding[] {\n const findings: BidiSecurityFinding[] = [];\n const characters = [...text];\n let utf16Index = 0;\n for (let codePointIndex = 0; codePointIndex < characters.length; codePointIndex += 1) {\n const character = characters[codePointIndex]!;\n const sourceRange = {\n utf16: { start: utf16Index, end: utf16Index + character.length },\n codePoint: { start: codePointIndex, end: codePointIndex + 1 }\n };\n if (character === '\\u200B') {\n findings.push({\n code: 'HIDDEN_ZERO_WIDTH_SPACE',\n severity: 'warning',\n message: 'ZERO WIDTH SPACE (U+200B) is hidden and can disguise identifiers, links, or filenames.',\n sourceRange,\n remediation: 'Remove it from identifiers and source-like content unless its use is explicitly required.'\n });\n }\n if ((character === '\\u200C' || character === '\\u200D')\n && isAsciiIdentifierCharacter(characters[codePointIndex - 1])\n && isAsciiIdentifierCharacter(characters[codePointIndex + 1])) {\n const name = character === '\\u200C' ? 'ZERO WIDTH NON-JOINER' : 'ZERO WIDTH JOINER';\n findings.push({\n code: 'HIDDEN_IDENTIFIER_JOINER',\n severity: 'warning',\n message: `${name} is hidden inside an ASCII identifier-like token.`,\n sourceRange,\n remediation: 'Remove the joiner from machine identifiers, or document and validate the identifier protocol that requires it.'\n });\n }\n if (character === '\\u2060') {\n findings.push({\n code: 'HIDDEN_WORD_JOINER',\n severity: 'info',\n message: 'WORD JOINER (U+2060) is invisible and can disguise token boundaries.',\n sourceRange,\n remediation: 'Confirm that non-breaking behavior is required; remove it from identifiers and source-like content.'\n });\n }\n // A leading U+FEFF can represent a decoded byte-order signature. The same\n // character midstream is invisible content and deserves an explicit finding.\n if (character === '\\uFEFF' && codePointIndex > 0) {\n findings.push({\n code: 'HIDDEN_MIDSTREAM_BOM',\n severity: 'warning',\n message: 'ZERO WIDTH NO-BREAK SPACE/BOM (U+FEFF) appears inside the text.',\n sourceRange,\n remediation: 'Remove the midstream BOM unless a documented protocol explicitly requires it.'\n });\n }\n utf16Index += character.length;\n }\n return findings;\n}\n\n/** Audits hidden bidi formatting without mutating the source string. */\nexport function scanBidiSecurity(\n text: string,\n options: { mode?: BidiSecurityMode } = {}\n): BidiSecurityReport {\n const mode = options.mode ?? 'audit';\n if (mode === 'off') return { mode, safe: true, shouldBlock: false, controls: [], findings: [] };\n const controls = findBidiControls(text);\n const findings = [\n ...controls.map(controlFinding),\n ...balanceFindings(text, controls),\n ...invisibleCharacterFindings(text)\n ].sort((a, b) => a.sourceRange.utf16.start - b.sourceRange.utf16.start || a.code.localeCompare(b.code));\n const hasHigh = findings.some((finding) => finding.severity === 'high');\n return {\n mode,\n safe: !hasHigh,\n shouldBlock: mode === 'strict' ? findings.length > 0 : mode === 'warn' && hasHigh,\n controls,\n findings\n };\n}\n\nexport interface SanitizeBidiControlsOptions {\n /** Remove controls with these risk levels. Defaults to every level. */\n remove?: BidiControlRisk[];\n /**\n * Remove only these semantic control groups. PDF follows embedding/override;\n * PDI follows isolate, so preserved isolate pairs stay structurally intact.\n */\n removeGroups?: BidiControlSanitizationGroup[];\n}\n\nconst ALL_SANITIZATION_GROUPS: readonly BidiControlSanitizationGroup[] = [\n 'mark', 'embedding-override', 'isolate', 'deprecated'\n];\n\nconst SANITIZATION_GROUP_RISK: Readonly> = {\n mark: 'low',\n 'embedding-override': 'high',\n isolate: 'medium',\n deprecated: 'medium'\n};\n\nfunction sanitizationGroup(codePoint: number, category: BidiControlFinding['category']): BidiControlSanitizationGroup {\n if (codePoint === 0x202c || category === 'embedding' || category === 'override') {\n return 'embedding-override';\n }\n if (codePoint === 0x2069 || category === 'isolate') return 'isolate';\n if (category === 'mark' || category === 'deprecated') return category;\n // Every recognized pop is handled above; keep an explicit defensive\n // fallback so future metadata cannot silently escape the default sanitizer.\n return 'deprecated';\n}\n\nexport function sanitizeBidiControls(\n text: string,\n options: SanitizeBidiControlsOptions = {}\n): { text: string; removed: BidiControlFinding[] } {\n const remove = new Set(options.remove ?? ['high', 'medium', 'low']);\n const removeGroups = new Set(options.removeGroups ?? ALL_SANITIZATION_GROUPS);\n const grouped = options.removeGroups !== undefined;\n const removed: BidiControlFinding[] = [];\n let output = '';\n let utf16Index = 0;\n let codePointIndex = 0;\n\n for (const character of text) {\n const codePoint = character.codePointAt(0)!;\n const metadata = CONTROL_METADATA.get(codePoint);\n const group = metadata && sanitizationGroup(codePoint, metadata.category);\n const selected = metadata && group && removeGroups.has(group)\n && remove.has(grouped ? SANITIZATION_GROUP_RISK[group] : metadata.risk);\n if (metadata && selected) {\n removed.push({\n character,\n codePoint: `U+${codePoint.toString(16).toUpperCase().padStart(4, '0')}`,\n index: utf16Index,\n end: utf16Index + character.length,\n codePointIndex,\n ...metadata\n });\n } else {\n output += character;\n }\n utf16Index += character.length;\n codePointIndex += 1;\n }\n\n return { text: output, removed };\n}\n", "import { classifyBidiStrongCharacter } from './classify.js';\nimport { findBidiControls } from './security.js';\nimport type { ResolvedDirection } from './types.js';\n\n/**\n * `auto` is the non-interference default: ordinary LTR content in an LTR\n * context receives no BidiLens markup or DOM mutation. `always` retains the\n * explicit-annotation behavior for integrations that require stable markers.\n */\nexport type BidiInterventionMode = 'auto' | 'always';\n\nexport interface BidiInterventionOptions {\n intervention?: BidiInterventionMode | undefined;\n inheritedDirection?: ResolvedDirection | undefined;\n}\n\n/**\n * Reports whether rendering metadata is needed for a string in its host\n * context. Hidden bidi controls deliberately disable the LTR fast path so an\n * apparently English string cannot bypass bidi-aware handling.\n */\nexport function needsBidiIntervention(\n text: string,\n options: BidiInterventionOptions = {}\n): boolean {\n if (options.intervention === 'always') return true;\n if (findBidiControls(text).length > 0) return true;\n\n let hasLtr = false;\n for (const character of text) {\n const direction = classifyBidiStrongCharacter(character);\n if (direction === 'rtl') return true;\n if (direction === 'ltr') hasLtr = true;\n }\n\n return options.inheritedDirection === 'rtl' && (hasLtr || text.length > 0);\n}\n", "import { classifyCharacter } from './classify.js';\nimport { isolateText } from './controls.js';\nimport { findTechnicalTokenRanges } from './detect.js';\nimport { needsBidiIntervention } from './intervention.js';\nimport type { BidiInterventionMode } from './intervention.js';\nimport type { Direction, DirectionalRun, InlineIsolation } from './types.js';\n\ntype PlannedIsolation = Omit;\n\nfunction attachSourceRanges(text: string, isolations: Omit[]): InlineIsolation[] {\n const codePointAtUtf16 = new Uint32Array(text.length + 1);\n let utf16Offset = 0;\n let codePointOffset = 0;\n for (const character of text) {\n codePointAtUtf16.fill(codePointOffset, utf16Offset, utf16Offset + character.length);\n utf16Offset += character.length;\n codePointOffset += 1;\n }\n codePointAtUtf16.fill(codePointOffset, utf16Offset);\n return isolations.map((isolation) => ({\n ...isolation,\n sourceRange: {\n utf16: { start: isolation.start, end: isolation.end },\n codePoint: {\n start: codePointAtUtf16[isolation.start]!,\n end: codePointAtUtf16[isolation.end]!\n }\n }\n }));\n}\n\nfunction resolveNeutralRuns(runs: DirectionalRun[]): DirectionalRun[] {\n const previousStrong: Direction[] = new Array(runs.length).fill('neutral');\n const nextStrong: Direction[] = new Array(runs.length).fill('neutral');\n let previous: Direction = 'neutral';\n let next: Direction = 'neutral';\n\n for (let index = 0; index < runs.length; index += 1) {\n previousStrong[index] = previous;\n const direction = runs[index]!.direction;\n if (direction !== 'neutral') previous = direction;\n }\n\n for (let index = runs.length - 1; index >= 0; index -= 1) {\n nextStrong[index] = next;\n const direction = runs[index]!.direction;\n if (direction !== 'neutral') next = direction;\n }\n\n return runs.map((run, index) => {\n if (run.direction !== 'neutral') return run;\n const before = previousStrong[index] ?? 'neutral';\n const after = nextStrong[index] ?? 'neutral';\n const direction: Direction = before === after && before !== 'neutral'\n ? before\n : before !== 'neutral'\n ? before\n : after;\n return { ...run, direction };\n });\n}\n\nfunction mergeAdjacent(runs: DirectionalRun[]): DirectionalRun[] {\n const merged: DirectionalRun[] = [];\n for (const run of runs) {\n const previous = merged.at(-1);\n if (previous && previous.direction === run.direction) {\n previous.text += run.text;\n previous.end = run.end;\n } else {\n merged.push({ ...run });\n }\n }\n return merged;\n}\n\nfunction trimNeutralBoundaries(text: string, start: number, end: number): { start: number; end: number } {\n while (start < end) {\n const character = text.slice(start).match(/^./su)?.[0];\n // Combining marks are bidi-neutral, but they are part of the preceding\n // grapheme. Trimming one from an isolate changes the visible word (for\n // example Persian `\u0645\u062B\u0644\u0627\u064B` became `\u0645\u062B\u0644\u0627` plus a detached tanwin), so marks\n // must anchor an isolation boundary just like a strong character.\n if (!character || classifyCharacter(character) !== 'neutral' || /^\\p{M}$/u.test(character)) break;\n start += character.length;\n }\n while (end > start) {\n const character = text.slice(0, end).match(/.$/su)?.[0];\n if (!character || classifyCharacter(character) !== 'neutral' || /^\\p{M}$/u.test(character)) break;\n end -= character.length;\n }\n return { start, end };\n}\n\nconst HARD_FRAGMENT_SEPARATOR = /[,\u060C;\u061B:!?\u061F|]/u;\n\n/**\n * Punctuation separates semantic LTR fragments in an RTL paragraph, while\n * whitespace joins adjacent fragments into one ordered phrase. Without this\n * normalization, two neighboring isolates such as `page` and `97` are\n * reordered as independent RTL atoms.\n */\nfunction normalizeIsolationPlan(text: string, isolations: PlannedIsolation[]): PlannedIsolation[] {\n const split: PlannedIsolation[] = [];\n for (const isolation of isolations) {\n if (isolation.kind !== 'opposite-direction-run') {\n split.push(isolation);\n continue;\n }\n let pieceStart = isolation.start;\n let cursor = isolation.start;\n for (const character of text.slice(isolation.start, isolation.end)) {\n const index = cursor;\n cursor += character.length;\n if (HARD_FRAGMENT_SEPARATOR.test(character)) {\n const trimmed = trimNeutralBoundaries(text, pieceStart, index);\n if (trimmed.start < trimmed.end) {\n split.push({\n ...isolation,\n text: text.slice(trimmed.start, trimmed.end),\n start: trimmed.start,\n end: trimmed.end\n });\n }\n pieceStart = cursor;\n }\n }\n const trimmed = trimNeutralBoundaries(text, pieceStart, isolation.end);\n if (trimmed.start < trimmed.end) {\n split.push({\n ...isolation,\n text: text.slice(trimmed.start, trimmed.end),\n start: trimmed.start,\n end: trimmed.end\n });\n }\n }\n\n const ordered = split.sort((a, b) => a.start - b.start || a.end - b.end);\n const merged: PlannedIsolation[] = [];\n for (const isolation of ordered) {\n const previous = merged.at(-1);\n if (\n previous &&\n previous.direction === isolation.direction &&\n previous.end <= isolation.start &&\n /^\\s*$/u.test(text.slice(previous.end, isolation.start))\n ) {\n previous.end = isolation.end;\n previous.text = text.slice(previous.start, previous.end);\n if (previous.kind !== isolation.kind) previous.kind = 'opposite-direction-run';\n } else {\n merged.push({ ...isolation });\n }\n }\n return merged;\n}\n\nexport function segmentDirectionalRuns(text: string): DirectionalRun[] {\n if (!text) return [];\n const runs: DirectionalRun[] = [];\n let currentDirection: Direction | null = null;\n let currentText = '';\n let start = 0;\n let index = 0;\n\n for (const character of text) {\n const direction = classifyCharacter(character);\n if (currentDirection === null) {\n currentDirection = direction;\n currentText = character;\n start = index;\n } else if (direction === currentDirection) {\n currentText += character;\n } else {\n runs.push({ text: currentText, direction: currentDirection, start, end: index });\n currentDirection = direction;\n currentText = character;\n start = index;\n }\n index += character.length;\n }\n\n if (currentDirection !== null) {\n runs.push({ text: currentText, direction: currentDirection, start, end: index });\n }\n\n return mergeAdjacent(resolveNeutralRuns(runs));\n}\n\nexport function isolateDirectionalRuns(text: string): string {\n return segmentDirectionalRuns(text)\n .map((run) => isolateText(run.text, run.direction))\n .join('');\n}\n\n/**\n * Plans semantic inline boundaries without changing the stored source text.\n * Technical ranges are isolated first; opposite natural-language runs are\n * then isolated only when they differ from the block's base direction.\n */\nexport function planInlineIsolation(\n text: string,\n blockDirection: Exclude,\n options: {\n excludeTechnicalTokens?: boolean;\n isolateOppositeRuns?: boolean;\n intervention?: BidiInterventionMode | undefined;\n technicalIdentifiers?: readonly string[] | undefined;\n } = {}\n): InlineIsolation[] {\n if (!needsBidiIntervention(text, {\n intervention: options.intervention,\n inheritedDirection: blockDirection\n })) return [];\n const technical = options.excludeTechnicalTokens === false\n ? []\n : findTechnicalTokenRanges(text, options.technicalIdentifiers);\n const isolations: Omit[] = technical.map((range) => ({\n text: range.text,\n direction: 'ltr',\n start: range.start,\n end: range.end,\n kind: range.kind\n }));\n\n if (options.isolateOppositeRuns === false) {\n return attachSourceRanges(text, normalizeIsolationPlan(text, isolations));\n }\n\n let technicalIndex = 0;\n for (const run of segmentDirectionalRuns(text)) {\n if (run.direction === 'neutral' || run.direction === blockDirection) continue;\n while (technicalIndex < technical.length && technical[technicalIndex]!.end <= run.start) {\n technicalIndex += 1;\n }\n let cursor = run.start;\n for (let index = technicalIndex; index < technical.length; index += 1) {\n const range = technical[index]!;\n if (range.end <= cursor) continue;\n if (range.start >= run.end) break;\n const partEnd = Math.min(range.start, run.end);\n if (cursor < partEnd) {\n const trimmed = trimNeutralBoundaries(text, cursor, partEnd);\n if (trimmed.start < trimmed.end) isolations.push({\n text: text.slice(trimmed.start, trimmed.end),\n direction: run.direction,\n start: trimmed.start,\n end: trimmed.end,\n kind: 'opposite-direction-run'\n });\n }\n cursor = Math.max(cursor, range.end);\n if (cursor >= run.end) break;\n }\n if (cursor < run.end) {\n const trimmed = trimNeutralBoundaries(text, cursor, run.end);\n if (trimmed.start < trimmed.end) isolations.push({\n text: text.slice(trimmed.start, trimmed.end),\n direction: run.direction,\n start: trimmed.start,\n end: trimmed.end,\n kind: 'opposite-direction-run'\n });\n }\n }\n\n return attachSourceRanges(text, normalizeIsolationPlan(text, isolations));\n}\n", "import {\n analyzeText,\n needsBidiIntervention,\n planInlineIsolation,\n type BidiInterventionMode,\n type DetectionOptions,\n type ResolvedDirection,\n type TextAnalysis\n} from '@bidilens/core';\n\nexport interface RenderHtmlOptions extends DetectionOptions {\n blockTag?: string;\n containerTag?: string | false;\n blockClassName?: string;\n containerClassName?: string;\n includeDataAttributes?: boolean;\n /** Skip BidiLens markup for LTR-only text in an LTR context. */\n intervention?: BidiInterventionMode;\n}\n\nexport interface RenderedHtmlBlock {\n text: string;\n html: string;\n direction: ResolvedDirection;\n start: number;\n end: number;\n}\n\nexport interface RenderedBidiHtml {\n source: string;\n html: string;\n analysis: TextAnalysis;\n blocks: RenderedHtmlBlock[];\n}\n\nconst SAFE_TAG = /^[a-z][a-z0-9-]*$/u;\nconst SAFE_BLOCK_TAGS = new Set([\n 'address', 'article', 'aside', 'blockquote', 'dd', 'div', 'dt', 'figcaption',\n 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'main', 'nav',\n 'p', 'pre', 'section', 'span', 'td', 'th'\n]);\nconst SAFE_CONTAINER_TAGS = new Set([\n 'article', 'aside', 'blockquote', 'div', 'footer', 'header', 'main', 'nav', 'section', 'span'\n]);\n\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/gu, (character) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": '''\n }[character] ?? character));\n}\n\nfunction checkedTag(value: string, option: string, allowed: ReadonlySet): string {\n const normalized = value.toLowerCase();\n if (!SAFE_TAG.test(normalized) || !allowed.has(normalized)) {\n throw new Error(`${option} must be an allowed non-executable HTML container tag.`);\n }\n return normalized;\n}\n\nfunction classAttribute(value: string | undefined): string {\n return value ? ` class=\"${escapeHtml(value)}\"` : '';\n}\n\nexport function renderInlineBidiHtml(\n source: string,\n direction: ResolvedDirection,\n options: {\n includeDataAttributes?: boolean;\n intervention?: BidiInterventionMode | undefined;\n technicalIdentifiers?: readonly string[] | undefined;\n } = {}\n): string {\n const includeData = options.includeDataAttributes ?? true;\n const isolations = planInlineIsolation(source, direction, {\n intervention: options.intervention,\n technicalIdentifiers: options.technicalIdentifiers\n });\n let html = '';\n let cursor = 0;\n for (const isolation of isolations) {\n html += escapeHtml(source.slice(cursor, isolation.start));\n const tag = isolation.kind === 'code' ? 'code' : 'bdi';\n const data = includeData\n ? ` data-bidilens-isolate=\"\" data-bidilens-kind=\"${isolation.kind}\"${isolation.kind === 'code' ? ' data-bidilens-code=\"\"' : ''}`\n : '';\n html += `<${tag} dir=\"${isolation.direction}\"${data}>${escapeHtml(isolation.text)}`;\n cursor = isolation.end;\n }\n return html + escapeHtml(source.slice(cursor));\n}\n\n/** Serializes untrusted plain text; it never accepts or emits unescaped source HTML. */\nexport function renderBidiHtml(source: string, options: RenderHtmlOptions = {}): RenderedBidiHtml {\n const detection: DetectionOptions = {\n ...options,\n fallback: options.fallback ?? options.inheritedDirection ?? 'ltr'\n };\n const analysis = analyzeText(source, detection);\n const blockTag = checkedTag(options.blockTag ?? 'p', 'blockTag', SAFE_BLOCK_TAGS);\n const includeData = options.includeDataAttributes ?? true;\n const intervene = analysis.paragraphs.some((paragraph) => paragraph.direction === 'rtl')\n || needsBidiIntervention(source, {\n intervention: options.intervention,\n inheritedDirection: options.inheritedDirection\n });\n const blocks = analysis.paragraphs.map((paragraph) => {\n const direction = paragraph.direction === 'neutral'\n ? (options.inheritedDirection ?? 'ltr')\n : paragraph.direction;\n const data = intervene && includeData ? ' data-bidilens-block=\"\"' : '';\n const directionAttribute = intervene ? ` dir=\"${direction}\"` : '';\n const blockClass = classAttribute(options.blockClassName);\n const inline = intervene\n ? renderInlineBidiHtml(paragraph.text, direction, {\n includeDataAttributes: includeData,\n intervention: options.intervention,\n technicalIdentifiers: options.technicalIdentifiers\n })\n : escapeHtml(paragraph.text);\n const html = `<${blockTag}${directionAttribute}${data}${blockClass}>${inline}`;\n return { text: paragraph.text, html, direction, start: paragraph.start, end: paragraph.end };\n });\n\n const serializedBlocks = blocks.map((block, index) => {\n const next = blocks[index + 1];\n const separator = next ? source.slice(block.end, next.start) : '';\n return `${block.html}${escapeHtml(separator)}`;\n }).join('');\n const automaticContainer = blocks.length > 1 ? 'div' : false;\n const container = options.containerTag === undefined ? automaticContainer : options.containerTag;\n const html = container === false\n ? serializedBlocks\n : (() => {\n const tag = checkedTag(container, 'containerTag', SAFE_CONTAINER_TAGS);\n const data = intervene && includeData ? ' data-bidilens-document=\"\"' : '';\n const containerClass = classAttribute(options.containerClassName);\n return `<${tag}${data}${containerClass}>${serializedBlocks}`;\n })();\n return { source, html, analysis, blocks };\n}\n", "{\n \"name\": \"@bidilens/cli\",\n \"version\": \"0.3.1\",\n \"description\": \"CLI for inspecting direction and auditing hidden Unicode bidi controls.\",\n \"license\": \"MIT\",\n \"author\": {\n \"name\": \"Shayan SalehiRad\",\n \"url\": \"https://github.com/CodeinScrubs\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/CodeinScrubs/BidiLens.git\",\n \"directory\": \"packages/cli\"\n },\n \"homepage\": \"https://github.com/CodeinScrubs/BidiLens#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/CodeinScrubs/BidiLens/issues\"\n },\n \"type\": \"module\",\n \"sideEffects\": false,\n \"keywords\": [\n \"bidi\",\n \"rtl\",\n \"ltr\",\n \"unicode\",\n \"cli\",\n \"security\"\n ],\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\",\n \"CHANGELOG.md\",\n \"THIRD_PARTY_NOTICES.md\",\n \"corpus\",\n \"examples\"\n ],\n \"bin\": {\n \"bidilens\": \"./dist/bin.js\"\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/bin.ts --format esm --dts --clean --sourcemap\",\n \"prepack\": \"pnpm run build\",\n \"example\": \"node examples/basic.mjs\"\n },\n \"dependencies\": {\n \"@bidilens/core\": \"workspace:*\",\n \"@bidilens/html\": \"workspace:*\",\n \"commander\": \"^15.0.0\"\n },\n \"devDependencies\": {\n \"tsup\": \"^8.5.1\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"], + "mappings": "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AA,EAAM;AAAA,EACN;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAU;AACZ;AAEO,IAAM,wBAA+C;AAAA,EAC1D;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAO;AAAA,EACP;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAQ;AAAA,EACR;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT;AAAA,EAAS;AAAA,EACT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", "names": ["import_node_process", "import_promises", "import_node_path", "import_node_process", "import_node_path", "import_node_process", "import_node_util", "cmd", "choice", "line", "str", "process", "fs", "path", "childProcess", "option", "line", "lineStart", "trimmed", "html", "process", "input", "program", "process", "path", "process"] } diff --git a/android/README.md b/android/README.md index a6233ad..edc0f93 100644 --- a/android/README.md +++ b/android/README.md @@ -176,7 +176,7 @@ pnpm run android:check Current executable evidence includes: - all 932 canonical direction fixtures and declared isolation plans in Kotlin; -- 23 core, 9 Views/Robolectric, and 8 Compose JVM tests; +- 29 core, 11 Views/Robolectric, and 9 Compose JVM tests; - 3 Views and 3 Compose UI tests on an Android 16/API 36.1 emulator; - release AAR assembly, sample APK assembly, and Android lint; - an isolated consumer build against the generated Maven-local coordinates; diff --git a/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiAnalyzer.kt b/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiAnalyzer.kt index 9e38cc2..f80e583 100644 --- a/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiAnalyzer.kt +++ b/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiAnalyzer.kt @@ -121,10 +121,12 @@ private fun analyzeParagraph( ) } +private val defaultParagraphSeparator = Regex("\\r\\n|\\n|\\r|\\u0085|[\\u001C-\\u001E]|\\u2029") + private fun splitParagraphs(text: String): List> { val result = mutableListOf>() var start = 0 - for (match in Regex("\\r\\n|\\n|\\r|\\u2029").findAll(text)) { + for (match in defaultParagraphSeparator.findAll(text)) { result += text.substring(start, match.range.first) to start start = match.range.last + 1 } diff --git a/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiSecurity.kt b/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiSecurity.kt index f8ea14e..bc225c2 100644 --- a/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiSecurity.kt +++ b/android/core/src/main/kotlin/io/github/codeinscrubs/bidilens/core/BidiSecurity.kt @@ -78,39 +78,28 @@ private fun BidiControlFinding.range() = BidiSourceRange( codePointEnd = codePointIndex + 1, ) -fun scanBidiSecurity(text: String): BidiSecurityReport { - val controls = findBidiControls(text) +private data class FormattingFrame(val isolate: Boolean, val finding: BidiControlFinding) + +private fun balanceParagraph( + controls: List, + boundary: String, +): List { val findings = mutableListOf() - data class Frame(val isolate: Boolean, val finding: BidiControlFinding) - val stack = mutableListOf() + val stack = mutableListOf() for (control in controls) { - val code = control.character.codePointAt(0) - findings += BidiSecurityFinding( - code = when (control.category) { - BidiControlCategory.OVERRIDE -> "BIDI_OVERRIDE_CONTROL" - BidiControlCategory.EMBEDDING -> "BIDI_EMBEDDING_CONTROL" - BidiControlCategory.ISOLATE -> "BIDI_ISOLATE_CONTROL" - BidiControlCategory.MARK -> "BIDI_DIRECTIONAL_MARK" - BidiControlCategory.DEPRECATED -> "BIDI_DEPRECATED_CONTROL" - BidiControlCategory.POP -> "BIDI_POP_CONTROL" - }, - message = "${control.name} (${control.codePoint}) is invisible and changes bidirectional interpretation.", - range = control.range(), - risk = control.risk, - ) - when (code) { - 0x202A, 0x202B, 0x202D, 0x202E -> stack += Frame(false, control) - 0x2066, 0x2067, 0x2068 -> stack += Frame(true, control) + when (val code = control.character.codePointAt(0)) { + 0x202A, 0x202B, 0x202D, 0x202E -> stack += FormattingFrame(false, control) + 0x2066, 0x2067, 0x2068 -> stack += FormattingFrame(true, control) 0x202C -> { val embedding = stack.indexOfLast { !it.isolate } val isolate = stack.indexOfLast { it.isolate } if (embedding <= isolate) { findings += BidiSecurityFinding( - "BIDI_UNMATCHED_PDF", - "POP DIRECTIONAL FORMATTING has no matching active embedding or override.", - control.range(), - BidiControlRisk.HIGH, + code = "BIDI_UNMATCHED_PDF", + message = "POP DIRECTIONAL FORMATTING has no matching active embedding or override.", + range = control.range(), + risk = BidiControlRisk.HIGH, ) } else { stack.removeAt(embedding) @@ -120,33 +109,72 @@ fun scanBidiSecurity(text: String): BidiSecurityReport { val isolate = stack.indexOfLast { it.isolate } if (isolate < 0) { findings += BidiSecurityFinding( - "BIDI_UNMATCHED_PDI", - "POP DIRECTIONAL ISOLATE has no matching isolate opener.", - control.range(), - BidiControlRisk.HIGH, + code = "BIDI_UNMATCHED_PDI", + message = "POP DIRECTIONAL ISOLATE has no matching isolate opener.", + range = control.range(), + risk = BidiControlRisk.HIGH, ) } else { for (frame in stack.drop(isolate + 1).filterNot { it.isolate }) { findings += BidiSecurityFinding( - "BIDI_FORMAT_CROSSES_ISOLATE_BOUNDARY", - "${frame.finding.name} is not closed before the containing isolate ends.", - frame.finding.range(), - BidiControlRisk.HIGH, + code = "BIDI_FORMAT_CROSSES_ISOLATE_BOUNDARY", + message = "${frame.finding.name} is not closed before the containing isolate ends.", + range = frame.finding.range(), + risk = BidiControlRisk.HIGH, ) } while (stack.size > isolate) stack.removeAt(stack.lastIndex) } } + else -> Unit } } for (frame in stack) { findings += BidiSecurityFinding( - if (frame.isolate) "BIDI_UNCLOSED_ISOLATE" else "BIDI_UNCLOSED_EMBEDDING", - "${frame.finding.name} is not terminated before the end of the text.", - frame.finding.range(), - BidiControlRisk.HIGH, + code = if (frame.isolate) "BIDI_UNCLOSED_ISOLATE" else "BIDI_UNCLOSED_EMBEDDING", + message = "${frame.finding.name} is not terminated before $boundary.", + range = frame.finding.range(), + risk = BidiControlRisk.HIGH, ) } + return findings +} + +private fun balanceFindings(text: String, controls: List): List { + val findings = mutableListOf() + val separator = Regex("\\r\\n|\\n|\\r|\\u0085|[\\u001C-\\u001E]|\\u2029") + var controlIndex = 0 + for (match in separator.findAll(text)) { + val paragraphControls = mutableListOf() + while (controlIndex < controls.size && controls[controlIndex].utf16Start < match.range.first) { + paragraphControls += controls[controlIndex] + controlIndex += 1 + } + findings += balanceParagraph(paragraphControls, "the paragraph boundary") + } + findings += balanceParagraph(controls.drop(controlIndex), "the end of the text") + return findings +} + +fun scanBidiSecurity(text: String): BidiSecurityReport { + val controls = findBidiControls(text) + val findings = controls.map { control -> + BidiSecurityFinding( + code = when (control.category) { + BidiControlCategory.OVERRIDE -> "BIDI_OVERRIDE_CONTROL" + BidiControlCategory.EMBEDDING -> "BIDI_EMBEDDING_CONTROL" + BidiControlCategory.ISOLATE -> "BIDI_ISOLATE_CONTROL" + BidiControlCategory.MARK -> "BIDI_DIRECTIONAL_MARK" + BidiControlCategory.DEPRECATED -> "BIDI_DEPRECATED_CONTROL" + BidiControlCategory.POP -> "BIDI_POP_CONTROL" + }, + message = "${control.name} (${control.codePoint}) is invisible and changes bidirectional interpretation.", + range = control.range(), + risk = control.risk, + ) + }.toMutableList() + findings += balanceFindings(text, controls) + val sorted = findings.sortedWith(compareBy { it.range.utf16Start }.thenBy { it.code }) return BidiSecurityReport( safe = sorted.none { it.risk == BidiControlRisk.HIGH }, diff --git a/android/core/src/test/kotlin/io/github/codeinscrubs/bidilens/core/BidiCoreTest.kt b/android/core/src/test/kotlin/io/github/codeinscrubs/bidilens/core/BidiCoreTest.kt index 6d3d537..cf8dbdc 100644 --- a/android/core/src/test/kotlin/io/github/codeinscrubs/bidilens/core/BidiCoreTest.kt +++ b/android/core/src/test/kotlin/io/github/codeinscrubs/bidilens/core/BidiCoreTest.kt @@ -163,6 +163,26 @@ class BidiCoreTest { assertEquals(source.indexOf('\n') + 1, analysis.paragraphs[1].utf16Start) } + @Test + fun allUnicodeParagraphSeparatorsSplitAnalysisWithoutChangingSource() { + listOf( + "NEL" to "\u0085", + "FILE SEPARATOR" to "\u001C", + "GROUP SEPARATOR" to "\u001D", + "RECORD SEPARATOR" to "\u001E", + "PARAGRAPH SEPARATOR" to "\u2029", + ).forEach { (name, separator) -> + val source = "Hello${separator}سلام" + val analysis = analyzeBidi(source) + assertEquals("wrong paragraph count for $name", 2, analysis.paragraphs.size) + assertEquals("Hello", analysis.paragraphs[0].text) + assertEquals("سلام", analysis.paragraphs[1].text) + assertEquals(BidiDirection.LTR, analysis.paragraphs[0].direction) + assertEquals(BidiDirection.RTL, analysis.paragraphs[1].direction) + assertEquals(source, analysis.text) + } + } + @Test fun isolationCarriesUtf16AndCodePointOffsets() { val source = "😀 React یک کتابخانه است." @@ -207,6 +227,50 @@ class BidiCoreTest { assertTrue(report.findings.any { it.code == "BIDI_UNMATCHED_PDI" }) } + @Test + fun formattingControlsDoNotBalanceAcrossParagraphBoundaries() { + listOf( + "LF" to "\n", + "CR" to "\r", + "CRLF" to "\r\n", + "NEL" to "\u0085", + "FILE SEPARATOR" to "\u001C", + "GROUP SEPARATOR" to "\u001D", + "RECORD SEPARATOR" to "\u001E", + "PARAGRAPH SEPARATOR" to "\u2029", + ).forEach { (name, separator) -> + val report = scanBidiSecurity( + "${BidiControls.RLO}before${separator}after${BidiControls.PDF}", + ) + val codes = report.findings.map { it.code } + assertTrue("missing unclosed embedding for $name", codes.contains("BIDI_UNCLOSED_EMBEDDING")) + assertTrue("missing unmatched PDF for $name", codes.contains("BIDI_UNMATCHED_PDF")) + } + } + + @Test + fun formattingControlsBalanceWithinOneParagraph() { + val report = scanBidiSecurity("before${BidiControls.RLO}inside${BidiControls.PDF}after") + assertFalse(report.findings.any { it.code == "BIDI_UNCLOSED_EMBEDDING" }) + assertFalse(report.findings.any { it.code == "BIDI_UNMATCHED_PDF" }) + } + + @Test + fun isolatesDoNotBalanceAcrossParagraphBoundaries() { + val report = scanBidiSecurity( + "${BidiControls.RLI}before\u2029after${BidiControls.PDI}", + ) + assertTrue(report.findings.any { it.code == "BIDI_UNCLOSED_ISOLATE" }) + assertTrue(report.findings.any { it.code == "BIDI_UNMATCHED_PDI" }) + } + + @Test + fun isolatesBalanceWithinOneParagraph() { + val report = scanBidiSecurity("${BidiControls.RLI}inside${BidiControls.PDI}") + assertFalse(report.findings.any { it.code == "BIDI_UNCLOSED_ISOLATE" }) + assertFalse(report.findings.any { it.code == "BIDI_UNMATCHED_PDI" }) + } + @Test fun ordinaryPersianZwnjIsNotReportedAsBidiControl() { val report = scanBidiSecurity("می\u200Cشود") diff --git a/apps/demo/package.json b/apps/demo/package.json index 3d83534..9e1db75 100644 --- a/apps/demo/package.json +++ b/apps/demo/package.json @@ -11,7 +11,7 @@ "@bidilens/core": "workspace:*", "@bidilens/markdown": "workspace:*", "@bidilens/react": "workspace:*", - "markdown-it": "^14.1.0", + "markdown-it": "^15.0.1", "react": "^19.2.8", "react-dom": "^19.2.8", "react-markdown": "^10.1.0", @@ -20,7 +20,6 @@ "unified": "^11.0.5" }, "devDependencies": { - "@types/markdown-it": "^14.1.2", "@vitejs/plugin-react": "^6.0.5", "vite": "^8.2.1" } diff --git a/apps/demo/src/App.tsx b/apps/demo/src/App.tsx index dd70cfa..1a4308e 100644 --- a/apps/demo/src/App.tsx +++ b/apps/demo/src/App.tsx @@ -12,6 +12,7 @@ import { } from '@bidilens/core'; import { markdownItBidi, rehypeBidi, remarkBidi } from '@bidilens/markdown'; import { BidiCode, BidiIsolate, BidiMessage, StreamingBidiMessage } from '@bidilens/react'; +import demoManifest from '../package.json' with { type: 'json' }; import corpusUrl from '../../../corpus/cases.json?url'; type UiLanguage = 'en' | 'fa'; @@ -84,7 +85,7 @@ const PRESETS = [ const COPY = { en: { - product: 'BidiLens v0.1.1', + product: `BidiLens v${demoManifest.version}`, headline: 'Mixed-direction text that stays readable while AI streams.', intro: 'Standards-based direction detection, Markdown annotation, inline isolation, and hidden-control auditing.', direction: 'Direction', confidence: 'Confidence', counts: 'RTL / LTR', controls: 'Hidden controls', @@ -102,7 +103,10 @@ const COPY = { share: 'Copy share link', exportJson: 'Export JSON', exportHtml: 'Export semantic HTML', verifyCopy: 'Verify logical copy', comparison: 'Live four-way comparison', comparisonHelp: 'The current immutable input under four base-direction approaches.', browser: 'Browser default', naive: 'Naive global RTL', auto: 'dir=auto', toolkit: 'BidiLens content-majority', - corpus: 'Offline corpus browser', corpusHelp: 'Search all 928 bundled cases and load one into the playground.', + corpus: 'Offline corpus browser', + corpusHelp: (count: number) => count > 0 + ? `Search all ${count.toLocaleString('en-US')} bundled cases and load one into the playground.` + : 'Loading the bundled corpus…', corpusSearch: 'Search fixture ID, description, tag, or text', load: 'Load', reviewed: 'native reviewed', primitives: 'Isolation primitives', primitivesHelp: 'Identifiers remain readable inside RTL prose.', language: 'فارسی', theme: 'Dark theme', @@ -113,7 +117,7 @@ const COPY = { copyFailed: 'Logical copy verification failed.' }, fa: { - product: 'BidiLens نسخهٔ ۰٫۱٫۰', + product: `BidiLens نسخهٔ ${demoManifest.version.replaceAll('.', '٫').replace(/\d/gu, (digit) => '۰۱۲۳۴۵۶۷۸۹'[Number(digit)]!)}`, headline: 'متن دوجهته‌ای که هنگام پخش پاسخ هوش مصنوعی خوانا می‌ماند.', intro: 'تشخیص جهت بر پایهٔ استاندارد، نشانه‌گذاری Markdown، ایزوله‌سازی درون‌خطی و ممیزی نویسه‌های پنهان.', direction: 'جهت', confidence: 'اطمینان', counts: 'RTL / LTR', controls: 'نویسهٔ پنهان', @@ -131,7 +135,10 @@ const COPY = { share: 'کپی پیوند اشتراک', exportJson: 'خروجی JSON', exportHtml: 'خروجی HTML معنایی', verifyCopy: 'بررسی کپی منطقی', comparison: 'مقایسهٔ زندهٔ چهارتایی', comparisonHelp: 'ورودی تغییرناپذیر فعلی با چهار روش تعیین جهت پایه.', browser: 'پیش‌فرض مرورگر', naive: 'RTL سراسری ساده‌لوحانه', auto: 'dir=auto', toolkit: 'BidiLens با محتوای غالب', - corpus: 'مرورگر آفلاین پیکره', corpusHelp: 'در هر ۹۱۸ نمونه جست‌وجو کنید و یکی را در محیط بارگذاری کنید.', + corpus: 'مرورگر آفلاین پیکره', + corpusHelp: (count: number) => count > 0 + ? `در هر ${count.toLocaleString('fa-IR')} نمونه جست‌وجو کنید و یکی را در محیط بارگذاری کنید.` + : 'در حال بارگذاری پیکرهٔ همراه…', corpusSearch: 'جست‌وجوی شناسه، توضیح، برچسب یا متن', load: 'بارگذاری', reviewed: 'بازبینی بومی', primitives: 'اجزای ایزوله‌سازی', primitivesHelp: 'شناسه‌ها در متن RTL خوانا می‌مانند.', language: 'English', theme: 'پوستهٔ تیره', @@ -387,7 +394,7 @@ export function App() {
-
{t.corpus}{t.corpusHelp}
setCorpusQuery(event.target.value)} />
+
{t.corpus}{t.corpusHelp(corpus.length)}
setCorpusQuery(event.target.value)} />
{filteredCorpus.map((fixture) =>
{fixture.id}{fixture.expected}
{fixture.description} · {fixture.tags.join(', ')}{fixture.nativeSpeakerReviewed ? ` · ${t.reviewed}` : ''}
)}
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 335d146..6b99025 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -99,12 +99,15 @@ its low half, a non-low successor, paragraph completion, or `finish()` arrives; this keeps live decisions invariant even when callers split a supplementary Unicode character between code units. -The optimized default newline separator completes paragraphs incrementally. -Custom JavaScript regular expressions are evaluated once at `finish()` because -an arbitrary match may depend on future input through lookarounds, anchors, or -an extendable match. Before finalization, the unresolved custom-separated -source remains one open paragraph. This explicit tradeoff preserves arbitrary -chunk-boundary invariance and linear append behavior. +The optimized default separator completes paragraphs incrementally for the +complete Unicode 17 `Bidi_Class=Paragraph_Separator` set: CR, LF, CRLF, NEL, +U+001C–U+001E, and U+2029. U+2028 is a line separator (`WS`) and therefore stays +inside the current bidi paragraph. Custom JavaScript regular expressions are +evaluated once at `finish()` because an arbitrary match may depend on future +input through lookarounds, anchors, or an extendable match. Before finalization, +the unresolved custom-separated source remains one open paragraph. This +explicit tradeoff preserves arbitrary chunk-boundary invariance and linear +append behavior. Framework streaming APIs are adapters over the same state machine: diff --git a/docs/FAQ.md b/docs/FAQ.md index 5dab502..6cc4ff7 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -76,6 +76,9 @@ CommonJS. Provide the exact logical source, expected base direction, numbered words, technical tokens, language/script, host renderer, and a minimal screenshot. Add a corpus fixture and policy regression test; do not patch the stored order. +The repository's current mixed Persian/English medical examples and their +acceptance invariants are collected in the +[screenshot regression cases](SCREENSHOT_CASES.md). ## Where are Android, Apple, Windows, Rust, Flutter, React Native, VS Code, Electron, and PDF? diff --git a/docs/LIMITATIONS.md b/docs/LIMITATIONS.md index 48bbd12..efbf706 100644 --- a/docs/LIMITATIONS.md +++ b/docs/LIMITATIONS.md @@ -42,7 +42,15 @@ deliberately checkpointed by source growth and structural boundaries; inspect `pendingSourceRange` before treating a live `document` as current. `finish()` is the exact batch-equivalence boundary. Unified/remark/rehype transforms remain supported as batch plugins, not as a -stateful unified streaming backend. +stateful unified streaming backend. The adapter source is built against +Markdown-It 15, and the compatibility matrix exercises representative +Markdown-It releases 13.0.2, 14.3.1, and 15.0.1 with packed strict TypeScript +consumers. The peer range covers 13.x, 14.x, and 15.x, but the matrix does not +claim every patch release. Markdown-It 15's host parser may +intentionally produce different linkification HTML because its upstream +`linkify-it` major changed, while BidiLens semantic block/isolation/security +reports remain equivalent. Other parser major versions are not a supported or +tested claim. ## Validation boundaries @@ -73,9 +81,10 @@ stateful unified streaming backend. - source and all 12 JavaScript packages are public, but no downstream production deployment or company adoption is claimed. -Public issues, discussions, and an unmerged integration pull request are listed -in the [outreach log](OUTREACH_LOG.md). They prove that review was requested, -not that any host validated, merged, deployed, or endorsed BidiLens. +Public issues, discussions, and integration pull requests are listed in the +[outreach log](OUTREACH_LOG.md). One native implementation merged in Streamdown; +the remaining open submissions prove that review was requested, not that any +host adopted the BidiLens dependency, deployed it, or endorsed BidiLens. ## Compatibility diff --git a/docs/OUTREACH_LOG.md b/docs/OUTREACH_LOG.md index c54730d..08c312f 100644 --- a/docs/OUTREACH_LOG.md +++ b/docs/OUTREACH_LOG.md @@ -2,7 +2,7 @@ **Initial outreach evidence date:** 2026-07-30 -**Last response audit:** 2026-08-13 +**Last response audit:** 2026-09-01 This log records public requests for review and bounded organizational role-address outreach. Public routes are independently link-verifiable; email @@ -39,19 +39,19 @@ endorsement. | OpenAI Codex CLI | [comment on issue #34871](https://github.com/openai/codex/issues/34871#issuecomment-5088082730) | Parent issue open | Separates bidi ordering from Arabic shaping and terminal capabilities. It offers the policy/corpus for a native Rust design rather than proposing a JavaScript dependency. | | OpenAI Codex community | [Show and tell #35557](https://github.com/openai/codex/discussions/35557) | Open | Public technical introduction, package/corpus summary, current integration evidence, limitations, and request for renderer/i18n review. | | Cline | [comment on feature discussion #12089](https://github.com/cline/cline/discussions/12089#discussioncomment-17793649) | Discussion open | Links the open renderer regression, supplies the mixed-content acceptance case, and offers a React/webview pilot or fixtures-only patch. | -| Cline VS Code webview | [PR #12724](https://github.com/cline/cline/pull/12724) | Open, mergeable, and ready for review; all fresh hosted checks passed on the rebased head; maintainer review required | Applies `@bidilens/markdown` at the existing React Markdown render boundary and adds Persian-majority, English-majority, and pure-English identity tests. Quality, unit, platform-integration, VS Code on Ubuntu/Windows, E2E on Ubuntu/macOS/Windows, and both Socket security checks passed on 2026-08-13. | +| Cline VS Code webview | [PR #12724](https://github.com/cline/cline/pull/12724) | Open but currently conflicting/dirty; hosted checks on the current head pass, and maintainer review is still required | Applies `@bidilens/markdown` at the existing React Markdown render boundary and adds Persian-majority, English-majority, and pure-English identity tests. Quality, unit, platform-integration, VS Code on Ubuntu/Windows, E2E on Ubuntu/macOS/Windows, and both Socket security checks passed; the branch needs an upstream conflict-resolution update before it can merge. | | Continue | [comment on issue #2767](https://github.com/continuedev/continue/issues/2767#issuecomment-5088124777) | Parent issue closed; reconsideration requested | Replaces the proposed global RTL rule with Auto/LTR/RTL policy and offers a focused GUI or fixtures-only patch. No new duplicate issue was created. | | assistant-ui | [Show and tell #5211](https://github.com/assistant-ui/assistant-ui/discussions/5211) | Open | Distinguishes the project's completed logical-layout work from per-message mixed-content direction and offers a documented `@bidilens/react` streaming recipe, adapter, hook, or fixtures-only path. | -| AnythingLLM | [comment on canonical RTL issue #3430](https://github.com/Mintplex-Labs/anything-llm/issues/3430#issuecomment-5126056699) | Parent issue open | Supplies a per-block acceptance fixture and integration guidance. A direct dependency patch was deferred because the host supports Node 18 and Markdown-It 13 while BidiLens 0.3 requires Node 22.12 and peers with Markdown-It 14; raising either compatibility floor would be a regression. | -| Vercel Streamdown | [PR #569](https://github.com/vercel/streamdown/pull/569) | Open, mergeable, and ready for review; review and security automation passed; maintainer review required | Adds a dependency-free native rehype pass because Streamdown supports Node 18. It assigns direction per semantic block, keeps code LTR, uses content majority with a first-strong tie-breaker, preserves pure-LTR behavior, and includes 985 passing package tests plus a production ESM/declaration build. The Vercel preview remains blocked on external-fork deployment authorization. | +| AnythingLLM | [comment on canonical RTL issue #3430](https://github.com/Mintplex-Labs/anything-llm/issues/3430#issuecomment-5126056699) | Parent issue open | Supplies a per-block acceptance fixture and integration guidance. [BidiLens PR #57](https://github.com/CodeinScrubs/BidiLens/pull/57) addresses the Markdown-It 13/14/15 peer/type gap with packed cross-version evidence, but AnythingLLM's Node 18 floor still conflicts with BidiLens 0.3's Node 22.12 minimum; a native fixtures-only patch remains the non-regressive route unless that runtime boundary changes. | +| Vercel Streamdown | [PR #569](https://github.com/vercel/streamdown/pull/569) | Merged on 2026-08-14 after maintainer approval; no downstream adoption claim is inferred | Adds a dependency-free native rehype pass because Streamdown supports Node 18. It assigns direction per semantic block, keeps code LTR, uses content majority with a first-strong tie-breaker, preserves pure-LTR behavior, and included 985 passing package tests plus a production ESM/declaration build. The implementation is now upstream in Streamdown; this is host-integration evidence, not a claim that Vercel adopted BidiLens as a dependency. | | Sentry | [feature request #120893](https://github.com/getsentry/sentry/issues/120893) | Open on the design-engineering backlog at low priority; a Sentry maintainer does not expect the BidiLens dependency to be adopted | Proposes content-aware behavior at Sentry's shared React Markdown renderer and Seer wrapper. After the maintainer noted Sentry's existing i18n tooling, the follow-up explicitly preferred a native/local implementation, offered fixtures only if requested, and committed not to bump the issue. This is backlog evidence, not dependency adoption. | | PostHog | [feature request #75474](https://github.com/PostHog/posthog/issues/75474) | Open | Proposes per-block handling in `LemonMarkdown` and PostHog AI's already memoized `MarkdownMessage` blocks. The public feature tracker was used instead of the automated email's sales-demo form, which requires company, role, and monthly-active-user data and is not an appropriate open-source engineering route. | The public endpoints above cover eleven project families and fourteen -repository-specific routes. Hermes, Cline, and Streamdown contain focused host -code; the remaining routes are issue or discussion submissions. None had -received a maintainer approval, merge, downstream pilot, or -production-adoption confirmation when this evidence was recorded. +repository-specific routes. Hermes and Cline contain focused host code, and +the Streamdown implementation in PR #569 merged on 2026-08-14; the remaining +routes are issue or discussion submissions. No downstream pilot or +production-adoption confirmation is claimed. ## Authenticated follow-up routes @@ -59,7 +59,7 @@ production-adoption confirmation when this evidence was recorded. |---|---|---| | JetBrains AI Assistant YouTrack | JetBrains support directed the proposal to the public AI Assistant tracker. A duplicate search found the directly matching, open, assigned [LLM-25407](https://youtrack.jetbrains.com/issue/LLM-25407/Arabic-RTL-Bidirectional-text-rendering-issue-in-Codex-input-field), so no duplicate was created. | Pending account authentication: add one implementation-focused comment with the English-first/Persian-majority fixture, BidiLens corpus and limitation links, and an offer of a scoped renderer patch. | | Nous Research support | The automated receipt for the original proposal assigned reference `T-1645`, while Hermes PR #72508 remained open without human review. | Sent one short follow-up on 2026-08-13 pointing directly to the PR and asking for routing to the Hermes TUI maintainer. | -| n8n support | The support AI said the original proposal had been escalated to a human product/engineering queue, but no human response arrived. | Sent one short follow-up on 2026-08-13 asking whether the team received it or prefers a public feature-request route. | +| n8n support | Senior support engineer Mo Hamdy confirmed the supported contribution route is an n8n Community feature request before any enhancement PR. He also confirmed that `@n8n/chat` uses Markdown-It without raw HTML and that a third-party dependency needs prior maintainer agreement. | A concise reply and [community proposal](outreach/N8N_COMMUNITY_PROPOSAL.md) are drafted, committing to a dependency-free-first approach: fixtures and a native renderer pattern, with BidiLens optional. Sending and posting remain pending explicit user confirmation. | ## Direct organizational outreach @@ -93,15 +93,15 @@ unmonitored addresses, and delivery failures did not receive follow-up mail. | Zulip | The customer-experience lead identified [issue #39511](https://github.com/zulip/zulip/issues/39511) and the existing `#issues` topic for mixed LTR/RTL messages. | Replied that the issue directly overlaps the proposal, clarified the per-paragraph and inline-isolation scope, and committed to continue with small before/after fixtures in the public topic. | | Zed | A Zed representative confirmed that more RTL support is useful but stated that a non-Rust dependency is a non-starter. | The original reply accurately disclosed that no Rust port existed at that time. After [native Rust core PR #31](https://github.com/CodeinScrubs/BidiLens/pull/31) merged, a focused follow-up supplied the source-only status, 928-case/207-isolation evidence, Rust 1.85 target, and final Linux/macOS/Windows CI result. No response to that follow-up, Zed integration, or adoption is claimed. | | Ollama | The support AI requested product feedback in problem/current-behavior/expected-behavior form. After receiving that clarification, it confirmed the submission contains the information its team uses for feature review and made no timeline or adoption commitment. | Sent one structured clarification with the repository and regression-corpus context; stopped after the automated confirmation to avoid an AI-response loop. | -| n8n | The support AI said it escalated the proposal to a human product/engineering review queue. | After no human response arrived, sent one short follow-up on 2026-08-13 asking whether the team received the proposal or prefers a public feature-request route. No further email will be sent without a reply. | +| n8n | Senior support engineer Mo Hamdy replied with the public feature-request route and renderer constraints: Markdown-It, no raw HTML, and prior maintainer agreement before adding a dependency. | Prepared a human reply and a narrower community proposal strategy that leads with fixtures and a native renderer change. BidiLens PR #57 independently adds verified Markdown-It 13/14/15 compatibility, but it is not presented as a dependency mandate. | | Nous Research | An automated receipt assigned support reference `T-1645` and promised a later follow-up. | After no human response arrived, sent one short follow-up on 2026-08-13 that points directly to Hermes PR #72508 and asks for routing to the TUI maintainer. The public PR remains the primary technical channel. | | JetBrains and Sentry | These responses routed the proposal to public trackers. | The resulting tracker evidence is recorded above; no redundant support-email reply was sent. | | PostHog | An automated response identified an unmonitored inbox and linked support and sales-oriented routes that were unsuitable for an open-source engineering proposal. | No email reply was sent. The public feature request recorded above was opened independently. | | Cohere, Supabase, Microsoft, and delivery systems | The messages were acknowledgements, account-verification instructions, unmonitored-address notices, or delivery failures. | No reply was sent because none represented maintainer review or an actionable technical question. | -These responses are routing evidence, not adoption evidence. No organization in -this table has approved a dependency, merged an integration, or confirmed a -production rollout. +These responses are routing evidence, not adoption evidence. Streamdown's +native implementation is the one recorded upstream merge; no organization +has approved a BidiLens dependency or confirmed a production rollout. ### Response audit (2026-08-13) @@ -113,14 +113,90 @@ human review. | Project/channel | New evidence | Action on the evidence date | |---|---|---| | Sentry | A design-engineering maintainer placed the behavior on the team's low-priority backlog, said Sentry already has i18n tooling, and did not expect to adopt the BidiLens dependency. | Replied once that the behavior is the request, not a dependency mandate; preferred a native/local implementation; offered a small fixture if requested; and committed not to bump the issue. | -| Cline | PR #12724 had become conflicting with current upstream. After a narrow rebase, only the lockfile required regeneration; the component, package manifest, and regression tests applied cleanly. | Rebased with force-with-lease, preserved the host lockfile's formatting, and reran hosted CI. All quality, unit, platform, VS Code, three-OS E2E, and security checks passed. No maintainer approval is claimed. | +| Cline | PR #12724 had become conflicting with current upstream. After a narrow rebase, only the lockfile required regeneration; the component, package manifest, and regression tests applied cleanly. The current GitHub state is again marked conflicting/dirty, although its hosted checks remain green. | The prior rebase and CI evidence are preserved. No further force-push is planned without a maintainer request or action-specific confirmation; no maintainer approval is claimed. | | Nous Research | Support reference `T-1645` remains an automated receipt with no human follow-up. Separately, `hermes-sweeper` revalidated PR #72508 against current `main`, found no verified problem, and recommended keeping it open with high salvageability. | Kept the public PR as the primary technical channel and sent one short routing follow-up on 2026-08-13. Automation is not human review; no additional follow-up is planned without a reply. | -| n8n | The support AI's promised human product/engineering follow-up had not arrived by the audit date. | Sent one short routing/status follow-up on 2026-08-13. No escalation or adoption is claimed, and no additional follow-up is planned without a reply. | +| n8n | Senior support engineer Mo Hamdy supplied an actionable public route and technical constraints on 2026-08-13. | Drafted a reply that follows his guidance and converted the Markdown-It 13 peer/type incompatibility into BidiLens PR #57 with a strict packed 13/14/15 gate. The reply and community post are not recorded as sent. | | Jupyter, Zulip, Zed, Ollama, JetBrains, PostHog, Cohere, Supabase, Microsoft, and delivery systems | No new actionable human email response was found beyond the earlier audit. | No additional email was sent: these threads were already handled, routed to public channels, automated-only, unmonitored, rejected, or delivery failures. | The August 13 audit adds one maintainer backlog disposition and stronger hosted -CI/automation evidence. It does not add a merge, downstream pilot, production -deployment, endorsement, or company adoption claim. +CI/automation evidence. It does not, on its own, add a merge, downstream pilot, +production deployment, endorsement, or company adoption claim. + +### Response audit (2026-08-23) + +The project mailbox was checked again through 2026-08-23. No new human +maintainer reply or adoption decision was found after the August 13 audit. The +following status is current: + +| Project/channel | Current evidence | Action on the evidence date | +|---|---|---| +| Jupyter Community Building | Matt Fisher's latest message remains the August 3 handoff to Jupyter Zulip; the thread contains no newer technical response. | No new email was sent. The next valid route remains a focused public topic in `#jupyterlab` or `#ask-anything` with the screenshot-derived fixtures. | +| Zulip | Emily Sutherlin's latest reply still points to issue [#39511](https://github.com/zulip/zulip/issues/39511) and its existing `#issues` topic. | No duplicate issue or reminder was posted. The previously stated fixtures-first plan remains the appropriate next step. | +| Ollama | The latest response is an automated support confirmation that the problem/current-behavior/expected-behavior format is useful; it makes no timeline or adoption promise. | No further reply was sent; the automated loop was intentionally stopped. | +| n8n | Mo Hamdy's August 13 guidance remains the only actionable maintainer-routing response: open a Community feature request first, lead with a native/dependency-free proposal, and keep raw HTML disabled. | The reply and [community proposal](outreach/N8N_COMMUNITY_PROPOSAL.md) remain drafts. Nothing was posted or sent during this audit. | +| JetBrains, Sentry, Zed, Nous Research, Expo, Microsoft, and other role-address threads | The latest messages are routing instructions, automated acknowledgements, or unmonitored-address notices; none is a maintainer approval or merge decision. | No unsolicited follow-up was sent. Public tracker/PR routes remain the source of truth. | +| Account/security notifications | Recent Google/Anthropic messages concern sign-in or account-data sharing, not BidiLens review. | No security links were followed and no account settings were changed. | +| Public PR status | Vercel Streamdown PR #569 is merged; Hermes PR #72508 remains open with no human review; Cline PR #12724 is open but currently conflicting/dirty despite green hosted checks. | Updated this log from the live GitHub state; no external PR was edited or force-pushed during the audit. | + +This audit is an inbox snapshot, not proof of delivery, reading, or product +adoption. Existing drafts were preserved. Any public forum post, tracker +comment, or email reply still requires an action-specific confirmation at the +time it would be sent. + +### Response and release audit (2026-08-24, historical snapshot) + +The signed-in project mailbox was checked through August 24, 2026. No new +human maintainer reply, review decision, or adoption confirmation was found +after the August 13 responses. The only project-adjacent messages after +August 22 were Google account-data notices for Claude and opencode.ai; no +security links were followed and no account settings were changed. + +The BidiLens host-integration work is tracked in [PR #57](https://github.com/CodeinScrubs/BidiLens/pull/57). The source behavior reviewed in this audit is committed in `8386684`, including the Unicode paragraph-boundary alignment; later documentation-only commits did not alter that behavior. At the time of this snapshot: + +- the PR is open and remains a draft for maintainer review; +- the branch is mergeable and the protected status is clean; +- all required CI and CodeQL jobs pass, including Rust formatting, tests, the + Android and Apple gates, Windows, three-browser visual checks, packed Node + consumers, dependency audit, and Markdown-It 13/14/15 compatibility; +- the stale protected status context was corrected from the old 13/14 label to + the current 13/14/15 compatibility check, without changing source-branch + review requirements. + +External status is unchanged: Hermes PR #72508 is open without a human review +decision, Cline PR #12724 remains open and conflicting/dirty with review still +required, and Streamdown PR #569 remains the one recorded upstream merge. No +external PR was edited, force-pushed, merged, or commented on during this +audit. The current Markdown-It 15 compatibility target is supported by the +upstream 15.0.1 release; BidiLens continues to pin reproducible Unicode 17 +data until Unicode 18 leaves its prepublication/beta period. + +This audit is evidence of current checks and routing only. It does not prove +delivery, maintainer review, production deployment, or adoption. + +### Response and release audit (2026-09-01) + +The signed-in project mailbox was searched for BidiLens, bidirectional-text, +RTL, and contacted-organization replies after August 24. No new maintainer +reply, review decision, routing instruction, rejection, or adoption claim was +found. Account, newsletter, and product messages mentioning AI vendors were +not treated as project responses; no security link was followed, no message +was sent, and existing drafts were preserved. + +The public routes were refreshed independently of email. Hermes PR #72508 is +still open without a human review or exposed status checks. Cline PR #12724 is +still open, review-required, and conflicting despite its previously successful +hosted checks. Streamdown PR #569 remains merged. The Antigravity, Claude Code, +and two Codex issues remain open without a new maintainer response to the +BidiLens proposals. No external issue, PR, discussion, or comment was changed +during this audit. + +The local `0.3.1` candidate passed the complete static gate, all 30 +Chromium/Firefox/WebKit tests, all 12 packed type-layout checks, the +Markdown-It 13.0.2/14.3.1/15.0.1 compatibility matrix, dependency audit, +CycloneDX validation, and workflow lint. GitHub-hosted results for any newer PR +head remain pending until that head is pushed; the live PR page is the +authoritative status source. These checks are engineering evidence, not proof +of downstream adoption or universal rendering correctness. ## Deliberate deferrals @@ -135,9 +211,10 @@ deployment, endorsement, or company adoption claim. 1. Respond to maintainer questions with a minimal reproduction, benchmark, test, or smaller patch; do not answer with generic promotion. -2. For PRs #72508, #12724, and #569, keep the branches available and rebase - only when requested or when a real conflict appears. Never force-push over - review history without explaining why. +2. For PRs #72508 and #12724, keep the branches available and rebase only + when requested or when a real conflict appears. PR #569 is merged and needs + no branch maintenance. Never force-push over review history without + explaining why. 3. Do not post a reminder on an unchanged issue or discussion for at least 30 days. A reminder must include new evidence, such as a released fix, host fixture, benchmark, or maintainer-requested implementation. @@ -160,7 +237,8 @@ deployment, endorsement, or company adoption claim. results. - **Adopted:** the host confirms continued use in a released product. -Only the first state is evidenced for most routes above. The three code PRs are -submitted and have not been approved or merged. See the [adoption +Only the first state is evidenced for most routes above. Of the three focused +code PRs, Streamdown is merged while Hermes and Cline remain submitted without +maintainer approval. See the [adoption strategy](ADOPTION.md), [limitations](LIMITATIONS.md), and [outreach kit](OUTREACH.md) before describing this activity publicly. diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md index a481204..dc33f3e 100644 --- a/docs/PERFORMANCE.md +++ b/docs/PERFORMANCE.md @@ -91,7 +91,8 @@ API signal while a rich document is between checkpoints. - release checks enforce aggregate emitted-JavaScript budgets, including code-split chunks. -The default newline separator is recognized incrementally. An arbitrary custom +The complete Unicode 17 paragraph-separator set (CR, LF, CRLF, NEL, +U+001C–U+001E, and U+2029) is recognized incrementally. An arbitrary custom paragraph-separator regular expression is buffered and evaluated once by `finish()`. This preserves chunk-boundary invariance for future-sensitive lookarounds, anchors, and extendable matches without reparsing the accumulated diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md index 3e71765..a5113e2 100644 --- a/docs/PUBLISHING.md +++ b/docs/PUBLISHING.md @@ -66,9 +66,10 @@ version. - verified `shayanay80` owner access to the `bidilens` npm organization and `@bidilens` scope; - identified bootstrap maintainer and CODEOWNERS; -- strict `main` protection requires all 23 verification contexts: the 18 CI - jobs (including the Android library/sample build, API 35 UI-test gate, Apple - and Windows compiler gates, and three-platform Rust gate) plus five CodeQL +- strict `main` protection requires all 24 verification contexts: the 19 CI + jobs (including the Markdown-It 13/14/15 packed compatibility gate, Android + library/sample build, API 35 UI-test gate, Apple and Windows compiler gates, + and three-platform Rust gate) plus five CodeQL language analyses for JavaScript/TypeScript, Kotlin, C#, Swift, and Rust. The branch must be up to date and use linear history, while force-pushes and branch deletion are blocked; repository administrators are also subject to @@ -137,8 +138,9 @@ git status --short ``` `verify:production` expands to the quality, three-browser visual, package type, -dependency-audit, SBOM, and clean-release gate set that CI and release -preparation enforce as separate steps. +packed Markdown-It 13/14/15 compatibility, dependency-audit, SBOM, and +clean-release gate set that CI and release preparation enforce as separate +steps. `release:check` rejects a dirty tree, packs each public package, checks files and dependency protocols, installs all local tarballs into a temporary strict diff --git a/docs/REQUIREMENT_MATRIX.md b/docs/REQUIREMENT_MATRIX.md index 90f6950..a375ba1 100644 --- a/docs/REQUIREMENT_MATRIX.md +++ b/docs/REQUIREMENT_MATRIX.md @@ -1,6 +1,6 @@ # Build-specification traceability matrix -**Evidence date:** 2026-07-27 +**Current-tree evidence date:** 2026-09-01 This file maps the binding “Ultimate Build Instruction — Cross-Platform Bidirectional Text Toolkit for AI Interfaces, version 2.0” to the source and @@ -39,7 +39,7 @@ Status vocabulary: | Surface | Status | Evidence or exact gap | |---|---|---| | Framework-independent TypeScript core | Complete and tested | `@bidilens/core`; dependency-free runtime; generated Unicode data; analysis, evidence, isolation, security, streaming | -| unified/remark/rehype and markdown-it AST processing | Complete and tested | `@bidilens/markdown`; typed adapters, structural blocks, tables/lists/quotes/code/math, raw-HTML-safe defaults | +| unified/remark/rehype and markdown-it AST processing | Complete and tested | `@bidilens/markdown`; typed adapters, structural blocks, tables/lists/quotes/code/math, raw-HTML-safe defaults; source builds against Markdown-It 15 through a version-neutral runtime boundary, while packed strict consumers verify identical full 932-fixture behavior on Markdown-It 13.0.2/14.3.1 and identical BidiLens semantic reports on Markdown-It 15.0.1 (whose upstream linkifier can render differently), without leaking host type lines | | Plain HTML and DOM | Complete and tested | `@bidilens/html` and `@bidilens/dom`; escaped serialization, restore/observe lifecycle, cross-realm tests | | Web Component | Complete and tested | `@bidilens/web-component`; side-effect-free/SSR-safe main import, explicit `/auto` registration, self-contained browser bundle, three-browser load test | | React | Complete and tested | `@bidilens/react`; React 18/19 probes, SSR, components and streaming hook | @@ -71,7 +71,7 @@ batch plugin path; it is not misrepresented as a stateful streaming backend. | Surface | Status | Evidence or exact gap | |---|---|---| -| Android/Jetpack Compose | Implemented, signed, and published; external validation pending | Maven Central `0.1.1` pure Kotlin core, Views, and Compose libraries; sample app; current source verifies the generated 932-case corpus (the published `0.1.1` release predates the fourteen boundary-regression fixtures); JVM/Robolectric suites; lint/AAR/APK tasks; 3 Views plus 3 Compose UI tests on local API 36.1; and an API 35 emulator CI gate. Physical-device/OEM/IME/TalkBack evidence and a downstream pilot remain open | +| Android/Jetpack Compose | Implemented, signed, and published; external validation pending | Maven Central `0.1.1` pure Kotlin core, Views, and Compose libraries; sample app; current source verifies the generated 932-case corpus and the newer paragraph-boundary security regressions (the published `0.1.1` release predates this hardening); JVM/Robolectric suites; lint/AAR/APK tasks; 3 Views plus 3 Compose UI tests on local API 36.1; and an API 35 emulator CI gate. Physical-device/OEM/IME/TalkBack evidence and a downstream pilot remain open | | Flutter/Dart | Missing | No package/demo, generated corpus representation, widget/golden tests, or SDK build report | | React Native | Missing | No component, generated corpus representation, native tests, or platform build report | | Swift Package/SwiftUI/UIKit | Source and hosted simulator/compiler validation complete; physical-device/release validation pending | Swift Package, generated Unicode 17 ranges, copied 932-case corpus, core tests/example, UIKit `UILabel`/`UITextView`/`UITextField` adapters, UIKit-backed SwiftUI `BidiText`, independent physical alignment, and protected macOS/iOS Simulator gates in [CI](https://github.com/CodeinScrubs/BidiLens/actions/workflows/ci.yml). Physical iOS/VoiceOver evidence, sample app, editable SwiftUI integration, and registry publication remain open | @@ -101,7 +101,7 @@ recorded explicitly. | Requirement | Status | Evidence or exact gap | |---|---|---| -| Chunk-boundary invariance | Complete for finalized direction/text and Markdown-It rich output within the tested grammar | Seeded fast-check properties cover whole, one-code-point, random, token-like, UTF-16 surrogate splits, Markdown fences/links and default paragraph separators; unfinished future-sensitive tokens may revise live snapshots, and final rich documents equal the batch oracle | +| Chunk-boundary invariance | Complete for finalized direction/text and Markdown-It rich output within the tested grammar | Seeded fast-check properties cover whole, one-code-point, random, token-like, UTF-16 surrogate splits, Markdown fences/links and every Unicode 17 default paragraph separator; unfinished future-sensitive tokens may revise live snapshots, and final rich documents equal the batch oracle | | Stable live rendering and flagship transition | Complete for the shipped streams | Source-position checkpoints; completed core paragraphs immutable; rich Markdown exposes conservative `stableThrough`, pending source, and dirty replacements rather than freezing future-sensitive syntax; default direction remains revisable and sticky locking is explicit | | Incremental performance without full-document reparse per token | Complete for the shipped streams | Core incremental state plus 1-char/1,000-chunk benchmarks; the rich Markdown parser runs at geometric and structural checkpoints plus finalization, with an 8,192 one-character plain-text regression asserting no more than 14 live parses | | Final stream equals batch for source and directions | Complete and tested | Core properties and framework adapter tests | @@ -116,7 +116,7 @@ recorded explicitly. | Thousands of generated/property variants | Complete at test runtime | Seeded fast-check runs arbitrary Unicode and random chunking; generated variants are reproducible test cases rather than committed corpus rows | | Fixture-review guide | Complete | `corpus/README.md` explains review fields and native-speaker workflow | | Unit/property/serialization/range tests | Complete for shipped packages | `pnpm run check`; package-local suites and fast-check properties | -| Visual Chromium + Firefox + WebKit | Complete and tested | 24 Playwright cases across three engines on the committed Windows/Arial baseline | +| Visual Chromium + Firefox + WebKit | Complete and tested | 30 Playwright cases across three engines on the committed Windows/Arial baseline, including screenshot-derived mixed Persian/English medical prose | | Four-way, flagship, structured Markdown, stream, dark, zoom | Complete and tested | Playwright flagship suite and screenshots | | Selection and copy/paste invariant | Complete for web evidence; partial for Android | Three-engine logical selection and Chromium clipboard test; Android editable callbacks and Compose semantics remain control-free in device tests. Firefox/WebKit clipboard, physical Android OEM/IME copy, and other native surfaces remain environment-specific gaps | | Accessibility | Partial/external | Automated semantic, selection, dark-mode and zoom evidence plus `docs/ACCESSIBILITY.md`; real screen-reader/browser/OS laboratory matrix is not complete | @@ -129,7 +129,7 @@ recorded explicitly. | English and Persian main README | Complete | `README.md` and `README.fa.md` | | Architecture, security, limitations, accessibility, migration, FAQ, contributing, governance, conduct, roadmap, changelog | Complete for the public web beta and Android Maven release | Checked by `scripts/check-docs.ts`; Android has a dedicated integration guide; guides for missing surfaces necessarily remain incomplete | | Reproducible performance matrix and budgets | Complete for current JS surfaces | `scripts/benchmark.ts`, `docs/PERFORMANCE.md`, scheduled workflow, package byte budgets in release checker | -| 3 patch-quality upstream integrations | Partial/external | One host-tested patch is submitted as [NousResearch/hermes-agent#72508](https://github.com/NousResearch/hermes-agent/pull/72508), with focused tests and local host gates. It is unmerged and does not satisfy the minimum of three integrations | +| 3 patch-quality upstream integrations | Partial/external | One host-tested native implementation merged in [Vercel Streamdown#569](https://github.com/vercel/streamdown/pull/569); Hermes #72508 and Cline #12724 remain submitted/open. The minimum of three integrations, downstream pilots, and adoption evidence is not met | | 2 issue-quality evidence bundles | Complete as public submissions, not product fixes | Current-policy, non-duplicate evidence is public for Antigravity, Claude Code, Codex, Cline, Continue, and assistant-ui; routes and exact states are recorded in the [outreach log](OUTREACH_LOG.md) | | IMPACT, ADOPTION, APPLICATION_NOTES with measured facts only | Complete | Root and `docs/` evidence documents; targets are labeled as targets | | CI: quality, package, visual, size, SBOM, audit | Complete for current JS/web surfaces | Pinned GitHub Actions; Node 22/24, Windows/macOS, three-browser Windows visual job, audit and CycloneDX checks | @@ -152,10 +152,10 @@ tag. Therefore working code alone cannot make an historical milestone green. | M3 streaming | Implemented; historical gate incomplete | Direction and rich Markdown-It stream gates pass now; no historical `m3` tag exists and is not fabricated retroactively | | M4 frameworks/Electron | Partial | Web Component/React/Vue/Svelte pass anti-hollow and SSR gates; Electron is missing; no `m4` tag | | M5 CLI/Playwright Action/VS Code | Partial | CLI, reusable Playwright helpers, and bundled conformance Action pass; VS Code extension is missing; no `m5` tag | -| M6 ≥300/visual/copy | Implemented; historical gate incomplete | 932 corpus cases and 24 three-engine visual tests pass; no `m6` tag | +| M6 ≥300/visual/copy | Implemented; historical gate incomplete | 932 corpus cases and 30 three-engine visual tests pass; no `m6` tag | | M7 native + terminal | Partial | Terminal, Android, SwiftUI/UIKit, and .NET/WPF exist; Flutter, React Native, and other documented native adapters remain open; no `m7` tag | | M8 playground/full EN/FA docs | Implemented; historical gate incomplete | Offline bilingual playground and EN/FA repository docs pass build/browser/link checks; no annotated `m8` tag | -| M9 release/integrations | Partial | Package release side is complete: clean committed checkout, public npm artifacts, provenance, trusted publishing, SBOM, retained manifest, immutable `v0.3.0` web release, and signed `android-v0.1.1` Maven release. One of the required three host-tested integrations is submitted but unmerged, so the integration minimum remains incomplete | +| M9 release/integrations | Partial | Package release side is complete: clean committed checkout, public npm artifacts, provenance, trusted publishing, SBOM, retained manifest, immutable `v0.3.0` web release, and signed `android-v0.1.1` Maven release. One host-tested native implementation merged upstream, but the required three integrations, downstream pilots, and adoption evidence remain incomplete | ## Definition-of-done audit @@ -173,7 +173,7 @@ tag. Therefore working code alone cannot make an historical milestone green. | 10 | Complete as schema-valid technical corpus; native review remains a publication-quality gap | | 11 | Complete — no-backend bilingual playground and EN/FA repository docs exist | | 12 | Complete for current packages — workflows validate, SBOM/license/notices exist | -| 13 | Partial — one host-tested integration patch is submitted; fewer than three exist and none is merged or piloted | +| 13 | Partial — one host-tested native implementation is merged; fewer than three integrations exist and no downstream pilot is evidenced | | 14 | Complete for current documented claims; continue checking after every change | | 15 | Partial — the reviewed source, current `v0.3.0` web release, and `android-v0.1.1` Maven release are public, but historical intermediate milestone tags were not fabricated retroactively | diff --git a/docs/SCREENSHOT_CASES.md b/docs/SCREENSHOT_CASES.md new file mode 100644 index 0000000..1ac4df7 --- /dev/null +++ b/docs/SCREENSHOT_CASES.md @@ -0,0 +1,82 @@ +# Screenshot-derived mixed-direction cases + +This document turns the user-supplied ChatGPT screenshots into repeatable, +non-clinical rendering evidence. The screenshots show Persian medical study +notes interleaved with English labels, abbreviations, arrows, emoji, Markdown +lists, block quotes, and tables. The wording is used only as text-shape and +boundary material; it is not medical guidance and BidiLens does not validate +the medical claims. + +## What the renderer must preserve + +The source is always kept in logical order. For example, the source sequence + +```text +React یک کتابخانه جاوااسکریپت بسیار محبوب است. +``` + +has the word order `React=1`, `یک=2`, through `است=7`, then `.=8`. BidiLens +chooses the paragraph base from natural-language evidence, isolates the Latin +technical run, and lets the browser's Unicode Bidirectional Algorithm perform +visual reordering. It never reverses the string, inserts hidden controls into +the stored value, or changes the caller's alignment. + +The fixture in +[`scripts/fixtures/chatgpt-mixed-direction.ts`](../scripts/fixtures/chatgpt-mixed-direction.ts) +covers the following boundaries from the screenshots: + +- Persian-majority headings and paragraphs containing `CN IX`, `CN X`, `ICH`, + `SAH`, `CT`, `CSF`, arrows, and emoji; +- the Persian combining-mark word `مثلاً` immediately beside the English phrase + `right vagus lesion:`; +- English-majority lines such as `Uvula runs away from the lesion.` inside an + otherwise RTL document; +- list items, block quotes, Markdown tables, inline code, and punctuation; +- a long Persian/English context sentence similar to an AI session summary. + +## Acceptance invariants + +Every adapter and host integration should preserve these invariants: + +1. `textContent`, selection, clipboard, logs, prompts, and serialized source + remain byte-for-byte/logically identical to the input. +2. A Persian combining mark stays attached to its word; `مثلاً` must not become + `مثلا` plus a detached mark. +3. Compact technical labels are isolated as units (`CN X`, `CN IX`, `HR/BP`) + without treating ordinary prose such as `I am a developer.` as a label. +4. Direction metadata is semantic and block-local. It must not emit + `text-align`, overwrite authored `left`/`right` alignment, or mutate an + ancestor's layout. An RTL paragraph may intentionally remain physically + left-aligned. +5. A fully LTR scope with no RTL strong characters or bidi controls remains a + no-op unless the caller explicitly requests stable annotation. +6. Code, URLs, paths, identifiers, and user-supplied raw HTML follow their + documented safety policies rather than being guessed as natural language. + +## Verification + +The unit and Markdown adapter regression tests exercise the fixture directly: + +```bash +pnpm exec vitest run packages/core/src/core.test.ts +pnpm exec vitest run packages/markdown/src/markdown.test.ts +``` + +The cross-version gate renders it through all supported Markdown-It host lines +(13.0.2, 14.3.1, and 15.0.1) and compares the resulting BidiLens reports: + +```bash +pnpm run markdown-it:compat +``` + +The Playwright suite additionally checks DOM direction, isolation text, and +source text in Chromium, Firefox, and WebKit: + +```bash +pnpm run test:visual +``` + +These checks prove the adapter contract, not every browser font, IME, +accessibility service, terminal emulator, or proprietary host renderer. A +downstream product should still run the same fixture on its target devices and +keep its own explicit alignment policy. diff --git a/docs/SECURITY.md b/docs/SECURITY.md index fa8f01f..2ded4f0 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -31,6 +31,9 @@ can emit human, JSON, or SARIF results with UTF-16 line/column semantics. Detected categories include ALM/LRM/RLM, LRE/RLE/LRO/RLO/PDF, LRI/RLI/FSI/PDI, deprecated U+206A–U+206F formatting controls, unmatched pops/openers, formatting that crosses an isolate boundary, and U+200B. +Formatting stacks are balanced independently for each Unicode paragraph +boundary (CR, LF, CRLF, NEL, U+001C–U+001E, and U+2029); a closer in a later +paragraph never makes an earlier opener appear balanced. ## Secure defaults diff --git a/docs/V1_BUILD_REPORT.md b/docs/V1_BUILD_REPORT.md index 74dab8f..5ed22cf 100644 --- a/docs/V1_BUILD_REPORT.md +++ b/docs/V1_BUILD_REPORT.md @@ -1,20 +1,23 @@ -# BidiLens 0.2.0 release report +# BidiLens current verification and release report -> This is the immutable historical report for 0.2.0. Web/package `0.3.1` is -> prepared for protected publication; `0.3.0` remains the latest verified -> public release. Current changes are recorded in the root changelog, and -> release evidence is retained by the protected publication workflow. +> This report separates the current `0.3.1` candidate evidence from immutable +> publication history. Web/package `0.3.1` is prepared for protected +> publication; `0.3.0` remains the latest verified public release. Historical +> release evidence is retained by the protected publication workflows and +> GitHub releases linked below. -**Evidence date:** 2026-07-28 +**Current-tree evidence date:** 2026-09-01 **License:** MIT, with Unicode-data and Apache-2.0 corpus third-party notices -**Publication status:** all 12 `0.2.0` packages are public with verified +**Publication status:** all 12 `0.3.0` packages are public with verified registry integrity, `latest` tags, and SLSA provenance; the exact source commit -has an annotated `v0.2.0` tag and an immutable GitHub release containing the -retained tarballs, release manifest, and validated SBOM. The later native -Android `0.1.1` core, Views, and Compose modules are signed and public on Maven -Central with an annotated tag, immutable release, and public-consumer evidence +has an annotated `v0.3.0` tag and an immutable GitHub release containing the +retained tarballs, release manifest, and validated SBOM. The native Android +`0.1.1` core, Views, and Compose modules are signed and public on Maven Central +with an annotated tag, immutable release, and public-consumer evidence. The +`0.3.1` source and package manifests are not public until the protected release +workflow completes. **Recommendation:** suitable for bounded, maintainer-controlled web pilots; not a universal cross-platform production release @@ -38,7 +41,7 @@ opposite-direction runs. | Surface | Status | Evidence / boundary | |---|---|---| -| `@bidilens/core` | Complete and tested | Unicode analysis, raw and policy-adjusted evidence, configurable technical vocabulary, dual-offset isolation, security, revisable streaming with tested final chunk invariance, properties; 95.73% lines | +| `@bidilens/core` | Complete and tested | Unicode analysis, raw and policy-adjusted evidence, configurable technical vocabulary, dual-offset isolation, security, revisable streaming with tested final chunk invariance, properties; 96.28% lines | | `@bidilens/dom` | Complete and tested | apply/restore, custom selectors, styles, observer lifecycle, detached/cross-realm DOM | | `@bidilens/html` | Complete and tested | escaped semantic blocks and `` isolation, tag validation, source preservation | | `@bidilens/markdown` | Complete and tested | unified/remark/rehype and typed Markdown-It batch adapters; blocks/lists/tables/quotes/code/math/XSS; rich Markdown-It stream with AST/HTML/isolation/security final parity, dirty/pending ranges, and 97.29% lines | @@ -51,11 +54,14 @@ opposite-direction runs. | `@bidilens/terminal` | Complete and tested | ANSI-aware conservative output; emulator shaping remains host-dependent | | `@bidilens/cli` | Complete and tested | inspect/render/test/audit/lint/security-scan/sanitize; human/JSON/SARIF; real packed binary | | Bundled GitHub Action | Complete and tested | Node 24 audit/corpus action, human/JSON/SARIF, workspace-safe report path, real exit codes; source and generated-bundle probes | -| React/Vite playground | Complete and tested | Static/offline; EN/FA UI, policy/security controls, adjustable stream, live four-way comparison, AST/evidence/isolation/security, searchable 928-case asset, copy verification, JSON/semantic HTML export, hash state and explicit theme; three-browser flow | -| Corpus | Partial (with exact missing functionality) | 928 schema-valid technical/user cases, including 196 attributed sibling seeds; zero native-speaker-certified templates | +| React/Vite playground | Complete and tested | Static/offline; EN/FA UI, policy/security controls, adjustable stream, live four-way comparison, AST/evidence/isolation/security, searchable 932-case asset, copy verification, JSON/semantic HTML export, hash state and explicit theme; three-browser flow | +| Corpus | Partial (with exact missing functionality) | 932 schema-valid technical/user cases, including 196 attributed sibling seeds; zero native-speaker-certified templates | | VS Code, Electron, PDF | Unsupported (with technical reason) | No implementations exist; hollow packages were rejected and these require host-specific security/print tests | -| Native Android | Implemented and published after the immutable 0.2.0 web release | Signed Maven Central `0.1.1` core, Views, and Compose artifacts; sample APK; current source verifies 928 cases while the published release predates the ten boundary-regression fixtures; JVM/Robolectric tests; lint/AAR build; and API 35/36 emulator UI evidence. This does not alter the historical 0.2.0 npm artifacts | -| Flutter, React Native, Swift | Unsupported (with technical reason) | No implementations or executable SDK evidence exist in this repository | +| Native Android | Implemented and published | Signed Maven Central `0.1.1` core, Views, and Compose artifacts; sample APK; current source verifies 932 cases while the published release predates later boundary/evidence fixtures; JVM/Robolectric tests; lint/AAR build; and API 35/36 emulator UI evidence | +| Apple Swift/UIKit/SwiftUI | Implemented in source; registry and physical-device validation pending | Swift Package, generated Unicode 17 tables, 932-case corpus tests, UIKit adapters, UIKit-backed SwiftUI `BidiText`, independent physical alignment, and hosted macOS/iOS Simulator gates | +| Windows .NET/WPF | Implemented in source; NuGet and physical-device validation pending | Dependency-free .NET 8 core, WPF adapters, 932-case executable corpus gate, state/selection restoration, physical-left RTL test, sample, build and package gates | +| Rust | Implemented in source; crates.io and downstream validation pending | Native core, generated Unicode 17 tables, byte/UTF-16/code-point offsets, 932-case conformance, Linux/macOS/Windows CI, and a runnable example | +| Flutter and React Native | Unsupported (with technical reason) | No implementations, generated corpus representations, package builds, widget tests, or host integration evidence exist in this repository | | Upstream AI-product integrations | External review in progress; no adoption | One host-tested Hermes TUI patch is submitted as [NousResearch/hermes-agent#72508](https://github.com/NousResearch/hermes-agent/pull/72508); tailored evidence requests are public for six additional project families. No review, merge, pilot, deployment, or endorsement is claimed; see the [outreach log](OUTREACH_LOG.md). | ## Reproduced validation @@ -63,27 +69,27 @@ opposite-direction runs. | Command / gate | Observed result | |---|---| | `pnpm run check` | Unicode, strict TypeScript, ESLint, anti-hollow package depth, coverage, corpus, docs, 12 package builds plus demo, Action bundle and generated-artifact probes pass | -| Vitest within `check` | 16 files, 392 tests pass | -| Coverage (seeded run) | 91.85% statements, 85.80% branches, 94.48% functions, 94.76% lines; core 95.73%, Markdown 97.29%, Playwright helpers 100% lines | -| `pnpm run corpus:check` | 928/928; 0 native-speaker-reviewed | +| Vitest within `check` | 16 files, 437 tests pass | +| Coverage (seeded run) | 92.22% statements, 86.26% branches, 94.85% functions, 95.02% lines; core 96.28%, Markdown 97.30%, Playwright helpers 100% lines | +| `pnpm run corpus:check` | 932/932; 0 native-speaker-reviewed | | `pnpm run android:check` | Kotlin core/Views/Compose unit suites, Android lint, all debug assemblies, and the sample APK pass with JDK 21 and SDK 36 | | Android device gates | 3/3 Views and 3/3 Compose UI tests pass locally on Android 16/API 36.1; CI defines a pinned API 35 emulator gate | -| `pnpm run test:visual` | 24/24 across Chromium, Firefox, WebKit on the Windows/Arial baseline OS, including real standalone-module loading and the bilingual playground's controls/corpus/copy/theme/exports; CI aligns pixel and geometry checks to that OS while Linux runs semantic/build/package gates | +| `pnpm run test:visual` | 30/30 across Chromium, Firefox, WebKit on the Windows/Arial baseline OS, including real standalone-module loading, screenshot-derived Persian medical prose, and the bilingual playground's controls/corpus/copy/theme/exports; CI aligns pixel and geometry checks to that OS while Linux runs semantic/build/package gates | | `pnpm -r --if-present run example` | all 12 public package examples run in the workspace | | `pnpm run packages:types` | all 12 ESM package layouts and the spec package's five JSON subpaths pass real ATTW packing; CJS is intentionally unsupported | | publint 0.3.21 against every package directory | all 12 packed manifests and published file layouts report `All good!` | | `pnpm run deps:audit` | no known vulnerabilities at audit time | | `pnpm licenses list --prod` | runtime dependency inventory reports MIT, ISC, BSD-2-Clause, and Python-2.0 licenses; Unicode data and the imported Apache-2.0 corpus are covered separately by the committed third-party notices | | `pnpm outdated -r` | only `@types/node` 26 and TypeScript 7 are newer majors; types stay aligned to supported Node 24 and TypeScript 6.0.3 is the newest line accepted by the installed `typescript-eslint` peer range | -| `pnpm run sbom` + `pnpm run sbom:check` | CycloneDX 1.7; 585 components, 599 dependency relationships. cdxgen also reports inherited process environment warnings in the local execution environment; validation does not treat those environment warnings as component findings | +| `pnpm run sbom` + `pnpm run sbom:check` | CycloneDX 1.7; 577 components, 591 dependency relationships. cdxgen also reports inherited process environment warnings in the local execution environment; validation does not treat those environment warnings as component findings | | actionlint 1.7.12 | CI, release-preparation, benchmark, and opt-in Pages workflows pass | -| `pnpm run action:check` | 195,023-byte bundle; Node 24 metadata/notices and unresolved-import checks pass; built artifact returns 0 for safe source and 2 for a strict high-risk control without mutation | +| `pnpm run action:check` | 199,943-byte bundle; Node 24 metadata/notices and unresolved-import checks pass; built artifact returns 0 for safe source and 2 for a strict high-risk control without mutation | | Supported Node probes | built core and CLI pass Node 22.22.1 and 24.18.0; an additional Node 20.19.5 compatibility probe passed, but that EOL line is not a production support claim | | Packed framework peer probes | shipped examples pass React/React DOM 18.3.1, Vue/server-renderer 3.5.0, and Svelte 4.2.20; the primary consumer covers React 19.2.8, Vue 3.5.40, and Svelte 5 | | `pnpm run release:check` | strict clean-worktree build/pack/inspect/install/type/runtime/CLI consumer passes; exact examples extracted from all 12 tarballs execute. The pre-commit development tree also passed with `--allow-dirty` | -| GitHub CI for published commit | [11/11 jobs passed](https://github.com/CodeinScrubs/BidiLens/actions/runs/30297267976): Node 22/24 quality and packed consumers, Windows/macOS quality, three browser engines, actionlint, dependency audit, and SBOM | -| Protected npm publication | [workflow run `30297697861`](https://github.com/CodeinScrubs/BidiLens/actions/runs/30297697861) passed the full release gate, published all 12 `0.2.0` packages through OIDC, verified registry integrity, and retained the exact tarballs and manifest | -| Immutable GitHub release | [`v0.2.0`](https://github.com/CodeinScrubs/BidiLens/releases/tag/v0.2.0) resolves to the published source commit; GitHub's immutable-release verification covers the 12 package tarballs, release manifest, and validated SBOM | +| GitHub CI for published commit | [15/15 jobs passed](https://github.com/CodeinScrubs/BidiLens/actions/runs/30352957959): Node 22/24 quality and packed consumers, Windows/macOS quality, three browser engines, actionlint, dependency audit, and SBOM | +| Protected npm publication | [workflow run `30352982906`](https://github.com/CodeinScrubs/BidiLens/actions/runs/30352982906) passed the full release gate, published all 12 `0.3.0` packages through OIDC, verified registry integrity, and retained the exact tarballs and manifest | +| Immutable GitHub release | [`v0.3.0`](https://github.com/CodeinScrubs/BidiLens/releases/tag/v0.3.0) resolves to the published source commit; GitHub's immutable-release verification covers the 12 package tarballs, release manifest, and validated SBOM | | External npm consumer | all 12 public packages installed from the registry; runtime imports, mixed Persian/English direction, streaming, CLI, and the pure-LTR no-op passed; current production dependency audit reported zero findings | | Android release CI | [13/13 jobs passed](https://github.com/CodeinScrubs/BidiLens/actions/runs/30337482079), including Android libraries/sample, isolated Maven consumer, and API 35 device tests | | Protected Android publication | [workflow run `30339097846`](https://github.com/CodeinScrubs/BidiLens/actions/runs/30339097846) signed and published all three Android `0.1.1` modules to Maven Central | @@ -92,7 +98,7 @@ opposite-direction runs. ## Post-release outreach evidence -The outreach recorded before `0.2.0` remains independent of publication. The +The outreach recorded before and after `0.3.0` remains independent of publication. The [outreach log](OUTREACH_LOG.md) links every live route, records one focused host-code PR, explains why other routes are issue/discussion proposals, and lists deliberate anti-spam deferrals. This activity does not change the @@ -110,20 +116,20 @@ Aggregate emitted JavaScript, including chunks and before minification/gzip: | Package | Bytes | Enforced budget | |---|---:|---:| -| CLI | 16,241 | 32,768 | -| Core | 120,452 | 122,880 | -| DOM | 18,297 | 20,480 | +| CLI | 16,330 | 32,768 | +| Core | 126,825 | 126,976 | +| DOM | 18,321 | 20,480 | | HTML | 4,361 | 12,288 | -| Markdown | 79,375 | 81,920 | +| Markdown | 79,833 | 81,920 | | Playwright | 8,542 | 16,384 | -| React | 11,597 | 16,384 | +| React | 11,666 | 16,384 | | Spec | 9,160 | 24,576 | | Svelte | 1,855 | 8,192 | | Terminal | 4,273 | 8,192 | -| Vue | 4,478 | 12,288 | -| Web Component | 35,595 | 81,920 | +| Vue | 4,553 | 12,288 | +| Web Component | 37,391 | 81,920 | -The core artifact is 25,500 bytes with gzip and 19,110 bytes with Brotli on +The core artifact is 26,941 bytes with gzip and 20,257 bytes with Brotli on this build. Its unminified increase funds exact batch/final token-policy parity, invisible-character auditing, atomic control-family sanitization, and closed-fence recognition across the tested token grammar and stream chunk @@ -132,7 +138,7 @@ that implementation. Live snapshots remain intentionally revisable while an unfinished token can still change classification; `finish()` is the exact finalization boundary. -The Markdown artifact is 14,916 bytes with gzip and 12,980 bytes with Brotli on +The Markdown artifact is 15,053 bytes with gzip and 13,111 bytes with Brotli on this build. Its increase contains the serializable token AST, block-analysis report, security deltas, dirty/pending range protocol, geometric and context-changing structural checkpoints, bounded grammar-aware provisional @@ -195,17 +201,17 @@ local numbers, not a service-level objective. The canonical checkout is the strongest reproducible JavaScript/web implementation among the local sibling folders: 12 public packages, 16 test -files with 391 tests, 928 fixtures, current generated Unicode data, real +files with 437 tests, 932 fixtures, current generated Unicode data, real three-engine visual evidence, and clean package-consumer gates. Broader native/desktop ideas found in sibling documentation are retained in the [traceability audit](PROJECT_COMPARISON.md), not misrepresented as working code. ## Release decision -The `0.2.0` code artifacts are published as a **maintainer-controlled public +The `0.3.0` code artifacts are published as a **maintainer-controlled public web beta**. npm publication, package provenance, registry-integrity verification, per-package trusted publishing, protected human approval, the -annotated `v0.2.0` tag, and the immutable release are complete. Broad rollout +annotated `v0.3.0` tag, and the immutable release are complete. Broad rollout still requires: 1. final name/trademark review appropriate to the adopter; @@ -216,9 +222,10 @@ still requires: Broad production or “all platforms” readiness is **not** claimed. Native Android Kotlin, Views, and Compose modules now have JVM, lint, sample-app, and emulator evidence plus signed Maven Central distribution, but physical OEM/IME -and TalkBack validation, iOS/desktop/PDF surfaces, upstream integrations, -native-speaker certification, an external security audit, and a real -downstream pilot remain absent. Historical milestone tags between -`m1` and the current `v0.2.0` release tag were not retroactively fabricated; -publishing -the reviewed source does not reconstruct the original stepwise tag history. +and TalkBack validation, physical iOS/VoiceOver and Windows accessibility/IME +labs, native registry publication beyond Android, PDF support, upstream +integrations, native-speaker certification, an external security audit, and a +real downstream pilot remain absent. Historical milestone tags between `m1` +and the current `v0.3.0` release tag were not retroactively fabricated; +publishing the reviewed source does not reconstruct the original stepwise tag +history. diff --git a/docs/outreach/N8N_COMMUNITY_PROPOSAL.md b/docs/outreach/N8N_COMMUNITY_PROPOSAL.md new file mode 100644 index 0000000..96e0e98 --- /dev/null +++ b/docs/outreach/N8N_COMMUNITY_PROPOSAL.md @@ -0,0 +1,76 @@ +# n8n Community proposal draft + +**Status:** prepared for human review; not posted. + +## Suggested title + +Per-block mixed RTL/LTR direction in `@n8n/chat` Markdown messages + +## Problem + +`@n8n/chat` can display Arabic, Persian, Hebrew, Urdu, and other RTL text, but +mixed-direction AI answers need a base direction per rendered block. CSS +`dir="auto"` follows the first strong character, so it misclassifies a +Persian-majority sentence that begins with a technical English token: + +```text +React یک کتابخانه جاوااسکریپت بسیار محبوب است. +``` + +The paragraph should have an RTL base while `React` remains an isolated LTR +run. The mirror case should remain LTR: + +```text +The Persian word کتاب means book. +``` + +A global RTL setting is not sufficient because one answer can contain +independent headings, paragraphs, list items, quotes, table cells, and code. + +## Proposed bounded change + +At `@n8n/chat`'s existing Markdown-It render boundary, add semantic `dir` +metadata to prose block tokens only when the content needs bidirectional +intervention. Keep code LTR and isolate opposite-direction inline technical +runs. Do not enable raw HTML, rewrite generated or stored Markdown, reverse +strings, or change chat layout/navigation direction. + +The first implementation can be dependency-free and local to n8n. BidiLens is +offered as a fixture/policy reference, not as a dependency requirement. If the +maintainers later prefer a package, BidiLens verifies strict packed consumers +against Markdown-It 13.0.2, 14.3.1, and 15.0.1. + +## Minimum acceptance fixtures + +| Source | Expected block base | Additional requirement | +|---|---|---| +| `React یک کتابخانه جاوااسکریپت بسیار محبوب است.` | RTL | isolate `React` as LTR | +| `The Persian word کتاب means book.` | LTR | isolate `کتاب` as RTL | +| `Plain English Markdown stays exactly as it is.` | unchanged | no added BidiLens/native attributes or wrappers | +| Persian paragraph with `src/index.ts` | RTL | keep the path LTR | +| fenced TypeScript code inside an RTL answer | LTR code | surrounding prose resolves independently | +| two paragraphs with different majorities | independent | no message-wide direction override | + +For every fixture, logical source, `textContent`, selection, and clipboard text +must remain identical. Existing Markdown-It plugins and `html: false` behavior +must continue to work. + +## Rollout and rollback + +Start behind a chat-renderer feature flag or in shadow analysis, measure only +messages containing RTL characters, and compare source/copy identity before +enabling semantic markup. Pure LTR messages must take the identity path. The +change is confined to one renderer stage and should be removable in one +commit. + +## Evidence and limits + +- BidiLens repository: +- Markdown-It 13/14/15 compatibility PR: +- Canonical corpus: +- Exact limitations: + +BidiLens currently has zero native-speaker-certified corpus cases and no n8n +maintainer approval, downstream pilot, independent security review, or +accessibility lab result. This proposal asks for a scoped technical review, not +adoption or endorsement. diff --git a/package.json b/package.json index 5928180..b7fe639 100644 --- a/package.json +++ b/package.json @@ -51,11 +51,12 @@ "npm:release:dry-run": "tsx scripts/publish-npm.ts", "npm:release:publish": "tsx scripts/publish-npm.ts --publish", "packages:types": "tsx scripts/check-package-types.ts", + "markdown-it:compat": "tsx scripts/check-markdown-it-compat.ts", "packages:depth": "tsx scripts/check-package-depth.ts", "sbom": "pnpm dlx @cyclonedx/cdxgen@12.7.1 -t js --no-install-deps --fail-on-error --spec-version 1.7 --json-pretty -o bidilens-sbom.cdx.json .", "sbom:check": "tsx scripts/check-sbom.ts", "deps:audit": "pnpm audit --audit-level low", - "verify:production": "pnpm run check && pnpm run test:visual && pnpm run packages:types && pnpm run deps:audit && pnpm run sbom && pnpm run sbom:check && pnpm run release:check", + "verify:production": "pnpm run check && pnpm run test:visual && pnpm run packages:types && pnpm run markdown-it:compat && pnpm run deps:audit && pnpm run sbom && pnpm run sbom:check && pnpm run release:check", "changeset": "changeset", "changeset:status": "changeset status" }, @@ -64,7 +65,6 @@ "@changesets/cli": "2.31.1", "@eslint/js": "^10.0.1", "@playwright/test": "^1.62.1", - "@types/markdown-it": "^14.1.2", "@types/node": "^24.10.0", "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", @@ -75,7 +75,7 @@ "fast-check": "^4.3.0", "globals": "^17.9.0", "jsdom": "^29.1.1", - "markdown-it": "^14.1.0", + "markdown-it": "^15.0.1", "tsx": "^4.23.12", "typescript": "^6.0.3", "typescript-eslint": "^8.66.0", diff --git a/packages/cli/src/cli.test.ts b/packages/cli/src/cli.test.ts index 039d257..62f52e5 100644 --- a/packages/cli/src/cli.test.ts +++ b/packages/cli/src/cli.test.ts @@ -130,6 +130,17 @@ describe('BidiLens CLI', () => { expect(override?.locations[0]?.physicalLocation.region.startColumn).toBe(5); }); + it('counts Unicode paragraph separators in SARIF line locations', async () => { + const suspicious = `first${String.fromCodePoint(0x0085)}safe${BIDI_CONTROLS.RLO}evil`; + await writeFile(join(cwd, 'unicode-boundary.ts'), suspicious, 'utf8'); + const result = await invoke(['security-scan', 'unicode-boundary.ts', '--sarif']); + const sarif = JSON.parse(result.stdout) as { + runs: Array<{ results: Array<{ ruleId: string; locations: Array<{ physicalLocation: { region: { startLine: number } } }> }> }>; + }; + const override = sarif.runs[0]?.results.find((item) => item.ruleId === 'BIDI_OVERRIDE_CONTROL'); + expect(override?.locations[0]?.physicalLocation.region.startLine).toBe(2); + }); + it('supports clean scans, aliases, modes, and JSON reports', async () => { await writeFile(join(cwd, 'clean.md'), 'می\u200Cخواهم کتاب بخوانم.', 'utf8'); const clean = await invoke(['lint', 'clean.md']); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index a984a2c..8be6ccc 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -7,6 +7,7 @@ import { Command, CommanderError } from 'commander'; import { renderBidiHtml } from '@bidilens/html'; import packageManifest from '../package.json' with { type: 'json' }; import { + DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, analyzeText, findBidiControls, sanitizeBidiControls, @@ -185,7 +186,9 @@ function highestFindingRisk(findings: readonly BidiSecurityFinding[]): BidiContr function sourcePosition(text: string, utf16Offset: number): { line: number; column: number } { let lineNumber = 1; let lineStart = 0; - const newline = /\r\n|\n|\r/gu; + // Include Unicode paragraph separators plus U+2028 (line separator) so + // SARIF locations remain line-aware for every supported Unicode boundary. + const newline = new RegExp(`${DEFAULT_PARAGRAPH_SEPARATOR_SOURCE}|\\u2028`, 'gu'); let match: RegExpExecArray | null; while ((match = newline.exec(text)) !== null && match.index < utf16Offset) { lineNumber += 1; diff --git a/packages/core/README.md b/packages/core/README.md index ec09d0c..bcbad4c 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -44,14 +44,19 @@ formatting controls, an inherited RTL context, or `{ intervention: 'always' }` returns `true`. Inline planning likewise returns no unnecessary ranges for ordinary LTR-only text. -The default newline paragraph separator is recognized incrementally. A custom -`paragraphSeparator` regular expression is evaluated once by `finish()` so -future-sensitive lookarounds, anchors, and extendable matches remain invariant -across arbitrary source chunking. Until then, custom-separated input is exposed -as one unresolved open paragraph. Set `paragraphBoundary: 'markdown'` to -recognize blank lines incrementally while retaining a single soft line break -inside the current paragraph. If both options are supplied, the explicit -Markdown boundary policy takes precedence in core and framework rendering. +The default Unicode paragraph separators are recognized incrementally: CR, LF, +CRLF, NEL, U+001C–U+001E, and U+2029. They match the complete Unicode 17 +`Bidi_Class=Paragraph_Separator` set; U+2028 remains a line separator inside the +same bidi paragraph. `DEFAULT_PARAGRAPH_SEPARATOR_SOURCE` exposes the exact +regular-expression source for adapters that must preserve separators while +rendering. A custom `paragraphSeparator` regular expression is evaluated once +by `finish()` so future-sensitive lookarounds, anchors, and extendable matches +remain invariant across arbitrary source chunking. Until then, +custom-separated input is exposed as one unresolved open paragraph. Set +`paragraphBoundary: 'markdown'` to recognize blank lines incrementally while +retaining a single soft line break inside the current paragraph. If both +options are supplied, the explicit Markdown boundary policy takes precedence +in core and framework rendering. The default `content-majority` policy excludes technical tokens before counting natural-language evidence. Raw-text analysis recognizes closed @@ -80,5 +85,10 @@ The default stream direction remains provisional and revisable until `finish()`. Choose `sticky-majority` only when UI stability is more important than correcting a misleading prefix before completion. +Numeric detection and stream thresholds must be finite. `NaN` and positive or +negative infinity are rejected with `RangeError` instead of silently disabling +direction decisions or stream locking; ordinary finite values retain the +documented clamping behavior. + Run the packaged example after building with `pnpm --filter @bidilens/core example`. diff --git a/packages/core/src/core.test.ts b/packages/core/src/core.test.ts index 70aa57f..40de913 100644 --- a/packages/core/src/core.test.ts +++ b/packages/core/src/core.test.ts @@ -69,6 +69,28 @@ describe('direction detection', () => { } }); + it('keeps Persian combining marks inside opposite-direction isolates', () => { + const source = 'مثلاً right vagus lesion:'; + const plans = planInlineIsolation(source, 'ltr'); + expect(plans).toContainEqual(expect.objectContaining({ + text: 'مثلاً', + direction: 'rtl', + kind: 'opposite-direction-run', + start: 0, + end: 'مثلاً'.length + })); + }); + + it('groups compact abbreviation labels without classifying ordinary prose pronouns', () => { + const source = 'CN X lesion و HR/BP باید حفظ شوند.'; + const ranges = findTechnicalTokenRanges(source); + expect(ranges).toContainEqual(expect.objectContaining({ text: 'CN X', kind: 'identifier' })); + expect(ranges).toContainEqual(expect.objectContaining({ text: 'HR/BP' })); + expect(findTechnicalTokenRanges('I am a developer.')).not.toContainEqual( + expect.objectContaining({ text: 'I', kind: 'identifier' }) + ); + }); + it('still excludes hyphenated tokens built from a known technical segment', () => { expect(findTechnicalTokenRanges('react-markdown').map((range) => range.text)) .toEqual(['react-markdown']); @@ -294,6 +316,30 @@ describe('direction detection', () => { expect(result.paragraphs.map((paragraph) => paragraph.direction)).toEqual(['ltr', 'rtl']); expect(result.mixed).toBe(true); }); + + it.each([ + ['NEL', '\u0085'], + ['file separator', '\u001c'], + ['group separator', '\u001d'], + ['record separator', '\u001e'], + ['paragraph separator', '\u2029'] + ] as const)('uses the Unicode paragraph boundary for %s', (_name, separator) => { + const result = analyzeText(`Hello${separator}سلام`); + expect(result.paragraphs.map((paragraph) => paragraph.text)).toEqual(['Hello', 'سلام']); + expect(result.paragraphs.map((paragraph) => paragraph.direction)).toEqual(['ltr', 'rtl']); + }); + + it('does not promote the Unicode line separator to a paragraph boundary', () => { + const result = analyzeText(`Hello${String.fromCodePoint(0x2028)}سلام`); + expect(result.paragraphs).toHaveLength(1); + }); + + it.each([ + ['minimumStrongCharacters', { minimumStrongCharacters: Number.NaN }], + ['majorityThreshold', { majorityThreshold: Number.POSITIVE_INFINITY }] + ] as const)('rejects non-finite %s detection options', (_name, options) => { + expect(() => detectDirection('سلام', options)).toThrow(/must be a finite number/iu); + }); }); describe('isolation and segmentation', () => { @@ -369,6 +415,15 @@ describe('isolation and segmentation', () => { }); describe('streaming', () => { + it.each([ + ['minimumStrongCharacters', { minimumStrongCharacters: Number.NaN }], + ['majorityThreshold', { majorityThreshold: Number.NEGATIVE_INFINITY }], + ['lockAfterStrongCharacters', { lockAfterStrongCharacters: Number.POSITIVE_INFINITY }], + ['lockMargin', { lockMargin: Number.NaN }] + ] as const)('rejects non-finite %s stream options', (_name, options) => { + expect(() => createBidiStream(options)).toThrow(/must be a finite number/iu); + }); + it('settles the flagship sentence from provisional LTR to revisable RTL', () => { const stream = createBidiStream(); expect(stream.push('React ').direction).toBe('ltr'); @@ -444,6 +499,30 @@ describe('streaming', () => { expect(next.currentParagraph).toMatchObject({ text: 'Hello', direction: 'ltr' }); }); + it.each([ + ['NEL', '\u0085'], + ['file separator', '\u001c'], + ['group separator', '\u001d'], + ['record separator', '\u001e'], + ['paragraph separator', '\u2029'] + ] as const)('keeps default stream paragraphs chunk-invariant across %s', (_name, separator) => { + const source = `Hello${separator}سلام`; + const whole = createBidiStream(); + whole.push(source); + const expected = whole.finish(); + + const chunked = createBidiStream(); + for (const character of source) chunked.push(character); + const actual = chunked.finish(); + + expect(actual.text).toBe(source); + expect(actual.paragraphs.map((paragraph) => paragraph.text)) + .toEqual(['Hello', 'سلام']); + expect(actual.paragraphs.map((paragraph) => paragraph.direction)) + .toEqual(['ltr', 'rtl']); + expect(actual.paragraphs).toEqual(expected.paragraphs); + }); + it.each([ '\n\n\n', '\n\n\n\n', @@ -1009,6 +1088,54 @@ describe('security', () => { expect(report.findings[0]?.sourceRange.utf16.start).toBe(4); }); + it.each([ + ['LF', '\n'], + ['CR', '\r'], + ['CRLF', '\r\n'], + ['NEL', '\u0085'], + ['file separator', '\u001c'], + ['group separator', '\u001d'], + ['record separator', '\u001e'], + ['paragraph separator', '\u2029'] + ] as const)('does not balance controls across a %s boundary', (_name, separator) => { + const report = scanBidiSecurity( + `${BIDI_CONTROLS.RLO}before${separator}after${BIDI_CONTROLS.PDF}`, + { mode: 'strict' } + ); + + expect(report.findings.map((finding) => finding.code)).toEqual(expect.arrayContaining([ + 'BIDI_UNCLOSED_EMBEDDING', + 'BIDI_UNMATCHED_PDF' + ])); + }); + + it('still balances controls within one paragraph', () => { + const report = scanBidiSecurity(`${BIDI_CONTROLS.RLO}safe${BIDI_CONTROLS.PDF}`); + expect(report.findings.map((finding) => finding.code)).not.toEqual(expect.arrayContaining([ + 'BIDI_UNCLOSED_EMBEDDING', + 'BIDI_UNMATCHED_PDF' + ])); + }); + + it('does not balance isolates across a paragraph boundary', () => { + const report = scanBidiSecurity( + `${BIDI_CONTROLS.RLI}before\u2029after${BIDI_CONTROLS.PDI}`, + { mode: 'strict' } + ); + expect(report.findings.map((finding) => finding.code)).toEqual(expect.arrayContaining([ + 'BIDI_UNCLOSED_ISOLATE', + 'BIDI_UNMATCHED_PDI' + ])); + }); + + it('still balances isolates within one paragraph', () => { + const report = scanBidiSecurity(`${BIDI_CONTROLS.RLI}safe${BIDI_CONTROLS.PDI}`); + expect(report.findings.map((finding) => finding.code)).not.toEqual(expect.arrayContaining([ + 'BIDI_UNCLOSED_ISOLATE', + 'BIDI_UNMATCHED_PDI' + ])); + }); + it('has no findings for ordinary Persian with ZWNJ and combining marks', () => { const report = scanBidiSecurity('می\u200Cخواهم دربارهٔ کتاب‌ها بخوانم.'); expect(report.controls).toHaveLength(0); diff --git a/packages/core/src/detect.ts b/packages/core/src/detect.ts index 9faa2c1..0f84fa7 100644 --- a/packages/core/src/detect.ts +++ b/packages/core/src/detect.ts @@ -1,4 +1,6 @@ import { classifyBidiStrongCharacter, classifyCharacter } from './classify.js'; +import { boundedNumberOption } from './options.js'; +import { DEFAULT_PARAGRAPH_SEPARATOR_SOURCE } from './paragraph.js'; import type { DetectionOptions, Direction, @@ -47,8 +49,20 @@ function normalizeOptions(options: DetectionOptions = {}): Required))/gu, 'identifier'); + const words = /\b[A-Za-z][A-Za-z0-9_.-]*\b/gu; const customIdentifiers = customTechnicalIdentifiers(technicalIdentifiers); const uppercaseProse = usesUppercaseProse(text); @@ -536,7 +559,7 @@ function firstBidiStrongCharacter(text: string): Direction { function splitParagraphs(text: string): Array<{ text: string; start: number; end: number }> { const paragraphs: Array<{ text: string; start: number; end: number }> = []; - const separator = /\r\n|\n|\r|\u2029/gu; + const separator = new RegExp(DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, 'gu'); let start = 0; let match: RegExpExecArray | null; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6cd9508..b346da0 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -7,6 +7,7 @@ export * from './intervention.js'; export * from './segments.js'; export * from './stream.js'; export * from './analysis.js'; +export { DEFAULT_PARAGRAPH_SEPARATOR_SOURCE } from './paragraph.js'; // Specification-oriented aliases retained alongside the original concise API. export { analyzeText as analyzePlainText, detectDirection as detectBaseDirection } from './detect.js'; diff --git a/packages/core/src/options.ts b/packages/core/src/options.ts new file mode 100644 index 0000000..10c17d0 --- /dev/null +++ b/packages/core/src/options.ts @@ -0,0 +1,18 @@ +/** + * Validate and clamp a numeric option without allowing NaN or infinities to + * poison direction comparisons. Finite values retain the historical + * clamping behavior; non-finite values are caller errors. + */ +export function boundedNumberOption( + name: string, + value: number | undefined, + defaultValue: number, + minimum: number, + maximum: number +): number { + const resolved = value ?? defaultValue; + if (!Number.isFinite(resolved)) { + throw new RangeError(`${name} must be a finite number.`); + } + return Math.min(maximum, Math.max(minimum, resolved)); +} diff --git a/packages/core/src/paragraph.ts b/packages/core/src/paragraph.ts new file mode 100644 index 0000000..98af857 --- /dev/null +++ b/packages/core/src/paragraph.ts @@ -0,0 +1,18 @@ +/** + * The default paragraph grammar follows the complete Unicode 17 + * Bidi_Class=Paragraph_Separator set. CRLF is listed before CR and LF so it + * is consumed as one separator. U+2028 is intentionally absent: Unicode + * classifies it as a line separator (WS), not a paragraph separator (B). + */ +export const DEFAULT_PARAGRAPH_SEPARATOR_SOURCE = + '\\r\\n|\\n|\\r|\\u0085|[\\u001C-\\u001E]|\\u2029'; + +export function isDefaultParagraphBoundaryCharacter(character: string): boolean { + if (character.length !== 1) return false; + const codeUnit = character.charCodeAt(0); + return codeUnit === 0x0a + || codeUnit === 0x0d + || codeUnit === 0x85 + || (codeUnit >= 0x1c && codeUnit <= 0x1e) + || codeUnit === 0x2029; +} diff --git a/packages/core/src/property.test.ts b/packages/core/src/property.test.ts index 1fa2679..4034b15 100644 --- a/packages/core/src/property.test.ts +++ b/packages/core/src/property.test.ts @@ -77,7 +77,10 @@ describe('property-based invariants', () => { it('produces batch-equivalent final output for arbitrary chunk boundaries', () => { const textArbitrary = fc.array(fc.oneof( fc.string({ maxLength: 24 }), - fc.constantFrom('\n', '\r', '\r\n', '\u2029', 'سلام', 'React', '😀', '`code`', 'https://example.com') + fc.constantFrom( + '\n', '\r', '\r\n', '\u0085', '\u001c', '\u001d', '\u001e', '\u2029', + 'سلام', 'React', '😀', '`code`', 'https://example.com' + ) ), { maxLength: 16 }).map((parts) => parts.join('')); fc.assert(fc.property( textArbitrary, @@ -134,6 +137,10 @@ describe('property-based invariants', () => { ' ', '\n', '\r\n', + '\u0085', + '\u001c', + '\u001d', + '\u001e', '\u2029' ), { minLength: 1, maxLength: 24 }).map((parts) => parts.join('')); diff --git a/packages/core/src/security.ts b/packages/core/src/security.ts index be0099e..55aa442 100644 --- a/packages/core/src/security.ts +++ b/packages/core/src/security.ts @@ -8,6 +8,11 @@ import type { BidiSecuritySeverity } from './types.js'; +const UAX9_PARAGRAPH_SEPARATOR = new RegExp( + `\\r\\n|\\n|\\r|\\u0085|[${String.fromCodePoint(0x1c)}-${String.fromCodePoint(0x1e)}]|\\u2029`, + 'gu' +); + const CONTROL_METADATA = new Map>([ [0x061c, { name: 'ARABIC LETTER MARK', risk: 'low', category: 'mark' }], [0x200e, { name: 'LEFT-TO-RIGHT MARK', risk: 'low', category: 'mark' }], @@ -118,7 +123,10 @@ function lastFrameIndex(stack: readonly FormattingFrame[], kind: FormattingFrame return -1; } -function balanceFindings(controls: readonly BidiControlFinding[]): BidiSecurityFinding[] { +function balanceParagraph( + controls: readonly BidiControlFinding[], + boundary: 'paragraph' | 'text' +): BidiSecurityFinding[] { const findings: BidiSecurityFinding[] = []; const stack: FormattingFrame[] = []; @@ -181,7 +189,7 @@ function balanceFindings(controls: readonly BidiControlFinding[]): BidiSecurityF findings.push({ code: frame.kind === 'isolate' ? 'BIDI_UNCLOSED_ISOLATE' : 'BIDI_UNCLOSED_EMBEDDING', severity: 'high', - message: `${frame.control.name} is not terminated before the end of the text.`, + message: `${frame.control.name} is not terminated before ${boundary === 'paragraph' ? 'the paragraph boundary' : 'the end of the text'}.`, sourceRange: rangeFor(frame.control), remediation: frame.kind === 'isolate' ? 'Add the matching PDI or remove the isolate opener.' @@ -192,6 +200,30 @@ function balanceFindings(controls: readonly BidiControlFinding[]): BidiSecurityF return findings; } +/** + * Bidi formatting state is paragraph-scoped under UAX #9. A PDF/PDI after a + * line or paragraph separator must not close an opener from the preceding + * paragraph, so balance each paragraph independently. + */ +function balanceFindings(text: string, controls: readonly BidiControlFinding[]): BidiSecurityFinding[] { + const findings: BidiSecurityFinding[] = []; + // UAX #9 paragraph separators are CR, LF, NEL, U+001C..U+001E, and + // U+2029. Keep the security scope aligned with the pinned Unicode data. + let controlIndex = 0; + + for (const match of text.matchAll(UAX9_PARAGRAPH_SEPARATOR)) { + const paragraphControls: BidiControlFinding[] = []; + while (controlIndex < controls.length && controls[controlIndex]!.index < match.index) { + paragraphControls.push(controls[controlIndex]!); + controlIndex += 1; + } + findings.push(...balanceParagraph(paragraphControls, 'paragraph')); + } + + findings.push(...balanceParagraph(controls.slice(controlIndex), 'text')); + return findings; +} + function isAsciiIdentifierCharacter(value: string | undefined): boolean { return value !== undefined && /^[A-Za-z0-9_$]$/u.test(value); } @@ -262,7 +294,7 @@ export function scanBidiSecurity( const controls = findBidiControls(text); const findings = [ ...controls.map(controlFinding), - ...balanceFindings(controls), + ...balanceFindings(text, controls), ...invisibleCharacterFindings(text) ].sort((a, b) => a.sourceRange.utf16.start - b.sourceRange.utf16.start || a.code.localeCompare(b.code)); const hasHigh = findings.some((finding) => finding.severity === 'high'); diff --git a/packages/core/src/segments.ts b/packages/core/src/segments.ts index bd6ee11..e4408ac 100644 --- a/packages/core/src/segments.ts +++ b/packages/core/src/segments.ts @@ -77,12 +77,16 @@ function mergeAdjacent(runs: DirectionalRun[]): DirectionalRun[] { function trimNeutralBoundaries(text: string, start: number, end: number): { start: number; end: number } { while (start < end) { const character = text.slice(start).match(/^./su)?.[0]; - if (!character || classifyCharacter(character) !== 'neutral') break; + // Combining marks are bidi-neutral, but they are part of the preceding + // grapheme. Trimming one from an isolate changes the visible word (for + // example Persian `مثلاً` became `مثلا` plus a detached tanwin), so marks + // must anchor an isolation boundary just like a strong character. + if (!character || classifyCharacter(character) !== 'neutral' || /^\p{M}$/u.test(character)) break; start += character.length; } while (end > start) { const character = text.slice(0, end).match(/.$/su)?.[0]; - if (!character || classifyCharacter(character) !== 'neutral') break; + if (!character || classifyCharacter(character) !== 'neutral' || /^\p{M}$/u.test(character)) break; end -= character.length; } return { start, end }; diff --git a/packages/core/src/stream.ts b/packages/core/src/stream.ts index 3a3d0df..4080e3f 100644 --- a/packages/core/src/stream.ts +++ b/packages/core/src/stream.ts @@ -1,5 +1,10 @@ import { DEFAULT_TECHNICAL_IDENTIFIERS, countStrongCharacters, detectDirection } from './detect.js'; import { classifyBidiStrongCharacter, classifyCharacter } from './classify.js'; +import { boundedNumberOption } from './options.js'; +import { + DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, + isDefaultParagraphBoundaryCharacter +} from './paragraph.js'; import type { BidiStreamOptions, BidiStreamSnapshot, @@ -8,8 +13,7 @@ import type { StreamStrategy } from './types.js'; -const DEFAULT_SEPARATOR_SOURCE = '\\r\\n|\\n|\\r|\\u2029'; -const DEFAULT_SEPARATOR = new RegExp(DEFAULT_SEPARATOR_SOURCE, 'g'); +const DEFAULT_SEPARATOR = new RegExp(DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, 'g'); const COMMAND_STARTERS = new Set(['npm', 'pnpm', 'yarn', 'npx', 'git', 'pip', 'python', 'node', 'cargo', 'go', 'docker', 'kubectl']); /** Mirrors the batch acronym bound in `detect.ts`. */ const ACRONYM_MAXIMUM_LENGTH = 5; @@ -200,14 +204,38 @@ export class BidiStream { this.#usesMarkdownSeparator = options.paragraphBoundary === 'markdown'; this.#usesDefaultSeparator = options.paragraphSeparator === undefined && !this.#usesMarkdownSeparator; - this.#minimumStrongCharacters = Math.max(1, options.minimumStrongCharacters ?? 1); - this.#threshold = Math.min(1, Math.max(0.5, options.majorityThreshold ?? 0.5)); + this.#minimumStrongCharacters = boundedNumberOption( + 'minimumStrongCharacters', + options.minimumStrongCharacters, + 1, + 1, + Number.POSITIVE_INFINITY + ); + this.#threshold = boundedNumberOption( + 'majorityThreshold', + options.majorityThreshold, + 0.5, + 0.5, + 1 + ); this.#excludeTechnicalTokens = options.excludeTechnicalTokens; // A single short opposite-language word should remain provisional. Eight // strong characters and a margin of three let the default strategy adopt // a direction while keeping it revisable as more model output arrives. - this.#lockAfter = Math.max(1, options.lockAfterStrongCharacters ?? 8); - this.#lockMargin = Math.max(1, options.lockMargin ?? 3); + this.#lockAfter = boundedNumberOption( + 'lockAfterStrongCharacters', + options.lockAfterStrongCharacters, + 8, + 1, + Number.POSITIVE_INFINITY + ); + this.#lockMargin = boundedNumberOption( + 'lockMargin', + options.lockMargin, + 3, + 1, + Number.POSITIVE_INFINITY + ); this.#technicalIdentifiers = Object.freeze([...(options.technicalIdentifiers ?? [])]); this.#customTechnicalTrie = technicalIdentifierTrie(this.#technicalIdentifiers); this.#policyTokenCustomTrieNode = this.#customTechnicalTrie; @@ -448,7 +476,7 @@ export class BidiStream { #consumeDefaultSeparators(chunk: string, final: boolean): void { const combined = `${this.#pendingCarriageReturn ? '\r' : ''}${chunk}`; this.#pendingCarriageReturn = false; - const separator = new RegExp(DEFAULT_SEPARATOR_SOURCE, 'g'); + const separator = new RegExp(DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, 'g'); let start = 0; let match: RegExpExecArray | null; while ((match = separator.exec(combined)) !== null) { @@ -893,7 +921,7 @@ export class BidiStream { } #processPolicyCharacter(character: string): void { - if (/\r|\n|\u2029/u.test(character)) { + if (isDefaultParagraphBoundaryCharacter(character)) { this.#policyDormantBacktickDelimiter = 0; this.#policySingleDollarOpen = false; } @@ -1014,7 +1042,7 @@ export class BidiStream { } if (this.#policyMode === 'command') { - if (/\r|\n|\u2029/u.test(character)) { + if (isDefaultParagraphBoundaryCharacter(character)) { this.#commitProvisionalPolicyStructure(); return; } @@ -1125,7 +1153,7 @@ export class BidiStream { return; } - if (/\r|\n|\u2029/u.test(character)) { + if (isDefaultParagraphBoundaryCharacter(character)) { this.#commitProvisionalPolicyStructure(); return; } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 587c697..ce3a15d 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -102,7 +102,8 @@ export interface BidiStreamOptions { fallback?: Direction; /** * Paragraph separator used when `finish()` reconciles the complete source. - * The default newline separator is recognized incrementally. An arbitrary + * The default Unicode paragraph separators (CR, LF, CRLF, NEL, + * U+001C..U+001E, and U+2029) are recognized incrementally. An arbitrary * custom RegExp is intentionally finalized only at end-of-stream because * lookarounds, anchors, and extendable matches can depend on future chunks. */ diff --git a/packages/markdown/README.md b/packages/markdown/README.md index a9b169c..fbf3bc6 100644 --- a/packages/markdown/README.md +++ b/packages/markdown/README.md @@ -27,16 +27,25 @@ const html = await unified() For Markdown-It, install the optional peer and call the typed plugin once: +BidiLens builds its adapter against Markdown-It 15 and verifies representative +Markdown-It releases `13.0.2`, `14.3.1`, and `15.0.1` with strict packed +TypeScript consumers and the complete canonical corpus. The supported peer +range is `13.x`, `14.x`, and `15.x`; the matrix does not claim every patch +release. Markdown-It 15 bundles its own declarations; the +older lines use their matching `@types/markdown-it` package. Its public +`MarkdownItCompatible` boundary intentionally exposes only the stable parser +surface BidiLens uses, so host parser types remain authoritative instead of +being duplicated by this package. + ```bash npm install @bidilens/markdown markdown-it ``` -TypeScript hosts that import `MarkdownIt` directly should also install its -declarations as a direct development dependency: - -```sh -npm install --save-dev @types/markdown-it -``` +TypeScript hosts using Markdown-It 13 or 14 that import `MarkdownIt` directly +should also install the matching declarations as a direct development +dependency (for example, `@types/markdown-it@13.0.9` or +`@types/markdown-it@14.2.0`). Markdown-It 15 already ships its declarations, so +do not add `@types/markdown-it` for that line. ```ts import MarkdownIt from 'markdown-it'; diff --git a/packages/markdown/package.json b/packages/markdown/package.json index 52d46dd..17cefae 100644 --- a/packages/markdown/package.json +++ b/packages/markdown/package.json @@ -51,12 +51,11 @@ "dependencies": { "@bidilens/core": "workspace:*", "@types/hast": "^3.0.4", - "@types/markdown-it": "^14.1.2", "@types/mdast": "^4.0.4", "unist-util-visit": "^5.0.0" }, "peerDependencies": { - "markdown-it": "^14.0.0" + "markdown-it": "^13.0.2 || ^14.0.0 || ^15.0.0" }, "peerDependenciesMeta": { "markdown-it": { @@ -64,7 +63,7 @@ } }, "devDependencies": { - "markdown-it": "^14.1.0", + "markdown-it": "^15.0.1", "rehype-stringify": "^10.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", diff --git a/packages/markdown/src/index.ts b/packages/markdown/src/index.ts index 8282dd2..5da2e83 100644 --- a/packages/markdown/src/index.ts +++ b/packages/markdown/src/index.ts @@ -1,7 +1,5 @@ import type { Element, ElementContent, Root as HastRoot, Text as HastText } from 'hast'; import type { Content, Root as MdastRoot } from 'mdast'; -import type MarkdownIt from 'markdown-it'; -import type Token from 'markdown-it/lib/token.mjs'; import { detectDirection, needsBidiIntervention, @@ -19,7 +17,10 @@ import type { BidiMarkdownDocument, BidiMarkdownStreamSession, BidiMarkdownStreamOptions, - MarkdownBidiOptions + MarkdownBidiOptions, + MarkdownItRuntime, + MarkdownItToken, + MarkdownItCompatible } from './types.js'; export type { @@ -33,10 +34,15 @@ export type { MarkdownBidiOptions, MarkdownBlockAnnotation, MarkdownDirtyRegion, + MarkdownItCompatible, MarkdownSecurityDelta, MarkdownSourceRange } from './types.js'; +function internalMarkdownIt(markdownIt: MarkdownItCompatible): MarkdownItRuntime { + return markdownIt as unknown as MarkdownItRuntime; +} + const MDAST_BLOCK_TYPES = new Set([ 'paragraph', 'heading', 'blockquote', 'listItem', 'tableCell', 'definition' ]); @@ -256,6 +262,13 @@ export function rehypeBidi(options: MarkdownBidiOptions = {}) { const configuredMarkdownIt = new WeakMap(); +function assertFiniteMarkdownOption(name: string, value: number | undefined): number | undefined { + if (value !== undefined && !Number.isFinite(value)) { + throw new RangeError(`${name} must be a finite number.`); + } + return value; +} + function markdownItConfigurationKey(options: MarkdownBidiOptions): string { const strategy = options.strategy ?? 'content-majority'; const majorityStrategy = strategy === 'content-majority' @@ -265,8 +278,8 @@ function markdownItConfigurationKey(options: MarkdownBidiOptions): string { strategy, fallback: options.fallback ?? options.inheritedDirection ?? 'ltr', inheritedDirection: options.inheritedDirection ?? 'ltr', - minimumStrongCharacters: Math.max(1, options.minimumStrongCharacters ?? 1), - majorityThreshold: Math.min(1, Math.max(0.5, options.majorityThreshold ?? 0.5)), + minimumStrongCharacters: Math.max(1, assertFiniteMarkdownOption('minimumStrongCharacters', options.minimumStrongCharacters) ?? 1), + majorityThreshold: Math.min(1, Math.max(0.5, assertFiniteMarkdownOption('majorityThreshold', options.majorityThreshold) ?? 0.5)), excludeTechnicalTokens: options.excludeTechnicalTokens ?? majorityStrategy, technicalIdentifiers: options.technicalIdentifiers ?? [], blockClassName: options.blockClassName ?? 'bidilens-block', @@ -277,13 +290,13 @@ function markdownItConfigurationKey(options: MarkdownBidiOptions): string { }); } -function markdownItClass(token: Token | undefined, className: string): void { +function markdownItClass(token: MarkdownItToken | undefined, className: string): void { if (!token) return; if (token.attrJoin) token.attrJoin('class', className); else token.attrSet('class', className); } -function markdownItBlockContent(tokens: Token[], index: number, closeType: string): string { +function markdownItBlockContent(tokens: MarkdownItToken[], index: number, closeType: string): string { const openType = tokens[index]?.type; let nested = 0; const values: string[] = []; @@ -302,7 +315,8 @@ function markdownItBlockContent(tokens: Token[], index: number, closeType: strin } /** Markdown-It adapter with the same content-majority policy as the AST plugins. */ -export function markdownItBidi(md: MarkdownIt, inputOptions: MarkdownBidiOptions = {}): void { +export function markdownItBidi(markdownIt: MarkdownItCompatible, inputOptions: MarkdownBidiOptions = {}): void { + const md = internalMarkdownIt(markdownIt); const options: MarkdownBidiOptions = { ...inputOptions, ...(inputOptions.technicalIdentifiers @@ -321,8 +335,8 @@ export function markdownItBidi(md: MarkdownIt, inputOptions: MarkdownBidiOptions let activeDirection: 'ltr' | 'rtl' | null = null; const blockClassName = options.blockClassName ?? 'bidilens-block'; const codeClassName = options.codeClassName ?? 'bidilens-code'; - const interventionCache = new WeakMap(); - const tokensNeedIntervention = (tokens: Token[]): boolean => { + const interventionCache = new WeakMap(); + const tokensNeedIntervention = (tokens: MarkdownItToken[]): boolean => { const cached = interventionCache.get(tokens); if (cached !== undefined) return cached; const required = tokens.some((token) => (token.type === 'inline' @@ -461,7 +475,7 @@ export function markdownItBidi(md: MarkdownIt, inputOptions: MarkdownBidiOptions const renderValue = (part: string): string => { if (!originalText) return escape(part); const copy = [...tokens]; - copy[index] = { ...tokens[index]!, content: part } as Token; + copy[index] = { ...tokens[index]!, content: part }; return originalText(copy, index, renderOptions, env, self); }; let rendered = ''; @@ -491,12 +505,12 @@ export function markdownItBidi(md: MarkdownIt, inputOptions: MarkdownBidiOptions /** Exact batch document used as the rich stream's final equivalence oracle. */ export function analyzeBidiMarkdown( - markdownIt: MarkdownIt, + markdownIt: MarkdownItCompatible, source: string, options: BidiMarkdownStreamOptions = {} ): BidiMarkdownDocument { markdownItBidi(markdownIt, options); - return analyzeConfiguredBidiMarkdown(markdownIt, source, options); + return analyzeConfiguredBidiMarkdown(internalMarkdownIt(markdownIt), source, options); } /** @@ -505,9 +519,9 @@ export function analyzeBidiMarkdown( * through the same batch pipeline as `analyzeBidiMarkdown()`. */ export function createBidiMarkdownStream( - markdownIt: MarkdownIt, + markdownIt: MarkdownItCompatible, options: BidiMarkdownStreamOptions = {} ): BidiMarkdownStreamSession { markdownItBidi(markdownIt, options); - return new BidiMarkdownStream(markdownIt, options); + return new BidiMarkdownStream(internalMarkdownIt(markdownIt), options); } diff --git a/packages/markdown/src/markdown.test.ts b/packages/markdown/src/markdown.test.ts index 829b597..2c10c03 100644 --- a/packages/markdown/src/markdown.test.ts +++ b/packages/markdown/src/markdown.test.ts @@ -14,6 +14,7 @@ import { } from './index.js'; import { stablePrefixEnd } from './stream.js'; import type { Root as MdastRoot } from 'mdast'; +import { CHATGPT_MIXED_DIRECTION_MARKDOWN } from '../../../scripts/fixtures/chatgpt-mixed-direction.js'; async function render(markdown: string): Promise { return String(await unified() @@ -42,6 +43,13 @@ describe('Markdown plugins', () => { expect(html).not.toContain('data-bidilens'); }); + it.each([ + ['minimumStrongCharacters', { minimumStrongCharacters: Number.NaN }], + ['majorityThreshold', { majorityThreshold: Number.POSITIVE_INFINITY }] + ] as const)('rejects non-finite Markdown-It %s options before configuration', (_name, options) => { + expect(() => markdownItBidi(new MarkdownIt({ html: false }), options)).toThrow(/must be a finite number/iu); + }); + it('leaves an LTR-only MDAST tree structurally unchanged', () => { const tree = { type: 'root', @@ -91,6 +99,23 @@ describe('Markdown plugins', () => { expect(html).toContain('>React'); }); + it('preserves caller alignment while adding semantic direction metadata', () => { + const md = new MarkdownIt({ html: false }); + const originalParagraphOpen = md.renderer.rules.paragraph_open; + md.renderer.rules.paragraph_open = (tokens, index, options, env, self) => { + tokens[index]?.attrSet('style', 'text-align:left'); + return originalParagraphOpen + ? originalParagraphOpen(tokens, index, options, env, self) + : self.renderToken(tokens, index, options); + }; + markdownItBidi(md); + + const html = md.render('React یک کتابخانه جاوااسکریپت بسیار محبوب است.'); + expect(html).toContain('dir="rtl"'); + expect(html).toContain('style="text-align:left"'); + expect(html).not.toContain('text-align:right'); + }); + it('annotates Persian paragraphs', async () => { const html = await render('سلام دنیا'); expect(html).toContain('dir="rtl"'); @@ -208,6 +233,21 @@ describe('Markdown plugins', () => { expect(english).toContain('>کتاب'); }); + it('keeps screenshot-derived medical Markdown logically ordered and mark-safe', () => { + const md = new MarkdownIt({ html: false }); + const document = analyzeBidiMarkdown(md, CHATGPT_MIXED_DIRECTION_MARKDOWN); + + expect(document.source).toBe(CHATGPT_MIXED_DIRECTION_MARKDOWN); + expect(document.html).toContain('>مثلاً'); + expect(document.html).toContain('>CN X'); + expect(document.html).toContain('>ICH:

'); + expect(document.html).toContain('dir="rtl"'); + // Direction/isolation metadata must not take ownership of caller layout. + expect(document.html).not.toContain('text-align'); + expect(document.blocks.some((block) => block.text.includes('CN X') && block.direction === 'rtl')).toBe(true); + expect(document.blocks.some((block) => block.text.includes('Uvula runs away') && block.direction === 'ltr')).toBe(true); + }); + it('propagates caller-specific identifiers through Markdown detection and isolation', () => { const md = new MarkdownIt({ html: false }); markdownItBidi(md, { technicalIdentifiers: ['InternalPlatform'] }); diff --git a/packages/markdown/src/stream.ts b/packages/markdown/src/stream.ts index e353071..6567b10 100644 --- a/packages/markdown/src/stream.ts +++ b/packages/markdown/src/stream.ts @@ -1,5 +1,3 @@ -import type MarkdownIt from 'markdown-it'; -import type Token from 'markdown-it/lib/token.mjs'; import { BidiStream, analyzeBlock, @@ -21,7 +19,9 @@ import type { MarkdownAstNode, MarkdownDirtyRegion, MarkdownSecurityDelta, - MarkdownSourceRange + MarkdownSourceRange, + MarkdownItRuntime, + MarkdownItToken } from './types.js'; const OPEN_BLOCKS = new Map([ @@ -63,7 +63,7 @@ function lineOffsets(source: string): number[] { return offsets; } -function sourceMapForToken(tokens: readonly Token[], tokenIndex: number): [number, number] | null { +function sourceMapForToken(tokens: readonly MarkdownItToken[], tokenIndex: number): [number, number] | null { const token = tokens[tokenIndex]; if (!token) return null; if (token.map) return [token.map[0], token.map[1]]; @@ -89,7 +89,7 @@ function rangeForSourceMap( return { start, end }; } -function nestedBlockText(tokens: readonly Token[], index: number, closeType: string): string { +function nestedBlockText(tokens: readonly MarkdownItToken[], index: number, closeType: string): string { const openType = tokens[index]?.type; let nested = 0; const values: string[] = []; @@ -107,7 +107,7 @@ function nestedBlockText(tokens: readonly Token[], index: number, closeType: str return values.join(' '); } -function textForBlock(tokens: readonly Token[], index: number, closeType: string): string { +function textForBlock(tokens: readonly MarkdownItToken[], index: number, closeType: string): string { const token = tokens[index]; if (!token) return ''; if (token.type === 'blockquote_open' || token.type === 'list_item_open') { @@ -121,7 +121,7 @@ function blockAnalysisOptions(options: BidiMarkdownStreamOptions): BidiMarkdownS } function collectBlocks( - tokens: readonly Token[], + tokens: readonly MarkdownItToken[], source: string, options: BidiMarkdownStreamOptions ): BidiMarkdownBlock[] { @@ -161,12 +161,12 @@ function collectBlocks( return blocks; } -function attributesForToken(token: Token): Record | undefined { +function attributesForToken(token: MarkdownItToken): Record | undefined { if (!token.attrs?.length) return undefined; - return Object.fromEntries(token.attrs.map(([name, value]) => [name, value])); + return Object.fromEntries(token.attrs.map(([name, value]) => [name, String(value)])); } -function serializeToken(token: Token, annotation: BidiMarkdownBlock | undefined): MarkdownAstNode { +function serializeToken(token: MarkdownItToken, annotation: BidiMarkdownBlock | undefined): MarkdownAstNode { const attributes = attributesForToken(token); return { type: token.type, @@ -193,7 +193,7 @@ function serializeToken(token: Token, annotation: BidiMarkdownBlock | undefined) /** Runs the exact configured Markdown-It batch pipeline used for final reconciliation. */ export function analyzeConfiguredBidiMarkdown( - markdownIt: MarkdownIt, + markdownIt: MarkdownItRuntime, source: string, options: BidiMarkdownStreamOptions = {} ): BidiMarkdownDocument { @@ -908,7 +908,7 @@ function emptyDocument(options: BidiMarkdownStreamOptions): BidiMarkdownDocument } export class BidiMarkdownStream implements BidiMarkdownStreamSession { - readonly #markdownIt: MarkdownIt; + readonly #markdownIt: MarkdownItRuntime; readonly #options: BidiMarkdownStreamOptions; #directionStream: BidiStream; #pendingDirectionStream: BidiStream; @@ -968,7 +968,7 @@ export class BidiMarkdownStream implements BidiMarkdownStreamSession { #fenceLinePhase: 'container' | 'marker' | 'trailing' | 'invalid' = 'container'; #fenceMarkerCount = 0; - constructor(markdownIt: MarkdownIt, options: BidiMarkdownStreamOptions = {}) { + constructor(markdownIt: MarkdownItRuntime, options: BidiMarkdownStreamOptions = {}) { this.#markdownIt = markdownIt; this.#options = Object.freeze({ ...options, diff --git a/packages/markdown/src/types.ts b/packages/markdown/src/types.ts index c36cc2c..d5b585d 100644 --- a/packages/markdown/src/types.ts +++ b/packages/markdown/src/types.ts @@ -10,6 +10,79 @@ import type { ResolvedDirection } from '@bidilens/core'; +/** + * Version-neutral subset of the Markdown-It instance used by BidiLens. + * + * Keeping the public boundary structural prevents one parser type major from + * leaking into consumers that use another supported parser line. The packed + * compatibility gate verifies the complete implementation against the real + * v13, v14, and v15 parser packages. + */ +export interface MarkdownItCompatible { + parse(source: string, environment: unknown): unknown[]; + readonly options: unknown; + readonly renderer: unknown; + readonly utils: unknown; +} + +/** + * Small structural view of the Markdown-It runtime used by the adapter. + * + * Markdown-It 13/14 publish their declarations through `@types/markdown-it` + * and expose internal token declarations under `lib/`. Markdown-It 15 ships + * its own declarations, removes those private export paths, and exports the + * instance type as a named `MarkdownIt` type. Depending on either declaration + * layout would make this package fail to build for one of the supported host + * lines. These local structural types describe only the stable plugin surface + * and keep parser-specific types out of BidiLens' public declarations. + */ +export type MarkdownItTokenAttribute = [name: string, value: string | number]; + +export interface MarkdownItToken { + type: string; + tag: string; + attrs: MarkdownItTokenAttribute[] | null; + map: [number, number] | null; + nesting: -1 | 0 | 1; + level: number; + children: MarkdownItToken[] | null; + content: string; + markup: string; + info: string; + block: boolean; + hidden: boolean; + attrSet(name: string, value: string | number): void; + attrJoin(name: string, value: string | number): void; +} + +export interface MarkdownItRuntimeOptions { + readonly html?: boolean; + readonly [key: string]: unknown; +} + +export interface MarkdownItRenderer { + readonly rules: Record; + renderToken(tokens: MarkdownItToken[], index: number, options: unknown): string; + render(tokens: MarkdownItToken[], options: unknown, environment?: unknown): string; +} + +export interface MarkdownItRenderRule { + ( + tokens: MarkdownItToken[], + index: number, + options: unknown, + environment: unknown, + renderer: MarkdownItRenderer + ): string; +} + +export interface MarkdownItRuntime { + parse(source: string, environment: unknown): MarkdownItToken[]; + readonly options: MarkdownItRuntimeOptions; + readonly renderer: MarkdownItRenderer; + readonly utils?: { readonly escapeHtml?: (value: string) => string }; +} + export interface MarkdownBidiOptions extends DetectionOptions { fallback?: Direction; blockClassName?: string; diff --git a/packages/react/src/index.tsx b/packages/react/src/index.tsx index 6fd5f28..b68d240 100644 --- a/packages/react/src/index.tsx +++ b/packages/react/src/index.tsx @@ -1,5 +1,6 @@ import { createBidiStream, + DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, detectDirection, needsBidiIntervention, planInlineIsolation, @@ -320,7 +321,7 @@ function streamParagraphParts( ? customSeparator.flags.replaceAll('y', '') : `${customSeparator.flags.replaceAll('y', '')}g` ) - : /\r\n|\n|\r|\u2029/gu; + : new RegExp(DEFAULT_PARAGRAPH_SEPARATOR_SOURCE, 'gu'); const parts: Array<{ text: string; separator: string }> = []; let start = 0; let match: RegExpExecArray | null; diff --git a/packages/react/src/react.test.tsx b/packages/react/src/react.test.tsx index ceb4962..69e3742 100644 --- a/packages/react/src/react.test.tsx +++ b/packages/react/src/react.test.tsx @@ -260,4 +260,14 @@ describe('React adapter', () => { expect(container.textContent).toBe(source); expect(container.querySelectorAll('article > span')).toHaveLength(4); }); + + it('renders Unicode paragraph separators as independent streaming blocks', () => { + const source = `Hello${String.fromCodePoint(0x0085)}سلام`; + const container = document.createElement('div'); + container.innerHTML = renderToStaticMarkup(); + expect(container.textContent).toBe(source); + expect(container.querySelectorAll('article > span')).toHaveLength(2); + expect(container.querySelector('article > span')?.getAttribute('dir')).toBe('ltr'); + expect(container.querySelectorAll('article > span')[1]?.getAttribute('dir')).toBe('rtl'); + }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f0590c..62fe6d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,9 +30,6 @@ importers: '@playwright/test': specifier: ^1.62.1 version: 1.62.1 - '@types/markdown-it': - specifier: ^14.1.2 - version: 14.1.2 '@types/node': specifier: ^24.10.0 version: 24.13.3 @@ -64,8 +61,8 @@ importers: specifier: ^29.1.1 version: 29.1.1 markdown-it: - specifier: ^14.1.0 - version: 14.3.0 + specifier: ^15.0.1 + version: 15.0.1 tsx: specifier: ^4.23.12 version: 4.23.12 @@ -91,8 +88,8 @@ importers: specifier: workspace:* version: link:../../packages/react markdown-it: - specifier: ^14.1.0 - version: 14.3.0 + specifier: ^15.0.1 + version: 15.0.1 react: specifier: ^19.2.8 version: 19.2.8 @@ -112,9 +109,6 @@ importers: specifier: ^11.0.5 version: 11.0.5 devDependencies: - '@types/markdown-it': - specifier: ^14.1.2 - version: 14.1.2 '@vitejs/plugin-react': specifier: ^6.0.5 version: 6.0.5(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.2)(tsx@4.23.12)) @@ -175,9 +169,6 @@ importers: '@types/hast': specifier: ^3.0.4 version: 3.0.5 - '@types/markdown-it': - specifier: ^14.1.2 - version: 14.1.2 '@types/mdast': specifier: ^4.0.4 version: 4.0.4 @@ -186,8 +177,8 @@ importers: version: 5.1.0 devDependencies: markdown-it: - specifier: ^14.1.0 - version: 14.3.0 + specifier: ^15.0.1 + version: 15.0.1 rehype-stringify: specifier: ^10.0.1 version: 10.0.1 @@ -987,18 +978,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/linkify-it@5.0.0': - resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - - '@types/markdown-it@14.1.2': - resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} - '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/mdurl@2.0.0': - resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -1215,6 +1197,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + argparse@3.0.0: + resolution: {integrity: sha512-BOp5NMrHqKxmq/OLr+clzzrRxgOKSLkcjmkWuChp7Irqwn4s74WjOBPIgWfA/HMcBnVkZ5XEuf9uUqzlpfCQ6A==} + aria-query@5.3.1: resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} engines: {node: '>= 0.4'} @@ -1420,10 +1405,6 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - entities@7.0.1: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} @@ -1871,8 +1852,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - linkify-it@5.0.2: - resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + linkify-it@6.1.0: + resolution: {integrity: sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==} load-tsconfig@0.2.5: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} @@ -1909,8 +1890,8 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - markdown-it@14.3.0: - resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} + markdown-it@15.0.1: + resolution: {integrity: sha512-9/7gE95FNPkfUWrjJIoHZza2iLmuJlPD0UNMxPi7bxUrbCR525YZY0r+zyfes0dZI5ZZ/uNIXUJca0pJvtw41g==} hasBin: true markdown-table@3.0.4: @@ -1975,8 +1956,8 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -2539,8 +2520,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + uc.micro@3.0.0: + resolution: {integrity: sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==} ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} @@ -3339,19 +3320,10 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/linkify-it@5.0.0': {} - - '@types/markdown-it@14.1.2': - dependencies: - '@types/linkify-it': 5.0.0 - '@types/mdurl': 2.0.0 - '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 - '@types/mdurl@2.0.0': {} - '@types/ms@2.1.0': {} '@types/node@12.20.55': {} @@ -3625,6 +3597,8 @@ snapshots: argparse@2.0.1: {} + argparse@3.0.0: {} + aria-query@5.3.1: {} array-union@2.1.0: {} @@ -3795,8 +3769,6 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 - entities@4.5.0: {} - entities@7.0.1: {} entities@8.0.0: {} @@ -4261,9 +4233,9 @@ snapshots: lines-and-columns@1.2.4: {} - linkify-it@5.0.2: + linkify-it@6.1.0: dependencies: - uc.micro: 2.1.0 + uc.micro: 3.0.0 load-tsconfig@0.2.5: {} @@ -4297,14 +4269,14 @@ snapshots: dependencies: semver: 7.8.5 - markdown-it@14.3.0: + markdown-it@15.0.1: dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.2 - mdurl: 2.0.0 + argparse: 3.0.0 + entities: 8.0.0 + linkify-it: 6.1.0 + mdurl: 2.1.0 punycode.js: 2.3.1 - uc.micro: 2.1.0 + uc.micro: 3.0.0 markdown-table@3.0.4: {} @@ -4476,7 +4448,7 @@ snapshots: mdn-data@2.27.1: {} - mdurl@2.0.0: {} + mdurl@2.1.0: {} merge2@1.4.1: {} @@ -5187,7 +5159,7 @@ snapshots: typescript@6.0.3: {} - uc.micro@2.1.0: {} + uc.micro@3.0.0: {} ufo@1.6.4: {} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 78ff6bc..8c93946 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -482,7 +482,9 @@ fn split_paragraphs(text: &str) -> Vec> { index + 1 } } - '\n' | '\u{2029}' => index + character.len_utf8(), + '\n' | '\u{0085}' | '\u{001C}'..='\u{001E}' | '\u{2029}' => { + index + character.len_utf8() + } _ => continue, }; ranges.push(start..index); diff --git a/rust/src/security.rs b/rust/src/security.rs index 8c21d1e..73f90f8 100644 --- a/rust/src/security.rs +++ b/rust/src/security.rs @@ -126,35 +126,26 @@ fn control_code(category: BidiControlCategory) -> &'static str { } } -/// Scans hidden bidi formatting and related invisible characters without mutation. -#[must_use] -pub fn scan_bidi_security(text: &str) -> SecurityReport { - let controls = find_bidi_controls(text); - let mut findings: Vec = controls - .iter() - .map(|control| SecurityFinding { - code: control_code(control.category), - message: format!( - "{} ({}) is invisible and changes bidirectional interpretation.", - control.name, control.code_point - ), - source_range: control.source_range.clone(), - risk: control.risk, - }) - .collect(); +#[derive(Clone, Copy)] +enum FrameKind { + Embedding, + Isolate, +} - #[derive(Clone, Copy)] - enum FrameKind { - Embedding, - Isolate, - } +fn balance_paragraph( + controls: &[BidiControlFinding], + boundary: &str, + findings: &mut Vec, +) { let mut stack: Vec<(FrameKind, usize)> = Vec::new(); for (index, control) in controls.iter().enumerate() { match control.character { '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' => { stack.push((FrameKind::Embedding, index)); } - '\u{2066}' | '\u{2067}' | '\u{2068}' => stack.push((FrameKind::Isolate, index)), + '\u{2066}' | '\u{2067}' | '\u{2068}' => { + stack.push((FrameKind::Isolate, index)); + } '\u{202C}' => { let isolate = stack .iter() @@ -165,7 +156,8 @@ pub fn scan_bidi_security(text: &str) -> SecurityReport { if embedding.is_none() || embedding <= isolate { findings.push(SecurityFinding { code: "BIDI_UNMATCHED_PDF", - message: "POP DIRECTIONAL FORMATTING has no matching active embedding or override.".to_owned(), + message: "POP DIRECTIONAL FORMATTING has no matching active embedding or override." + .to_owned(), source_range: control.source_range.clone(), risk: BidiControlRisk::High, }); @@ -211,14 +203,75 @@ pub fn scan_bidi_security(text: &str) -> SecurityReport { FrameKind::Embedding => "BIDI_UNCLOSED_EMBEDDING", FrameKind::Isolate => "BIDI_UNCLOSED_ISOLATE", }, - message: format!( - "{} is not terminated before the end of the text.", - control.name - ), + message: format!("{} is not terminated before {}.", control.name, boundary), source_range: control.source_range.clone(), risk: BidiControlRisk::High, }); } +} + +fn balance_findings( + text: &str, + controls: &[BidiControlFinding], + findings: &mut Vec, +) { + let mut control_index = 0; + let mut byte_index = 0; + while byte_index < text.len() { + let character = text[byte_index..] + .chars() + .next() + .expect("byte index must be on a character boundary"); + let character_len = character.len_utf8(); + let boundary_len = + if character == '\r' && text[byte_index + character_len..].starts_with('\n') { + character_len + '\n'.len_utf8() + } else { + character_len + }; + let is_paragraph_boundary = matches!( + character, + '\r' | '\n' | '\u{0085}' | '\u{001C}'..='\u{001E}' | '\u{2029}' + ); + if is_paragraph_boundary { + let paragraph_control_start = control_index; + while control_index < controls.len() + && controls[control_index].source_range.bytes.start < byte_index + { + control_index += 1; + } + balance_paragraph( + &controls[paragraph_control_start..control_index], + "the paragraph boundary", + findings, + ); + // The controls list contains only formatting characters, so no + // control can begin inside the separator itself. Continue after + // CRLF as one UAX paragraph boundary. + } + byte_index += boundary_len; + } + balance_paragraph(&controls[control_index..], "the end of the text", findings); +} + +/// Scans hidden bidi formatting and related invisible characters without mutation. +#[must_use] +pub fn scan_bidi_security(text: &str) -> SecurityReport { + let controls = find_bidi_controls(text); + let mut findings: Vec = controls + .iter() + .map(|control| SecurityFinding { + code: control_code(control.category), + message: format!( + "{} ({}) is invisible and changes bidirectional interpretation.", + control.name, control.code_point + ), + source_range: control.source_range.clone(), + risk: control.risk, + }) + .collect(); + + balance_findings(text, &controls, &mut findings); let mut utf16_start = 0; let characters: Vec<_> = text diff --git a/rust/tests/conformance.rs b/rust/tests/conformance.rs index 3068016..8008cb3 100644 --- a/rust/tests/conformance.rs +++ b/rust/tests/conformance.rs @@ -325,6 +325,20 @@ fn source_offsets_cover_bytes_utf16_and_code_points() { assert_eq!(react.source_range.code_points, 2..7); } +#[test] +fn all_unicode_paragraph_separators_split_analysis_without_changing_source() { + for separator in ["\u{0085}", "\u{001C}", "\u{001D}", "\u{001E}", "\u{2029}"] { + let source = format!("Hello{separator}سلام"); + let analysis = analyze(&source, &AnalysisOptions::default()).expect("valid defaults"); + assert_eq!(analysis.paragraphs.len(), 2, "separator {separator:?}"); + assert_eq!(analysis.paragraphs[0].text, "Hello"); + assert_eq!(analysis.paragraphs[1].text, "سلام"); + assert_eq!(analysis.paragraphs[0].direction, Direction::Ltr); + assert_eq!(analysis.paragraphs[1].direction, Direction::Rtl); + assert_eq!(analysis.text, source); + } +} + #[test] fn security_reports_controls_balance_and_invisibles() { let report = scan_bidi_security("safe\u{202E}hidden\u{200B}"); @@ -335,6 +349,53 @@ fn security_reports_controls_balance_and_invisibles() { assert!(!report.safe); } +#[test] +fn formatting_controls_do_not_balance_across_paragraph_boundaries() { + for separator in [ + "\n", "\r", "\r\n", "\u{0085}", "\u{001C}", "\u{001D}", "\u{001E}", "\u{2029}", + ] { + let source = format!("{}before{separator}after{}", '\u{202E}', '\u{202C}'); + let report = scan_bidi_security(&source); + let codes: BTreeSet<_> = report.findings.iter().map(|value| value.code).collect(); + assert!( + codes.contains("BIDI_UNCLOSED_EMBEDDING"), + "missing unclosed embedding for {separator:?}" + ); + assert!( + codes.contains("BIDI_UNMATCHED_PDF"), + "missing unmatched PDF for {separator:?}" + ); + } +} + +#[test] +fn formatting_controls_balance_within_one_paragraph() { + let report = scan_bidi_security("before\u{202E}inside\u{202C}after"); + assert!(!report.findings.iter().any(|finding| matches!( + finding.code, + "BIDI_UNCLOSED_EMBEDDING" | "BIDI_UNMATCHED_PDF" + ))); +} + +#[test] +fn isolates_do_not_balance_across_paragraph_boundaries() { + let report = scan_bidi_security("\u{2067}before\u{2029}after\u{2069}"); + let codes: BTreeSet<_> = report.findings.iter().map(|value| value.code).collect(); + assert!(codes.contains("BIDI_UNCLOSED_ISOLATE")); + assert!(codes.contains("BIDI_UNMATCHED_PDI")); +} + +#[test] +fn isolates_balance_within_one_paragraph() { + let report = scan_bidi_security("\u{2067}inside\u{2069}"); + assert!( + !report + .findings + .iter() + .any(|finding| matches!(finding.code, "BIDI_UNCLOSED_ISOLATE" | "BIDI_UNMATCHED_PDI")) + ); +} + #[test] fn default_security_report_matches_an_empty_scan() { assert_eq!(SecurityReport::default(), scan_bidi_security("")); diff --git a/scripts/check-docs.ts b/scripts/check-docs.ts index 694ab31..9f63255 100644 --- a/scripts/check-docs.ts +++ b/scripts/check-docs.ts @@ -32,6 +32,12 @@ const releaseDocuments = [ 'CITATION.cff', 'docs/V1_BUILD_REPORT.md' ]; +const currentCorpusDocuments = [ + 'README.md', + 'IMPACT.md', + 'docs/REQUIREMENT_MATRIX.md', + 'docs/V1_BUILD_REPORT.md' +]; const staleReleasePhrases = [ 'maintained release-candidate scope', 'once the canonical repository exists', @@ -60,6 +66,19 @@ const markdownLink = /(?; + devDependencies?: Record; + peerDependencies?: Record; +} + +const root = process.cwd(); +const supportedMarkdownIt: MarkdownItTarget[] = [ + { version: '13.0.2', types: '13.0.9', comparison: 'exact' }, + { version: '14.3.1', types: '14.2.0', comparison: 'exact' }, + // Markdown-It 15 bundles its declarations and removes the old internal + // `markdown-it/lib/*` exports. The public structural boundary is designed + // to keep this host upgrade source-compatible without leaking those types. + { version: '15.0.1', comparison: 'semantic' } +]; +const expectedPeerRange = '^13.0.2 || ^14.0.0 || ^15.0.0'; +const reportOutput = process.env.BIDILENS_MARKDOWN_IT_REPORT_DIR; +const structuralFixtures: CorpusFixture[] = [ + { + id: 'compat-pure-ltr-no-op', + text: 'Plain English Markdown stays exactly as it is.', + expectNoOp: true + }, + { + id: 'compat-heading-inline-code', + text: '# راهنمای React\n\nدستور `pnpm test` را اجرا کنید.' + }, + { + id: 'compat-list-and-blockquote', + text: '- React یک کتابخانه محبوب است.\n- Vue هم محبوب است.\n\n> API باید پایدار بماند.' + }, + { + id: 'compat-table', + text: '| ابزار | توضیح |\n| --- | --- |\n| React | یک کتابخانه محبوب |' + }, + { + id: 'compat-link-and-punctuation', + text: 'مستندات [React](https://react.dev/docs?q=rtl) را بخوانید؛ سپس اجرا کنید.' + }, + { + id: 'compat-fenced-code', + text: 'نمونه:\n\n```ts\nconst direction = "rtl";\n```\n\nاین کد امن است.' + }, + { + id: 'compat-raw-html-disabled', + text: 'متن React' + }, + { + id: 'compat-soft-break', + text: 'React یک کتابخانه محبوب است\nو TypeScript هم پشتیبانی می‌شود.' + }, + { + id: 'compat-chatgpt-medical-mixed-blocks', + text: CHATGPT_MIXED_DIRECTION_MARKDOWN + } +]; + +function pnpmInvocation(args: string[]): { program: string; args: string[]; shell: boolean } { + if (process.platform !== 'win32') return { program: 'pnpm', args, shell: false }; + + const candidates = [ + process.env.npm_execpath, + process.env.PNPM_HOME ? resolve(process.env.PNPM_HOME, 'pnpm.cjs') : undefined, + process.env.APPDATA + ? resolve(process.env.APPDATA, 'npm', 'node_modules', 'pnpm', 'bin', 'pnpm.cjs') + : undefined + ].filter((candidate): candidate is string => Boolean(candidate)); + const cli = candidates.find((candidate) => existsSync(candidate)); + if (cli) return { program: process.execPath, args: [cli, ...args], shell: false }; + return { program: 'pnpm', args, shell: true }; +} + +function command(program: string, args: string[], cwd = root): Promise { + return new Promise((resolveCommand, reject) => { + const invocation = program === 'pnpm' + ? pnpmInvocation(args) + : { program, args, shell: false }; + const child = spawn(invocation.program, invocation.args, { + cwd, + shell: invocation.shell, + stdio: ['ignore', 'pipe', 'pipe'] + }); + let stdout = ''; + let stderr = ''; + child.stdout.setEncoding('utf8'); + child.stderr.setEncoding('utf8'); + child.stdout.on('data', (chunk: string) => { stdout += chunk; }); + child.stderr.on('data', (chunk: string) => { stderr += chunk; }); + child.on('error', reject); + child.on('close', (code) => { + if (code === 0) resolveCommand(stdout); + else reject(new Error(`${program} ${args.join(' ')} failed with ${code}.\n${stdout}${stderr}`)); + }); + }); +} + +function assert(condition: unknown, message: string): asserts condition { + if (!condition) throw new Error(message); +} + +function firstDifference(left: unknown, right: unknown, path = '$'): string | null { + if (Object.is(left, right)) return null; + if (typeof left !== typeof right || left === null || right === null) return path; + if (typeof left !== 'object') return path; + if (Array.isArray(left) !== Array.isArray(right)) return path; + const leftRecord = left as Record; + const rightRecord = right as Record; + const keys = new Set([...Object.keys(leftRecord), ...Object.keys(rightRecord)]); + for (const key of keys) { + const difference = firstDifference( + leftRecord[key], + rightRecord[key], + Array.isArray(left) ? `${path}[${key}]` : `${path}.${key}` + ); + if (difference) return difference; + } + return null; +} + +/** + * Keep v15's host-parser compatibility comparison semantic without dropping + * the annotated AST entirely. Markdown-It 15's linkify v6 intentionally + * changes URL punctuation ownership and href encoding; mask only the content + * and href of linkify nodes while retaining token structure and all BidiLens + * direction/annotation attributes. Linkify versions may also assign a + * trailing punctuation mark to the link text or to the following text token; + * normalize only that punctuation/whitespace at the immediate link boundary. + */ +function semanticAst( + node: unknown, + insideLinkify = false, + normalizeLeadingBoundary = false, + normalizeTrailingBoundary = false +): unknown { + if (Array.isArray(node)) { + let linkifyState = insideLinkify; + return node.map((child, index) => { + const previous = index > 0 ? node[index - 1] : undefined; + const next = index + 1 < node.length ? node[index + 1] : undefined; + const isLinkifyClose = (value: unknown): boolean => ( + Boolean(value) + && typeof value === 'object' + && !Array.isArray(value) + && (value as Record).type === 'link_close' + && (value as Record).markup === 'linkify' + ); + const isLinkifyOpen = (value: unknown): boolean => ( + Boolean(value) + && typeof value === 'object' + && !Array.isArray(value) + && (value as Record).type === 'link_open' + && (value as Record).markup === 'linkify' + ); + const result = semanticAst( + child, + linkifyState, + isLinkifyClose(previous), + isLinkifyOpen(next) + ); + if (child && typeof child === 'object' && !Array.isArray(child)) { + const token = child as Record; + if (token.type === 'link_open' && token.markup === 'linkify') { + linkifyState = true; + } else if (token.type === 'link_close' && token.markup === 'linkify') { + linkifyState = false; + } + } + return result; + }); + } + if (!node || typeof node !== 'object') return node; + const source = node as Record; + const linkify = insideLinkify || source.markup === 'linkify'; + const result: Record = {}; + for (const [key, value] of Object.entries(source)) { + if (key === 'attributes' && linkify && value && typeof value === 'object' && !Array.isArray(value)) { + const attributes = { ...(value as Record) }; + if (source.type === 'link_open') delete attributes.href; + result[key] = attributes; + continue; + } + if (key === 'content' && linkify && source.type === 'text') { + result[key] = ''; + continue; + } + if ( + key === 'content' + && source.type === 'text' + && (normalizeLeadingBoundary || normalizeTrailingBoundary) + && typeof value === 'string' + ) { + let normalized = value; + if (normalizeLeadingBoundary) normalized = normalized.replace(/^[\s\p{P}\p{S}]+/u, ''); + if (normalizeTrailingBoundary) normalized = normalized.replace(/[\s\p{P}\p{S}]+$/u, ''); + result[key] = normalized; + continue; + } + result[key] = key === 'children' ? semanticAst(value, linkify) : value; + } + return result; +} + +function semanticReport(report: unknown): unknown { + if (!Array.isArray(report)) return report; + return report.map((fixture) => { + const entry = fixture as Record; + return { + id: entry.id, + blocks: entry.blocks, + ast: semanticAst(entry.ast), + security: entry.security + }; + }); +} + +async function packPackage(packageName: string, destination: string): Promise { + const before = new Set(await readdir(destination)); + await command('pnpm', ['--filter', packageName, 'pack', '--pack-destination', destination]); + const created = (await readdir(destination)) + .find((file) => !before.has(file) && file.endsWith('.tgz')); + assert(created, `${packageName}: pnpm pack did not create a tarball.`); + return resolve(destination, created); +} + +async function runVersionProbe( + target: typeof supportedMarkdownIt[number], + coreTarball: string, + markdownTarball: string, + fixtures: CorpusFixture[], + temporary: string +): Promise { + const { version } = target; + const consumer = resolve(temporary, `markdown-it-${version}`); + await mkdir(consumer, { recursive: true }); + await writeFile(resolve(consumer, 'package.json'), JSON.stringify({ + name: `bidilens-markdown-it-${version.replaceAll('.', '-')}-consumer`, + private: true, + type: 'module', + dependencies: { + '@bidilens/core': `file:${coreTarball.replaceAll('\\', '/')}`, + '@bidilens/markdown': `file:${markdownTarball.replaceAll('\\', '/')}`, + 'markdown-it': version + }, + devDependencies: { + ...(target.types ? { '@types/markdown-it': target.types } : {}), + typescript: '6.0.3' + }, + pnpm: { + overrides: { + '@bidilens/core': `file:${coreTarball.replaceAll('\\', '/')}`, + '@bidilens/markdown': `file:${markdownTarball.replaceAll('\\', '/')}` + } + } + }, null, 2)); + await writeFile(resolve(consumer, 'tsconfig.json'), JSON.stringify({ + compilerOptions: { + target: 'ES2022', + module: 'NodeNext', + moduleResolution: 'NodeNext', + strict: true, + noEmit: true, + skipLibCheck: false + }, + include: ['index.ts'] + }, null, 2)); + await writeFile(resolve(consumer, 'index.ts'), ` +import MarkdownIt from 'markdown-it'; +import { + analyzeBidiMarkdown, + createBidiMarkdownStream, + markdownItBidi, + type BidiMarkdownDocument, + type BidiMarkdownStreamSession +} from '@bidilens/markdown'; + +const source = 'React یک کتابخانه جاوااسکریپت بسیار محبوب است.'; +const parser = new MarkdownIt({ html: false, linkify: true, typographer: true }); +markdownItBidi(parser); +const document: BidiMarkdownDocument = analyzeBidiMarkdown(new MarkdownIt(), source); +const stream: BidiMarkdownStreamSession = createBidiMarkdownStream(new MarkdownIt()); +stream.push(source); +void [parser.render(source), document.html, stream.finish().document.html]; +`); + await writeFile(resolve(consumer, 'fixtures.json'), JSON.stringify(fixtures)); + await writeFile(resolve(consumer, 'probe.mjs'), ` +import { strict as assert } from 'node:assert'; +import { readFile } from 'node:fs/promises'; +import MarkdownIt from 'markdown-it'; +import { analyzeBidiMarkdown, createBidiMarkdownStream, markdownItBidi } from '@bidilens/markdown'; + +const fixtures = JSON.parse(await readFile(new URL('./fixtures.json', import.meta.url), 'utf8')); +const results = []; +for (const fixture of fixtures) { + const options = { html: false, linkify: true, typographer: true }; + const baseline = new MarkdownIt(options).render(fixture.text); + const pluginParser = new MarkdownIt(options); + markdownItBidi(pluginParser); + const pluginHtml = pluginParser.render(fixture.text); + const batch = analyzeBidiMarkdown(new MarkdownIt(options), fixture.text); + assert.equal(batch.source, fixture.text, fixture.id + ': batch source changed'); + assert.equal(batch.html, pluginHtml, fixture.id + ': plugin and batch HTML differ'); + if (fixture.expectNoOp) { + assert.equal(pluginHtml, baseline, fixture.id + ': pure-LTR output was modified'); + } + + const stream = createBidiMarkdownStream(new MarkdownIt(options)); + for (const character of fixture.text) stream.push(character); + const final = stream.finish(); + assert.equal(final.source, fixture.text, fixture.id + ': stream source changed'); + assert.deepEqual(final.document, batch, fixture.id + ': stream and batch documents differ'); + + results.push({ + id: fixture.id, + baseline, + pluginHtml, + blocks: batch.blocks.map((block) => ({ + kind: block.kind, + text: block.text, + direction: block.direction, + intervention: block.intervention, + isolation: block.analysis.isolations.map((item) => ({ + start: item.start, + end: item.end, + text: item.text, + direction: item.direction, + kind: item.kind + })) + })), + ast: batch.ast, + security: batch.security + }); +} +process.stdout.write(JSON.stringify(results)); +`); + await command('pnpm', ['install', '--strict-peer-dependencies'], consumer); + await command('pnpm', ['exec', 'tsc', '--noEmit'], consumer); + const declarations = await readFile(resolve( + consumer, + 'node_modules/@bidilens/markdown/dist/index.d.ts' + ), 'utf8'); + assert( + !/from ["']markdown-it(?:\/[^"']*)?["']/u.test(declarations), + `Markdown-It ${version}: packed declarations leaked host parser types.` + ); + return JSON.parse(await command(process.execPath, ['probe.mjs'], consumer)) as unknown; +} + +const manifest = JSON.parse( + await readFile(resolve(root, 'packages/markdown/package.json'), 'utf8') +) as PackageManifest; +assert( + manifest.peerDependencies?.['markdown-it'] === expectedPeerRange, + `@bidilens/markdown must declare markdown-it peer ${expectedPeerRange}.` +); +assert( + manifest.dependencies?.['@types/markdown-it'] === undefined, + '@bidilens/markdown must not expose one Markdown-It type line as a runtime dependency.' +); +assert( + manifest.devDependencies?.['markdown-it']?.startsWith('^15.') === true, + '@bidilens/markdown must build its source against the latest supported Markdown-It line.' +); +const fixtures = JSON.parse( + await readFile(resolve(root, 'corpus/cases.json'), 'utf8') +) as CorpusFixture[]; +assert(fixtures.length >= 900, 'The compatibility gate requires the complete canonical corpus.'); +const probeFixtures = [...fixtures, ...structuralFixtures]; + +await command('pnpm', ['--filter', '@bidilens/core', 'run', 'build']); +await command('pnpm', ['--filter', '@bidilens/markdown', 'run', 'build']); +const temporary = await mkdtemp(resolve(tmpdir(), 'bidilens-markdown-it-compat-')); +try { + const packs = resolve(temporary, 'packs'); + await mkdir(packs, { recursive: true }); + const coreTarball = await packPackage('@bidilens/core', packs); + const markdownTarball = await packPackage('@bidilens/markdown', packs); + const reports = new Map(); + for (const target of supportedMarkdownIt) { + const report = await runVersionProbe( + target, + coreTarball, + markdownTarball, + probeFixtures, + temporary + ); + reports.set(target.version, report); + if (reportOutput) { + await mkdir(resolve(reportOutput), { recursive: true }); + await writeFile( + resolve(reportOutput, `markdown-it-${target.version}.json`), + JSON.stringify(report, null, 2) + ); + } + console.log(`Markdown-It ${target.version}: strict TypeScript consumer, ${fixtures.length} canonical fixtures, and ${structuralFixtures.length} host-structure fixtures passed.`); + } + const referenceTarget = supportedMarkdownIt[0]; + assert(referenceTarget, 'The Markdown-It compatibility matrix must contain a reference target.'); + const referenceVersion = referenceTarget.version; + const reference = reports.get(referenceVersion); + for (const target of supportedMarkdownIt.slice(1)) { + const candidate = reports.get(target.version); + const left = target.comparison === 'semantic' ? semanticReport(reference) : reference; + const right = target.comparison === 'semantic' ? semanticReport(candidate) : candidate; + const difference = firstDifference(left, right); + assert( + difference === null, + target.comparison === 'semantic' + ? `Markdown-It ${referenceVersion} and ${target.version} produced different BidiLens semantic reports at ${difference ?? 'an unknown path'}.` + : `Markdown-It ${referenceVersion} and ${target.version} produced different reports at ${difference ?? 'an unknown path'}.` + ); + } + console.log('Markdown-It 13.0.2 and 14.3.1 produced identical full reports; Markdown-It 15.0.1 produced identical BidiLens semantic reports (host parser rendering differences are expected after its linkify v6 change).'); + console.log(`Packed @bidilens/markdown ${basename(markdownTarball)} installed under strict peer resolution for all supported parser lines.`); +} finally { + await rm(temporary, { recursive: true, force: true }); +} diff --git a/scripts/fixtures/chatgpt-mixed-direction.ts b/scripts/fixtures/chatgpt-mixed-direction.ts new file mode 100644 index 0000000..1b20691 --- /dev/null +++ b/scripts/fixtures/chatgpt-mixed-direction.ts @@ -0,0 +1,61 @@ +/** + * Rendering-only regression material transcribed from user-supplied AI + * screenshots. The medical wording is not clinical guidance and is included + * solely to exercise mixed Persian/English Markdown boundaries. + */ +export const CHATGPT_MIXED_DIRECTION_MARKDOWN = [ + '## 🧠 CN IX و CN X — و صدا gag خیلی مهم برای بلع', + '', + 'ER scenario:', + 'می‌آید با stroke بیمار بعد از', + '', + '- dysphagia = مشکل بلع', + '- hoarseness = گرفتگی صدا', + '- uvula deviation', + '- gag reflex abnormal', + '', + '## CN IX = Glossopharyngeal nerve', + '', + '### 🚑 یک‌طرفه آسیب ببینید؟ CN X اگر', + '', + 'مثلاً right vagus lesion:', + '', + '- palate سمت همان weak می‌شود', + '- uvula به سمت سالم می‌رود', + '- hoarseness ممکن است ایجاد شود', + '', + '🔥 یعنی:', + '', + '> Uvula runs away from the lesion.', + '', + 'Right CN X lesion → uvula deviates LEFT', + '', + '## High-yield pair', + '', + 'IX = tongue/pharynx sensory', + 'X = palate/pharynx/larynx motor', + '', + 'و برای امتحان:', + '', + '> Gag afferent = IX', + '> Gag efferent = X', + '', + 'این قسمت برای brainstem localization nuclei of IX and X in medulla مهم می‌شود.', + '', + '### 🩸 تصویر ذهنی', + '', + 'ICH:', + '', + '> شکل گرفته → بافت اطراف را فشار می‌دهد hematoma داخل مغز ترکیده → یک رگ داخل مغز', + '', + '| CT | hyperdense داخل parenchyma لکه/توده | hyperdense در sulci/cisterns خون |', + '| --- | --- | --- |', + '| ICH | basal ganglia / thalamus / pons / cerebellum | فشار داخل مغز |', + '', + 'SAH:', + '', + '> در اطراف مغز پخش می‌شود CSF روی سطح مغز پاره می‌شود → خون وارد aneurysm می‌شود.', + '', + 'context قدیمی نه، مشکل تقریباً قطعا از اندازه یا محتوای session جدید کار می‌کند و session همان را بررسی می‌کنم context را دقیقاً راه‌های حفظ همان کار و کردن API key است.' +].join('\n'); + diff --git a/scripts/release-check.ts b/scripts/release-check.ts index 131d9a6..02d14cb 100644 --- a/scripts/release-check.ts +++ b/scripts/release-check.ts @@ -223,10 +223,9 @@ async function verifyConsumer(tarballs: Map, consumer: string): ); Object.assign(dependencies, { '@playwright/test': '1.62.0', - '@types/markdown-it': '14.1.2', '@vue/server-renderer': '3.5.40', jsdom: '29.1.1', - 'markdown-it': '14.3.0', + 'markdown-it': '15.0.1', react: '19.2.8', 'react-dom': '19.2.8', vue: '3.5.40', diff --git a/tests/visual/demo.spec.ts b/tests/visual/demo.spec.ts index 9341359..a4779ba 100644 --- a/tests/visual/demo.spec.ts +++ b/tests/visual/demo.spec.ts @@ -7,6 +7,10 @@ const FLAGSHIP = 'React یک کتابخانه جاوااسکریپت بسیار const SHARED = 'The Persian word کتاب means “book”.'; test('falls back when the browser clipboard API never settles', async ({ page }) => { + // This case intentionally waits for two clipboard timeout paths. Leave room + // for a cold Vite startup on slower hosted Windows/browser combinations. + test.setTimeout(60_000); + await page.addInitScript(() => { Object.defineProperty(navigator, 'clipboard', { configurable: true, @@ -33,11 +37,21 @@ test('falls back when the browser clipboard API never settles', async ({ page }) }); test('exercises the offline bilingual playground, controls, corpus, copy, and exports', async ({ page }) => { + const demoManifest = JSON.parse( + await readFile(new URL('../../apps/demo/package.json', import.meta.url), 'utf8') + ) as { version: string }; + const corpusFixtures = JSON.parse( + await readFile(new URL('../../corpus/cases.json', import.meta.url), 'utf8') + ) as unknown[]; const initialHash = new URLSearchParams({ text: SHARED }).toString(); await page.goto(`${DEMO_ORIGIN}/#${initialHash}`); const input = page.getByLabel('Input Markdown'); const direction = page.locator('.metric').filter({ hasText: 'Direction' }).locator('strong'); + await expect(page.locator('.eyebrow')).toHaveText(`BidiLens v${demoManifest.version}`); + await expect(page.locator('.corpus-panel .panel-title small')).toHaveText( + `Search all ${corpusFixtures.length.toLocaleString('en-US')} bundled cases and load one into the playground.` + ); await expect(input).toHaveValue(SHARED); await expect(direction).toHaveText('ltr'); @@ -121,5 +135,12 @@ test('exercises the offline bilingual playground, controls, corpus, copy, and ex await page.getByRole('button', { name: 'فارسی' }).click(); await expect(page.locator('main')).toHaveAttribute('lang', 'fa'); await expect(page.locator('main')).toHaveAttribute('dir', 'rtl'); + const persianVersion = demoManifest.version + .replaceAll('.', '٫') + .replace(/\d/gu, (digit) => '۰۱۲۳۴۵۶۷۸۹'[Number(digit)]!); + await expect(page.locator('.eyebrow')).toHaveText(`BidiLens نسخهٔ ${persianVersion}`); + await expect(page.locator('.corpus-panel .panel-title small')).toHaveText( + `در هر ${corpusFixtures.length.toLocaleString('fa-IR')} نمونه جست‌وجو کنید و یکی را در محیط بارگذاری کنید.` + ); await expect(page.getByRole('button', { name: 'English' })).toBeVisible(); }); diff --git a/tests/visual/flagship.spec.ts b/tests/visual/flagship.spec.ts index d1bb8f9..4875806 100644 --- a/tests/visual/flagship.spec.ts +++ b/tests/visual/flagship.spec.ts @@ -5,6 +5,7 @@ import MarkdownIt from 'markdown-it'; import { createBidiStream } from '../../packages/core/src/index.js'; import { renderBidiHtml } from '../../packages/html/src/index.js'; import { markdownItBidi } from '../../packages/markdown/src/index.js'; +import { CHATGPT_MIXED_DIRECTION_MARKDOWN } from '../../scripts/fixtures/chatgpt-mixed-direction.js'; import { expectBidiBlock, expectLogicalClipboard, @@ -170,4 +171,27 @@ test.describe('flagship mixed-direction rendering', () => { expect(await fixture.locator('h1').textContent()).toBe('React یک کتابخانه بسیار محبوب است.'); await expect(fixture).toHaveScreenshot('structured-markdown.png'); }); + + test('keeps screenshot-derived Persian medical prose and technical labels stable', async ({ page }) => { + const markdown = new MarkdownIt({ html: false }); + markdownItBidi(markdown); + const html = markdown.render(CHATGPT_MIXED_DIRECTION_MARKDOWN); + expect(html).not.toContain('text-align'); + await page.setContent(` + +
${html}
+ `); + + const fixture = page.locator('#fixture'); + const isolateTexts = await fixture.locator('bdi').allTextContents(); + expect(isolateTexts).toContain('مثلاً'); + expect(isolateTexts).toContain('CN X'); + await expect(fixture.locator('p').filter({ hasText: 'ICH:' })).toHaveAttribute('dir', 'ltr'); + await expect(fixture.locator('p[data-bidilens-block]').filter({ hasText: 'Uvula runs away' })).toHaveAttribute('dir', 'ltr'); + await expect(fixture.locator('bdi').filter({ hasText: 'مثلاً' })).toHaveAttribute('dir', 'rtl'); + expect(await fixture.evaluate((element) => element.textContent)).toContain('right vagus lesion:'); + }); }); diff --git a/unicode/README.md b/unicode/README.md index f0e7823..e47771f 100644 --- a/unicode/README.md +++ b/unicode/README.md @@ -8,6 +8,14 @@ strict strong-character behavior, while pinned general categories identify natural-language letters without depending on the host JavaScript runtime's Unicode version. +Unicode 17 remains the reproducible release baseline. Unicode 18.0.0 is still +the Consortium's prepublication/beta line as of 2026-08-23, with a planned +September 2026 final release; BidiLens deliberately does not ship beta UCD +data. After the final data is published, upgrade through the pinned-file and +checksum review process below rather than silently following host-runtime +Unicode changes. See the [Unicode 18 beta notice](https://www.unicode.org/versions/beta-18.0.0.html) +for the upstream status. + The source file and generated table are checked into the repository so normal builds and runtime analysis are offline. To verify them: