This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
npm run build # Build for Chrome (default)
npm run build firefox # Build for Firefox
npm run watch # Watch mode with auto-rebuild
npm run lint # ESLint on src/
npm run lint:fix # Auto-fix linting issues
npm run lint:ff # Firefox web-ext validation
npm run pack # Pack extension for all targets → packages/Build output goes to jiten.reader/ directory. Load as unpacked extension in browser for testing.
Node.js 22.x required.
src/apps/ajb.ts- Content script (runs on all pages)src/background-worker/background-worker.ts- Service workersrc/views/widget.ts- Extension popupsrc/views/settings.ts- Settings page
src/apps/integration/registry.ts- Central foreground state (Registry singleton)src/apps/batches/batch-controller.ts- Parsing pipeline orchestrationsrc/apps/parser/base.parser.ts- Abstract parser base classsrc/background-worker/parser/parser.ts- Background text parser
src/shared/configuration/types.ts- ConfigurationSchemasrc/shared/jiten/types.ts- JitenCard, JitenToken, JitenCardStatesrc/shared/host-meta/types.ts- HostMeta, PredefinedHostMeta
src/shared/messages/background/- Commands to service workersrc/shared/messages/foreground/- Commands to content scriptssrc/shared/messages/broadcast/- Commands to all contexts
JitenReader is a Manifest V3 browser extension that parses Japanese text using Jiten.moe. Supports Chrome (v116+) and Firefox (v126+).
Browser Extension:
├── Service Worker (Background) → src/background-worker/background-worker.ts
├── Content Scripts → src/apps/ajb.ts (injected into all frames)
├── Popup UI → src/views/widget.ts
├── Settings Page → src/views/settings.ts
└── Shared Libraries → src/shared/ (common code for all contexts)
src/apps/ - Content script applications (foreground context)
ajb.ts- Main entry, initialises parsers, popup, status bar, keybindsparser/- Parsing engines (see Parser System below)popup/- Popup UI manager and word displayintegration/- Registry, host evaluation, keybind manager, event delegationtext-highlighter/- Word colouration and highlightingbatches/- Batch text processing: paragraph extraction, token applicationsequence/- AbortableSequence for parse request managementparagraph-reader/- DOM text extraction into Paragraph fragmentsstatus-bar/- Bottom status bar showing parse statistics
src/background-worker/ - Service worker (background context)
jiten/- Jiten API integration and deck managementparser/- Japanese text parsing: Parser, ParseController, WorkerQueuejiten-card-actions/- Card state management (grade, forget, update)lookup/- Word lookup controllerlib/- Command handler collection and registration
src/shared/ - Shared code accessible from all contexts
messages/- Message passing system (see Message System below)configuration/- User settings schema, get/set, profilesjiten/- Jiten API wrappers (parse, review, add/remove vocabulary)anki/- AnkiConnect API wrappershost-meta/- Host configuration and metadataextension/- Chrome/Firefox API wrappers (runtime, tabs, storage)dom/- DOM utilities (on, createElement, displayToast)
src/views/ - HTML pages and controllers
widget.html/ts- Popup UIsettings.html/ts- Settings pageelements/- Web Components (profile selector, keybind input, etc.)
src/styles/ - SCSS stylesheets
theme/- Reusable theme components
scripts/ - Build tooling
webpack.mjs- Webpack config (auto-discovers entry points)transform-manifest.mjs- Chrome↔Firefox manifest transformbuild.mjs- Build orchestrator
BaseParser (abstract)
├── AutomaticParser - Parse on page load via observers
│ ├── MokuroParser - Mokuro manga reader
│ ├── MokuroLegacyParser - Legacy Mokuro support
│ ├── SatoriReaderParser - Satori Reader (desktop/mobile modes)
│ ├── BunproParser - BunPro grammar site
│ ├── AozoraParser - Aozora Bunko literature
│ ├── ReadwokParser - ReadWok
│ ├── TtsuParser - TTSU
│ └── ExStaticParser - Explainable Japanese Static
└── TriggerParser - Manual parsing via button/keybind
└── NoParser - Disabled, shows error on parse attempt
Custom parsers: src/apps/parser/custom-parsers/
Factory: src/apps/parser/get-custom-parser.ts
Content Script Service Worker
│ │
├── Parser.parsePage() │
│ ↓ │
├── BatchController │
│ .registerNodes() │
│ ↓ │
├── getParagraphs() │
│ → Paragraph[] │
│ ↓ │
├── ParseCommand.send() ─────────→├── ParseCommandHandler
│ │ ↓
│ ├── ParseController
│ │ .queueParagraph()
│ │ ↓
│ ├── WorkerQueue
│ │ ↓
│ ├── Parser.parse()
│ │ → Jiten API
│ │ ↓
├←── SequenceSuccessCommand ──────┤
│ ↓ │
└── applyTokens() │
→ DOM updated │
Registry singleton in src/apps/integration/registry.ts holds all foreground state:
parsers: BaseParser[]- Active parsersbatchController: BatchController- Parsing pipelinesequenceManager: SequenceManager- Abortable sequencessentenceManager: SentenceManager- Sentence state trackinghostEvaluator: HostEvaluator- Host configuration resolverwordEventDelegator: WordEventDelegator- Click/hover delegationevents: EventCollection- Custom event emitterpopupManager?: PopupManager- Popup lifecyclestatusBar?: StatusBar- Stats displaycards: Map<string, JitenCard>- Card cache bywordId/readingIndextextHighlighterOptions- Highlighting configuration
Commands extend base classes in src/shared/messages/lib/:
BackgroundCommand<Args, Result>- Content → Service Worker (call/send)ForegroundCommand<Args, Result>- Service Worker → Content ScriptBroadcastCommand<Args>- Any → All contexts (fire-and-forget)
Background (foreground → worker):
ParseCommand- Parse text sequencesLookupTextCommand- Look up wordFetchDecksCommand- Fetch Jiten decksGradeCardCommand- Grade card reviewForgetCardCommand- Forget/suspend cardUpdateCardStateCommand- Refresh card stateAbortRequestCommand- Cancel parse requestOpenSettingsCommand- Open settings page
Foreground (worker → content):
SequenceSuccessCommand- Return parsed tokensSequenceErrorCommand- Return parse errorSequenceAbortedCommand- Confirm abortToastCommand- Display notificationParsePageCommand/ParseSelectionCommand- Trigger parsing
Broadcast (any → all):
ConfigurationUpdatedCommand- Settings changedCardStateUpdatedCommand- Card state in Jiten changedDeckListUpdatedCommand- Deck list changedParsingPausedCommand- Parsing toggledProfileSwitchedCommand- Profile changed
Background handlers implement BackgroundCommandHandler<T>:
abstract class BackgroundCommandHandler<T extends BackgroundCommand> {
abstract readonly command: CommandConstructor<T>;
abstract handle(sender, ...args): PotentialPromise<ReturnType>;
}Registered in BackgroundCommandHandlerCollection which listens on runtime.onMessage.
- British spelling on common words
- Minimal comments - only for complex logic
- File naming: kebab-case (e.g.,
base.parser.ts,get-configuration.ts) - Classes: PascalCase with descriptive names
- Private fields: Underscore prefix (
_lookupKeyManager) - Types: Separate
*.types.tsfiles or inline with main export - No circular dependencies (enforced via ESLint)
ESLint enforces:
- 120 character max line length
- Single quotes
- Semicolons required
- Explicit function return types
- Member ordering
- Import restrictions per-scope
Run npm run lint before committing. All lint errors must be resolved.