Skip to content

Commit 4529d0e

Browse files
authored
Obsidian Guidelines Compliance + Phase 2 Refactoring (v1.4.1)
Fixes all [Obsidian team review issues](obsidianmd/obsidian-releases#8304 (comment)) + completes Phase 2 refactoring + corrects documentation inaccuracies. **Version:** 1.4.0 → 1.4.1 **Type:** Compliance + Documentation (no functionality changes) **Status:** ✅ Production-ready, passes all Obsidian automated checks --- ## ✅ Obsidian Compliance (4 issues fixed) 1. **Security** - Zero `innerHTML`/`outerHTML` usage (XSS-safe) 2. **Styling** - All inline styles replaced with `toggleClass()` (11 instances across 4 files) 3. **Logging** - Clean console (only 1 controlled Logger usage) 4. **Commands** - Renamed "Open DashReader" → "Open RSVP reader" --- ## 🏗️ Phase 2 Refactoring Complete **Architecture transformation:** - 6 core files → 20+ focused modules - 0 services → 4 dedicated services (timeout, settings, micropause, stats) - ~70% type-safe → 99% (1 `as any` remaining vs dozens before) - 2000+ line files → <500 lines average **Key changes:** - Service extraction with Strategy Pattern (`MicropauseService`) - Module extraction (constants, logger, hotkeys, DOM, state, UI builders) - Navigation managers (breadcrumb, minimap, menus, auto-load) - Type safety improvements (eliminated nearly all `as any` casts) --- ## 📚 Documentation Corrections **CLAUDE.md:** - Added 15 missing files from Phase 2 refactoring - Fixed breadcrumb description (single-line, not two-row layout) - Clarified line break handling location (engine vs parser) - Updated WPM max: 1000 → 5000 **README.md:** - Removed obsolete "Section counter" feature - Removed 3 broken REFACTORING.md links - Updated Roadmap (Phase 2 = COMPLETE, not "upcoming") - Added complete project structure (20+ files) All docs verified against actual codebase.
2 parents 1ef514b + 559d69c commit 4529d0e

29 files changed

+9718
-1574
lines changed

CLAUDE.md

Lines changed: 115 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,36 @@ npm run version
2323

2424
DashReader is an Obsidian plugin implementing RSVP (Rapid Serial Visual Presentation) speed reading. The architecture follows a clear separation:
2525

26+
**Core Architecture** (6 main files):
27+
2628
- **main.ts** - Plugin entry point, registers commands, ribbon icons, and manages view lifecycle
2729
- **src/rsvp-view.ts** - UI layer (ItemView), handles user interactions, cursor tracking, and display
2830
- **src/rsvp-engine.ts** - Core reading engine, controls timing, word iteration, and micropause logic
2931
- **src/markdown-parser.ts** - Transforms Markdown to plain text while marking headings with `[H1]`, `[H2]` etc.
3032
- **src/settings.ts** - Settings UI using Obsidian's PluginSettingTab
3133
- **src/types.ts** - Shared interfaces and default settings
3234

35+
**Support Modules** (extracted during refactoring Phase 2):
36+
37+
- **src/constants.ts** - Centralized CSS classes, timing values, limits, and magic numbers
38+
- **src/logger.ts** - Centralized logging with DashReader: prefix
39+
- **src/hotkey-handler.ts** - Keyboard event handling (Shift+Space, navigation hotkeys)
40+
- **src/word-display.ts** - Word rendering logic with heading/callout support
41+
- **src/dom-registry.ts** - DOM element management and lifecycle
42+
- **src/view-state.ts** - Reactive state management with change tracking
43+
- **src/breadcrumb-manager.ts** - Breadcrumb navigation UI and logic
44+
- **src/minimap-manager.ts** - Vertical minimap visualization
45+
- **src/menu-builder.ts** - Dropdown menu creation for navigation
46+
- **src/auto-load-manager.ts** - Auto-load text from editor on file-open/selection
47+
- **src/ui-builders.ts** - UI component builders (buttons, sliders, toggles)
48+
49+
**Services** (business logic extraction):
50+
51+
- **src/services/timeout-manager.ts** - Timer management with cleanup
52+
- **src/services/settings-validator.ts** - Settings validation and sanitization
53+
- **src/services/micropause-service.ts** - Micropause calculation using Strategy Pattern
54+
- **src/services/stats-formatter.ts** - Statistics formatting (time, WPM, progress)
55+
3356
### Key Architecture Patterns
3457

3558
**View-Engine Separation**: The view (`rsvp-view.ts`) owns the UI and event handling, while the engine (`rsvp-engine.ts`) owns reading logic and timing. They communicate via:
@@ -43,9 +66,51 @@ DashReader is an Obsidian plugin implementing RSVP (Rapid Serial Visual Presenta
4366
4. Pass word INDEX to engine, not character position
4467

4568
**Heading System**: Headings are marked during parsing (`# Title``[H1]Title`), then:
46-
- View detects markers and displays with proportional font size (H1=2x, H2=1.75x, etc.)
69+
- View detects markers and displays with proportional font size (H1=1.5x, H2=1.3x, H3=1.2x, etc.)
4770
- View adds visual separator lines before headings
48-
- Engine applies longer micropauses (H1=3x, H2=2.5x, etc.)
71+
- Engine applies longer micropauses (H1=2.0x, H2=1.8x, H3=1.5x, etc.)
72+
- Headings extracted with full titles using line break markers (§§LINEBREAK§§)
73+
74+
**Breadcrumb Navigation System** (v1.4.0): Provides document structure awareness and navigation:
75+
76+
- **Display**: Single-line breadcrumb showing hierarchical path: 📑 H1 › H2 › H3 ▼
77+
- **Extraction**: Engine's `extractHeadings()` collects all headings and callouts during `setText()`
78+
- Stops at §§LINEBREAK§§ markers to capture complete titles
79+
- Returns `HeadingInfo[]` with level, text, wordIndex, and optional calloutType
80+
- **Context Building**: `getCurrentHeadingContext()` builds hierarchical breadcrumb
81+
- Filters headings up to current word index
82+
- Maintains heading stack, pops when level decreases
83+
- Returns `HeadingContext` with breadcrumb array and current heading
84+
- **Navigation**: Click heading to jump, click ▼ dropdown for same-level navigation
85+
- `navigateToHeading(wordIndex)` preserves playback state
86+
- Dropdown menu shows all headings of same level with numbering
87+
- Menu created in `document.body` with fixed positioning for proper display
88+
- Centered under breadcrumb with viewport overflow protection
89+
- **Initial Display**: Breadcrumb shown immediately on `loadText()`, not just during playback
90+
- **Update Optimization**: Breadcrumb only redraws when heading context changes
91+
- `lastHeadingContext` property caches previous context
92+
- `hasHeadingContextChanged()` compares new vs old context
93+
- Prevents DOM recreation on every word, keeps dropdown clickable during reading
94+
95+
**Callout Support** (v1.4.0): Full integration with Obsidian callouts:
96+
- Parser marks callouts: `> [!type] Title``[CALLOUT:type]Title`
97+
- Treated as pseudo-headings (level=0) in breadcrumb hierarchy
98+
- Display with icon prefix (📝 note, 💡 tip, ⚠️ warning, etc.)
99+
- Visual separator and 1.2x font size during reading
100+
- 2.0x micropause multiplier (configurable)
101+
102+
**Line Break Preservation** (v1.4.0): Critical for heading extraction:
103+
104+
- `\n` replaced with `§§LINEBREAK§§` marker in `rsvp-engine.ts` `setText()` method (not in parser)
105+
- Allows `extractHeadings()` to detect end of single-line headings
106+
- Markers converted back to `\n` after extraction for display
107+
- Prevents headings from capturing following paragraphs
108+
109+
**Slow Start Feature** (v1.4.0): Progressive speed ramp for comfortable reading initiation:
110+
- Enabled by default via `enableSlowStart` setting
111+
- Multiplies delay over first 5 words: 2.0x → 1.8x → 1.6x → 1.4x → 1.2x → 1.0x
112+
- Resets on each new reading session (play after stop/reset)
113+
- Inspired by Stutter plugin's ease-in approach
49114

50115
**Accurate Time Estimation**: `getEstimatedDuration()` and `getRemainingTime()` iterate through ALL remaining words and sum their individual delays, accounting for:
51116
- Heading micropauses
@@ -91,22 +156,61 @@ Settings are defined in `src/types.ts` as:
91156

92157
UI is built in `src/settings.ts` using Obsidian's Setting API. Inline settings in the view mirror the main settings tab.
93158

159+
**Enhanced Settings UI** (v1.4.0):
160+
- **Editable Numeric Inputs**: All sliders now have editable text inputs displaying current values
161+
- Bidirectional sync: slider ↔ input
162+
- Validation and clamping to min/max bounds
163+
- Unit labels (px, s, x) displayed but non-editable
164+
- Implementation via `createSliderWithInput()` helper method
165+
- **Extended WPM Range**: Max WPM increased from 1000 to 5000 for ultra-fast reading
166+
- **Complete Micropause Controls**: All 8 micropause multipliers exposed in settings tab
167+
- Sentence-ending punctuation (.,!?)
168+
- Other punctuation (;:,)
169+
- Numbers and dates
170+
- Long words (>8 chars)
171+
- Paragraph breaks
172+
- Section markers (1., I., etc.)
173+
- List bullets (-, *, +, •)
174+
- Obsidian callouts
175+
94176
### Micropause System
95177

96-
Micropauses multiply the base delay (`60/WPM * 1000 ms`). Multiple conditions can stack multiplicatively:
178+
Micropauses multiply the base delay (`60/WPM * 1000 ms`). Multiple conditions can stack multiplicatively. **All multipliers are configurable in settings** (v1.4.0):
97179

98180
```typescript
99-
// Example: H1 heading with period and long word
100-
multiplier = 3.0 (H1) * 1.5 (period) * 1.3 (>8 chars) = 5.85x delay
181+
// Example: H1 heading with sentence-ending punctuation and long word
182+
multiplier = 2.0 (H1) * 2.5 (.) * 1.4 (>8 chars) = 7.0x delay
101183
```
102184

185+
**Configurable Multipliers** (v1.4.0):
186+
- `micropausePunctuation` (2.5x): Sentence-ending punctuation (.,!?)
187+
- `micropauseOtherPunctuation` (1.5x): Other punctuation (;:,)
188+
- `micropauseNumbers` (1.8x): Words containing digits (dates, statistics, years)
189+
- `micropauseLongWords` (1.4x): Words >8 characters
190+
- `micropauseParagraph` (2.5x): Paragraph breaks (\n)
191+
- `micropauseSectionMarkers` (2.0x): Section numbers (1., I., II., a., etc.)
192+
- `micropauseListBullets` (1.8x): List bullets (-, *, +, •)
193+
- `micropauseCallouts` (2.0x): Obsidian callouts ([CALLOUT:type])
194+
195+
**Heading Multipliers** (hardcoded in engine):
196+
- H1: 2.0x, H2: 1.8x, H3: 1.5x, H4: 1.3x, H5: 1.2x, H6: 1.1x
197+
103198
Order of detection in `calculateDelay()`:
104-
1. Headings (`[H1]` through `[H6]`)
105-
2. Section markers (1., I., etc.)
106-
3. List bullets (-, *, +, •)
107-
4. Punctuation (end of word)
108-
5. Long words (>8 characters)
109-
6. Paragraph breaks (`\n`)
199+
1. Headings (`[H1]` through `[H6]`) - engine hardcoded
200+
2. Callouts (`[CALLOUT:type]`) - `micropauseCallouts`
201+
3. Section markers (1., I., etc.) - `micropauseSectionMarkers`
202+
4. List bullets (-, *, +, •) - `micropauseListBullets`
203+
5. Sentence punctuation (.,!?) - `micropausePunctuation`
204+
6. Other punctuation (;:,) - `micropauseOtherPunctuation`
205+
7. Numbers (containing digits) - `micropauseNumbers`
206+
8. Long words (>8 characters) - `micropauseLongWords`
207+
9. Paragraph breaks (`\n`) - `micropauseParagraph`
208+
209+
**Stutter-Inspired Defaults** (v1.4.0):
210+
- Base WPM: 400 (up from 300)
211+
- Sentence punctuation: 2.5x (up from 1.5x)
212+
- Numbers: 1.8x (new feature)
213+
- Punctuation distinction: sentences vs. commas/semicolons
110214

111215
## Release Process
112216

0 commit comments

Comments
 (0)