Files
Chrome-RTL/docs/superpowers/plans/2026-07-13-persian-rtl-reliability.md
arsam 2ee5cb30a9 Import documentation: docs/superpowers/plans/2026-07-13-persian-rtl-reliability.md
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:07:35 +03:30

7.9 KiB

Persian RTL Reliability Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make the extension conservatively correct Persian text direction, add Vazirmatn only to author-unstyled Persian text, remain responsive during streaming AI chats, and provide a clearer accessible popup.

Architecture: Keep the dependency-free Manifest V3 structure. Replace the corrupted broad Arabic-range detector with testable Persian-specific helpers inside the isolated content script, apply reversible DOM mutations, and coalesce mutation work by semantic block. Keep settings in chrome.storage.local and make the popup a small controller over the same schema.

Tech Stack: Chrome Extensions Manifest V3, plain JavaScript, HTML/CSS, Node.js, jsdom 29.

Global Constraints

  • Detect Persian text only; Arabic-only and Hebrew text do not trigger changes.
  • Never rewrite text, punctuation, or Latin digits.
  • Any author-specified font family counts as styled, including generic and inherited families.
  • Work automatically on all supported websites and optimize for streaming AI chats without site-specific selectors.
  • All mutations must be reversible without a reload.
  • This folder is not a Git repository, so verification checkpoints replace commit steps.

Task 1: Real UTF-8 Detection and Direction Contract

Files:

  • Create: test/content-engine.js
  • Modify: src/content.js
  • Remove after replacement: test/integration-v2.js, test/regex-test.js

Interfaces:

  • Consumes: the content script's automatic bootstrap with a mocked chrome API.

  • Produces: Persian detection based on Persian-specific letters; conservative rtl/auto decisions and byte-identical text.

  • Step 1: Add failing fixtures for این متن فارسی است, Arabic-only هذا نص عربي, mixed English/Persian text, and نسخه 1234567890.

  • Step 2: Run node test/content-engine.js; expect failures for Persian detection and Arabic-only isolation against the corrupted current range.

  • Step 3: Replace the range with explicit Unicode escapes for Persian-specific letters plus a broader Arabic-script letter count used only after a Persian trigger. Classify first-strong Persian blocks as rtl, English-leading mixed blocks as auto, and preserve the original text exactly.

  • Step 4: Run node test/content-engine.js; expect all direction and integrity assertions to pass.

Task 2: Conservative Targets and Author-Font Detection

Files:

  • Modify: test/content-engine.js
  • Modify: src/content.js

Interfaces:

  • Consumes: processTextNode(node, votedBlocks) and reversible element markers.

  • Produces: semantic block targeting, explicit-direction preservation, and hasAuthorFont(element): boolean behavior.

  • Step 1: Add failing cases for existing dir="rtl", sensible inherited direction, inline Arial, stylesheet font-family: sans-serif, inherited body font, and a document with no author font.

  • Step 2: Run node test/content-engine.js; expect the current unconditional Vazirmatn behavior to fail the author-font cases.

  • Step 3: Implement author-font inspection by walking the element/ancestor chain and checking matching author stylesheet declarations plus inline declarations. Apply Vazirmatn only when no declaration exists; isolate inaccessible stylesheet errors.

  • Step 4: Refine target selection so paragraph/list/heading/message-sized containers win over broad sections, while code, SVG, MathML, and editable content remain protected.

  • Step 5: Run node test/content-engine.js; expect all font and target cases to pass.

Task 3: Streaming, Inputs, Frames, and Reversible Lifecycle

Files:

  • Modify: test/content-engine.js
  • Modify: test/edge-cases.js
  • Modify: src/content.js
  • Modify: manifest.json

Interfaces:

  • Consumes: queued text nodes/roots and storage change callbacks.

  • Produces: one scheduled processing pass per burst, reversible teardown/reapply, and related-frame coverage through Manifest V3 fields.

  • Step 1: Add asynchronous tests that append a streaming Persian response in several character-data mutations, toggle settings off/on, and verify text identity plus restored dir/font state.

  • Step 2: Run node test/content-engine.js and node test/edge-cases.js; expect streaming/lifecycle failures where stale direction or styling remains.

  • Step 3: Coalesce work by block and re-evaluate a previously processed block when streamed text changes its classification. Clear queues and observers during teardown.

  • Step 4: Keep inputs at dir="auto" without rewriting their values, and apply the unstyled-font policy consistently.

  • Step 5: Add match_origin_as_fallback: true beside all_frames for related about:, data:, blob:, and filesystem: frames.

  • Step 6: Run both tests; expect zero failures and no unhandled jsdom errors.

Task 4: Accessible Popup and Settings Migration

Files:

  • Create: test/popup.js
  • Modify: popup/popup.html
  • Modify: popup/popup.css
  • Modify: popup/popup.js

Interfaces:

  • Consumes: settings { enabled, fixDirection, useFont, fixInputs, disabledSites } with legacy values safely defaulted.

  • Produces: current-site status, master/site/direction/font/input controls, and safe unsupported-page/error states.

  • Step 1: Add popup controller tests with mocked tabs/storage for a normal HTTPS tab, chrome://extensions, storage failure, dependency disabling, and setting persistence.

  • Step 2: Run node test/popup.js; expect failure because current markup lacks status and fixDirection.

  • Step 3: Update markup and copy to expose the approved five controls and a live status region. Use native checkbox semantics and explicit labels.

  • Step 4: Update styles with visible keyboard focus, sufficient contrast, disabled states, compact spacing, and status icons/text that do not rely on color.

  • Step 5: Update controller to use chrome.runtime.lastError, tolerate missing tab URLs, disable site controls for unsupported pages, and migrate the old settings shape without data loss.

  • Step 6: Run node test/popup.js; expect all controller and accessibility assertions to pass.

Task 5: Demo, Documentation, and Complete Verification

Files:

  • Modify: demo.html
  • Modify: README.md
  • Modify: package.json
  • Modify: manifest.json

Interfaces:

  • Consumes: the final behavior and test commands.

  • Produces: correctly encoded manual fixtures, accurate installation/behavior documentation, and a single test entry point.

  • Step 1: Replace mojibake in user-visible metadata, popup copy, README, demo, test labels, and Persian fixtures with valid UTF-8.

  • Step 2: Add a streaming-chat demo that appends Persian text incrementally without converting its Latin digits.

  • Step 3: Add package scripts: "test": "node test/content-engine.js && node test/edge-cases.js && node test/popup.js" and "check:encoding": "node test/encoding.js"; add an encoding test that rejects known mojibake markers and requires real Persian fixtures.

  • Step 4: Run npm test; expect all suites to pass.

  • Step 5: Run npm run check:encoding; expect Encoding check passed.

  • Step 6: Parse manifest.json with Node and inspect the popup/demo in a Chromium browser if available; record any browser-only validation still required.

Self-Review

  • Spec coverage: direction, Persian-only scope, digit preservation, font policy, streaming, popup, reversibility, errors, demo, and tests are each assigned above.
  • Placeholder scan: no unresolved implementation placeholders remain.
  • Interface consistency: the shared settings keys are enabled, fixDirection, useFont, fixInputs, and disabledSites in content, popup, and tests.