@peaske7/readit 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/.claude/CLAUDE.md +118 -76
  2. package/.claude/commands/review.md +1 -1
  3. package/.claude/roadmap.md +32 -9
  4. package/.claude/user-stories.md +100 -15
  5. package/AGENTS.md +30 -26
  6. package/Makefile +32 -0
  7. package/README.md +90 -2
  8. package/biome.json +18 -8
  9. package/bun.lock +426 -568
  10. package/bunfig.toml +2 -0
  11. package/docs/perf-baseline.md +56 -1
  12. package/docs/superpowers/specs/2026-03-27-go-server-rewrite-design.md +284 -0
  13. package/e2e/comments.spec.ts +14 -58
  14. package/e2e/document-load.spec.ts +1 -23
  15. package/e2e/export.spec.ts +4 -4
  16. package/e2e/perf/add-comment.spec.ts +9 -11
  17. package/e2e/perf/fixtures/generate.ts +1 -5
  18. package/e2e/perf/screenshot-final.png +0 -0
  19. package/e2e/perf/utils/metrics.ts +73 -9
  20. package/e2e/persistence-file.spec.ts +41 -26
  21. package/e2e/utils/selection.ts +17 -73
  22. package/go/cmd/readit/main.go +416 -0
  23. package/go/go.mod +20 -0
  24. package/go/go.sum +41 -0
  25. package/go/internal/server/anchor.go +302 -0
  26. package/go/internal/server/anchor_test.go +111 -0
  27. package/go/internal/server/comments.go +390 -0
  28. package/go/internal/server/documents.go +113 -0
  29. package/go/internal/server/embed.go +17 -0
  30. package/go/internal/server/headings.go +33 -0
  31. package/go/internal/server/headings_test.go +75 -0
  32. package/go/internal/server/htmltext.go +123 -0
  33. package/go/internal/server/markdown.go +157 -0
  34. package/go/internal/server/markdown_bench_test.go +42 -0
  35. package/go/internal/server/markdown_test.go +79 -0
  36. package/go/internal/server/server.go +453 -0
  37. package/go/internal/server/server_bench_test.go +122 -0
  38. package/go/internal/server/settings.go +110 -0
  39. package/go/internal/server/sse.go +140 -0
  40. package/go/internal/server/storage.go +275 -0
  41. package/go/internal/server/storage_test.go +118 -0
  42. package/go/internal/server/template.go +66 -0
  43. package/go/internal/server/types.go +101 -0
  44. package/go/internal/server/watcher.go +74 -0
  45. package/index.html +4 -14
  46. package/nvim-readit/lua/readit/health.lua +64 -0
  47. package/nvim-readit/lua/readit/init.lua +463 -0
  48. package/nvim-readit/plugin/readit.lua +19 -0
  49. package/package.json +20 -28
  50. package/shell/_readit +158 -0
  51. package/shell/readit.zsh +87 -0
  52. package/src/App.svelte +881 -0
  53. package/src/cli.ts +183 -21
  54. package/src/components/ActionsMenu.svelte +95 -0
  55. package/src/components/CommentBadge.svelte +67 -0
  56. package/src/components/CommentErrorBanner.svelte +33 -0
  57. package/src/components/CommentInput.svelte +75 -0
  58. package/src/components/CommentListItem.svelte +95 -0
  59. package/src/components/CommentManager.svelte +129 -0
  60. package/src/components/CommentNav.svelte +109 -0
  61. package/src/components/DocumentViewer.svelte +218 -0
  62. package/src/components/FloatingComment.svelte +107 -0
  63. package/src/components/Header.svelte +76 -0
  64. package/src/components/InlineEditor.svelte +72 -0
  65. package/src/components/MarginNote.svelte +167 -0
  66. package/src/components/MarginNotesContainer.svelte +33 -0
  67. package/src/components/RawModal.svelte +126 -0
  68. package/src/components/ReanchorConfirm.svelte +30 -0
  69. package/src/components/SettingsModal.svelte +220 -0
  70. package/src/components/ShortcutCapture.svelte +82 -0
  71. package/src/components/ShortcutList.svelte +145 -0
  72. package/src/components/TabBar.svelte +52 -0
  73. package/src/components/TableOfContents.svelte +125 -0
  74. package/src/components/ui/ActionLink.svelte +40 -0
  75. package/src/components/ui/{Button.tsx → Button.svelte} +19 -20
  76. package/src/components/ui/Dialog.svelte +97 -0
  77. package/src/components/ui/DropdownMenu.svelte +85 -0
  78. package/src/components/ui/DropdownMenuItem.svelte +38 -0
  79. package/src/components/ui/DropdownMenuSeparator.svelte +11 -0
  80. package/src/components/ui/{Text.tsx → Text.svelte} +18 -23
  81. package/src/env.d.ts +6 -0
  82. package/src/index.css +36 -166
  83. package/src/lib/__fixtures__/bench-data.ts +0 -13
  84. package/src/lib/anchor.bench.ts +1 -12
  85. package/src/lib/anchor.test.ts +0 -8
  86. package/src/lib/anchor.ts +0 -4
  87. package/src/lib/comment-storage.bench.ts +49 -0
  88. package/src/lib/comment-storage.test.ts +41 -33
  89. package/src/lib/comment-storage.ts +21 -18
  90. package/src/lib/export.bench.ts +21 -0
  91. package/src/lib/export.ts +0 -1
  92. package/src/{hooks/useHeadings.test.ts → lib/headings.test.ts} +10 -24
  93. package/src/{hooks/useHeadings.ts → lib/headings.ts} +11 -13
  94. package/src/lib/highlight/core.test.ts +0 -5
  95. package/src/lib/highlight/dom.ts +52 -216
  96. package/src/lib/highlight/highlight-registry.ts +221 -0
  97. package/src/lib/highlight/highlight.bench.ts +92 -0
  98. package/src/lib/highlight/highlighter.ts +112 -132
  99. package/src/lib/highlight/resolver.ts +5 -79
  100. package/src/lib/highlight/types.ts +0 -5
  101. package/src/lib/html-text.test.ts +162 -0
  102. package/src/lib/html-text.ts +161 -0
  103. package/src/lib/i18n/en.ts +26 -0
  104. package/src/lib/i18n/ja.ts +26 -0
  105. package/src/lib/i18n/types.ts +25 -0
  106. package/src/lib/margin-layout.bench.ts +61 -0
  107. package/src/lib/margin-layout.ts +0 -7
  108. package/src/lib/markdown-renderer.test.ts +154 -0
  109. package/src/lib/markdown-renderer.ts +177 -0
  110. package/src/lib/mermaid-config.ts +38 -0
  111. package/src/lib/mermaid-renderer.ts +162 -0
  112. package/src/lib/mermaid-worker.ts +60 -0
  113. package/src/lib/positions.ts +31 -24
  114. package/src/lib/shortcut-registry.ts +244 -0
  115. package/src/lib/utils.ts +0 -29
  116. package/src/main.ts +16 -0
  117. package/src/schema.ts +16 -5
  118. package/src/server.ts +355 -91
  119. package/src/stores/app.svelte.ts +231 -0
  120. package/src/stores/locale.svelte.ts +46 -0
  121. package/src/stores/settings.svelte.ts +90 -0
  122. package/src/stores/shortcuts.svelte.ts +104 -0
  123. package/src/stores/ui.svelte.ts +12 -0
  124. package/src/template.ts +104 -0
  125. package/src/test-setup.ts +47 -0
  126. package/svelte.config.js +5 -0
  127. package/tsconfig.json +2 -2
  128. package/vite.config.ts +23 -3
  129. package/vscode-readit/.mcp.json +7 -0
  130. package/vscode-readit/.vscodeignore +7 -0
  131. package/vscode-readit/bun.lock +78 -0
  132. package/vscode-readit/icon.svg +10 -0
  133. package/vscode-readit/package.json +110 -0
  134. package/vscode-readit/src/extension.ts +117 -0
  135. package/vscode-readit/src/server-manager.ts +272 -0
  136. package/vscode-readit/src/webview-provider.ts +204 -0
  137. package/vscode-readit/tsconfig.json +20 -0
  138. package/e2e/fixtures/sample.html +0 -13
  139. package/src/App.tsx +0 -368
  140. package/src/components/ActionsMenu.tsx +0 -91
  141. package/src/components/DocumentViewer/CodeBlock.tsx +0 -160
  142. package/src/components/DocumentViewer/DocumentViewer.tsx +0 -230
  143. package/src/components/DocumentViewer/MermaidDiagram.tsx +0 -136
  144. package/src/components/Header.tsx +0 -54
  145. package/src/components/InlineEditor.tsx +0 -74
  146. package/src/components/MarginNote.tsx +0 -185
  147. package/src/components/MarginNotes.tsx +0 -23
  148. package/src/components/RawModal.tsx +0 -144
  149. package/src/components/ReanchorConfirm.tsx +0 -36
  150. package/src/components/SettingsModal.tsx +0 -232
  151. package/src/components/TabBar.tsx +0 -60
  152. package/src/components/TableOfContents.tsx +0 -108
  153. package/src/components/comments/CommentBadge.tsx +0 -49
  154. package/src/components/comments/CommentInput.tsx +0 -86
  155. package/src/components/comments/CommentListItem.tsx +0 -90
  156. package/src/components/comments/CommentManager.tsx +0 -129
  157. package/src/components/comments/CommentNav.tsx +0 -109
  158. package/src/components/ui/ActionLink.tsx +0 -28
  159. package/src/components/ui/Dialog.tsx +0 -116
  160. package/src/components/ui/DropdownMenu.tsx +0 -158
  161. package/src/contexts/CommentContext.tsx +0 -198
  162. package/src/contexts/LocaleContext.tsx +0 -76
  163. package/src/contexts/PositionsContext.tsx +0 -16
  164. package/src/contexts/SettingsContext.tsx +0 -133
  165. package/src/hooks/useClickOutside.ts +0 -31
  166. package/src/hooks/useCommentNavigation.ts +0 -107
  167. package/src/hooks/useComments.ts +0 -311
  168. package/src/hooks/useDocument.ts +0 -157
  169. package/src/hooks/useScrollSpy.ts +0 -77
  170. package/src/hooks/useTextSelection.ts +0 -86
  171. package/src/lib/highlight/worker.ts +0 -45
  172. package/src/main.tsx +0 -13
  173. package/src/store.ts +0 -222
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peaske7/readit",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A CLI tool to review Markdown documents with inline comments",
5
5
  "author": "Jay Shimada <peaske@pm.me>",
6
6
  "license": "MIT",
@@ -17,7 +17,7 @@
17
17
  "dev": "NODE_ENV=development bun --watch src/cli.ts --",
18
18
  "dev:client": "bunx vite",
19
19
  "build": "bunx vite build && bun run build:cli",
20
- "build:cli": "NODE_ENV=production bun build src/cli.ts --outdir dist --target bun --format esm --packages external",
20
+ "build:cli": "NODE_ENV=production bun build src/cli.ts --outfile dist/index.js --target bun --format esm --packages external",
21
21
  "start": "bun run build && bun dist/index.js",
22
22
  "test": "vitest run",
23
23
  "bench": "vitest bench",
@@ -36,37 +36,29 @@
36
36
  "dependencies": {
37
37
  "clsx": "^2.1.1",
38
38
  "commander": "^14.0.3",
39
- "lucide-react": "^0.577.0",
40
- "mermaid": "^11.13.0",
39
+ "lucide-svelte": "^0.577.0",
40
+ "markdown-it": "^14.1.1",
41
+ "mermaid": "^11.14.0",
41
42
  "open": "^11.0.0",
42
- "react-markdown": "^10.1.0",
43
- "react-syntax-highlighter": "^16.1.1",
44
- "rehype-raw": "^7.0.0",
45
- "remark-gfm": "^4.0.1",
46
- "sonner": "^2.0.7",
47
- "tailwind-merge": "^3.5.0",
48
- "zod": "^4.3.6",
49
- "zustand": "^5.0.12"
43
+ "jsdom": "^28.1.0",
44
+ "shiki": "^4.0.2",
45
+ "tailwind-merge": "^3.6.0"
50
46
  },
51
47
  "devDependencies": {
52
- "@biomejs/biome": "^2.4.9",
53
- "@playwright/test": "^1.58.2",
54
- "@tailwindcss/vite": "^4.2.2",
48
+ "@biomejs/biome": "^2.4.15",
49
+ "@playwright/test": "^1.59.1",
50
+ "@sveltejs/vite-plugin-svelte": "^5.1.1",
51
+ "@tailwindcss/vite": "^4.3.0",
55
52
  "@testing-library/jest-dom": "^6.9.1",
56
- "@testing-library/react": "^16.3.2",
57
- "@types/bun": "^1.3.11",
53
+ "@types/bun": "^1.3.13",
58
54
  "@types/jsdom": "^28.0.1",
59
- "@types/react": "^19.2.14",
60
- "@types/react-dom": "^19.2.3",
61
- "@types/react-syntax-highlighter": "^15.5.13",
62
- "@vitejs/plugin-react": "^6.0.1",
63
- "jsdom": "^28.1.0",
64
- "lefthook": "^2.1.4",
65
- "react": "^19.2.4",
66
- "react-dom": "^19.2.4",
67
- "tailwindcss": "^4.2.2",
55
+ "@types/markdown-it": "^14.1.2",
56
+ "@types/node": "^25.6.2",
57
+ "lefthook": "^2.1.6",
58
+ "svelte": "^5.55.5",
59
+ "tailwindcss": "^4.3.0",
68
60
  "typescript": "^5.9.3",
69
- "vite": "^8.0.3",
70
- "vitest": "^4.1.1"
61
+ "vite": "^8.0.11",
62
+ "vitest": "^4.1.5"
71
63
  }
72
64
  }
package/shell/_readit ADDED
@@ -0,0 +1,158 @@
1
+ #compdef readit
2
+
3
+ # Zsh completion for readit - Markdown document review CLI
4
+ #
5
+ # Provides:
6
+ # 1. Standard subcommand/option completion (readit <TAB>)
7
+ # 2. @-prefix file completion with [bracket] display (readit @<TAB>)
8
+ #
9
+ # Install: add to $fpath or source via `readit completion zsh`
10
+
11
+ # ── Helpers ────────────────────────────────────────────────────────────
12
+
13
+ # Collect markdown files using fd (fast) or find (fallback)
14
+ _readit_collect_md_files() {
15
+ local fd_cmd="$(command -v fdfind 2>/dev/null || command -v fd 2>/dev/null)"
16
+ if [[ -n "$fd_cmd" ]]; then
17
+ "$fd_cmd" --type f --hidden --exclude .git \
18
+ --extension md --extension markdown 2>/dev/null
19
+ else
20
+ find . -type f \( -name '*.md' -o -name '*.markdown' \) \
21
+ -not -path '*/\.*' \
22
+ -not -path '*/node_modules/*' \
23
+ -not -path '*/.next/*' \
24
+ -not -path '*/dist/*' \
25
+ 2>/dev/null | sed 's|^\./||'
26
+ fi
27
+ }
28
+
29
+ # Standard markdown file completion (no @ prefix, no brackets)
30
+ _readit_markdown_files() {
31
+ local -a files
32
+ files=( ${(f)"$(_readit_collect_md_files)"} )
33
+ (( ${#files} )) && _describe -t files 'markdown files' files
34
+ }
35
+
36
+ # @ prefix file completion with [bracket] display
37
+ # Renders a native multi-column grid of [file.md] entries
38
+ _readit_at_files() {
39
+ local current="${PREFIX}${SUFFIX}"
40
+
41
+ # Strip the leading @
42
+ local filter="${current#@}"
43
+
44
+ # Collect all markdown files
45
+ local -a all_files
46
+ all_files=( ${(f)"$(_readit_collect_md_files)"} )
47
+ (( ${#all_files} )) || return 1
48
+
49
+ # Filter by case-insensitive substring match
50
+ local -a matches
51
+ if [[ -n "$filter" ]]; then
52
+ local lc_filter="${(L)filter}"
53
+ local f
54
+ for f in "${all_files[@]}"; do
55
+ [[ "${(L)f}" == *"$lc_filter"* ]] && matches+=("$f")
56
+ done
57
+ else
58
+ matches=("${all_files[@]}")
59
+ fi
60
+ (( ${#matches} )) || return 1
61
+
62
+ # Build display array: [file.md] and insertion values: @[file.md]
63
+ local -a display_items
64
+ local item
65
+ for item in "${matches[@]}"; do
66
+ display_items+=("@[${item}]")
67
+ done
68
+
69
+ # Use compadd:
70
+ # -U = don't verify matches against current word
71
+ # -d = display strings (the [bracketed] versions shown in the menu)
72
+ # -Q = don't quote completions
73
+ # -S = suffix after insertion (space)
74
+ # -f = treat as file names
75
+ # The inserted text is @[file.md] which gets stripped to file.md on Enter
76
+ # by the readit-accept-line widget in readit.zsh
77
+ compadd -U -Q -S ' ' -d display_items -a display_items
78
+ }
79
+
80
+ _readit_commented_files() {
81
+ local readit_dir="${HOME}/.readit/comments"
82
+ if [[ ! -d "$readit_dir" ]]; then
83
+ return 1
84
+ fi
85
+ local -a sources
86
+ sources=( ${(f)"$(grep -rh '^source:' "$readit_dir" 2>/dev/null | sed 's/^source: *//')"} )
87
+ if (( ${#sources} )); then
88
+ _describe -t files 'files with comments' sources
89
+ fi
90
+ }
91
+
92
+ # ── Main Completion ────────────────────────────────────────────────────
93
+
94
+ _readit() {
95
+ local context state state_descr line
96
+ typeset -A opt_args
97
+
98
+ # Check if the current word starts with @
99
+ local current="${PREFIX}${SUFFIX}"
100
+ if [[ "$current" == @* ]]; then
101
+ _readit_at_files
102
+ return
103
+ fi
104
+
105
+ _arguments -C \
106
+ '1:command:->cmd_or_files' \
107
+ '*::arg:->args'
108
+
109
+ case "$state" in
110
+ cmd_or_files)
111
+ local -a commands
112
+ commands=(
113
+ 'open:Add files to a running server or start a new one'
114
+ 'list:List all files with comments'
115
+ 'show:Show comments for a file'
116
+ 'completion:Output shell completion script'
117
+ )
118
+ _alternative \
119
+ 'commands:command:compadd -a commands' \
120
+ 'files:markdown file:_readit_markdown_files'
121
+ ;;
122
+ args)
123
+ case "${line[1]}" in
124
+ open)
125
+ _arguments \
126
+ '-p[Port for new server]:port:' \
127
+ '--port[Port for new server]:port:' \
128
+ '--host[Host for new server]:host:' \
129
+ '*:file:_readit_markdown_files'
130
+ ;;
131
+ show)
132
+ _arguments \
133
+ '1:file:_readit_commented_files'
134
+ ;;
135
+ list)
136
+ # No arguments
137
+ ;;
138
+ completion)
139
+ local -a shells
140
+ shells=(zsh bash fish)
141
+ _describe -t shells 'shell' shells
142
+ ;;
143
+ *)
144
+ # Default command: [files...] with options
145
+ _arguments \
146
+ '-p[Port to run server on]:port:' \
147
+ '--port[Port to run server on]:port:' \
148
+ '--host[Host address to bind to]:host:' \
149
+ '--no-open[Do not automatically open browser]' \
150
+ '--clean[Clear all existing comments on startup]' \
151
+ '*:file:_readit_markdown_files'
152
+ ;;
153
+ esac
154
+ ;;
155
+ esac
156
+ }
157
+
158
+ _readit "$@"
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env zsh
2
+
3
+ # readit.zsh — Rich zsh integration for readit
4
+ #
5
+ # Provides @-prefix file autocomplete using zsh's native completion menu,
6
+ # rendering markdown file matches in a multi-column [bracketed] grid
7
+ # directly below the prompt — like Forge Code / Claude Code.
8
+ #
9
+ # The heavy lifting is in the _readit compdef (shell/_readit) which uses
10
+ # compadd to render [file.md] entries. This file adds:
11
+ # - Accept-line handler to strip @[...] brackets before execution
12
+ # - Syntax highlighting for @[...] references (cyan bold)
13
+ # - Completion system setup (loads _readit into fpath)
14
+ #
15
+ # Usage:
16
+ # eval "$(readit completion zsh)"
17
+ #
18
+ # This gives you:
19
+ # readit @<TAB> → native multi-column grid of markdown files
20
+ # readit @test<TAB> → grid filtered to files matching "test"
21
+ # readit @docs/<TAB> → grid filtered to files matching "docs/"
22
+ # readit open @<TAB> → same, works with subcommands
23
+ # readit <TAB> → standard subcommand/option completion
24
+
25
+ # ── Guard ──────────────────────────────────────────────────────────────
26
+ (( $+functions[_readit_plugin_loaded] )) && return 0
27
+ _readit_plugin_loaded() { :; }
28
+
29
+ # ── Accept Line: Strip @[...] Brackets ────────────────────────────────
30
+ #
31
+ # When Enter is pressed, convert @[file.md] references to bare file.md
32
+ # paths before executing. This lets the bracket syntax be a visual aid
33
+ # on the prompt without affecting the actual command arguments.
34
+
35
+ function readit-accept-line() {
36
+ if [[ "$BUFFER" == *'@['* ]]; then
37
+ local result="" rest="$BUFFER"
38
+ while [[ "$rest" == *'@['* ]]; do
39
+ result+="${rest%%@\[*}"
40
+ rest="${rest#*@\[}"
41
+ if [[ "$rest" == *']'* ]]; then
42
+ result+="${rest%%\]*}"
43
+ rest="${rest#*\]}"
44
+ else
45
+ result+="@[${rest}"
46
+ rest=""
47
+ fi
48
+ done
49
+ result+="$rest"
50
+ BUFFER="$result"
51
+ fi
52
+ zle accept-line
53
+ }
54
+
55
+ zle -N readit-accept-line
56
+ bindkey '^M' readit-accept-line
57
+ bindkey '^J' readit-accept-line
58
+
59
+ # ── Syntax Highlighting ───────────────────────────────────────────────
60
+ # Highlight @[...] references in cyan bold (requires zsh-syntax-highlighting)
61
+
62
+ if (( $+ZSH_HIGHLIGHT_PATTERNS )); then
63
+ ZSH_HIGHLIGHT_PATTERNS+=('@\[[^\]]*\]' 'fg=cyan,bold')
64
+ ZSH_HIGHLIGHT_HIGHLIGHTERS+=(pattern)
65
+ fi
66
+
67
+ # ── Completion Setup ──────────────────────────────────────────────────
68
+ # Load _readit compdef into fpath so Tab triggers native @ completion
69
+
70
+ _readit_setup_completion() {
71
+ local comp_dir="${0:A:h}"
72
+
73
+ if [[ -f "${comp_dir}/_readit" ]]; then
74
+ fpath=("$comp_dir" $fpath)
75
+ fi
76
+
77
+ autoload -Uz compinit
78
+ if (( ! $+functions[_readit] )); then
79
+ compinit -C 2>/dev/null
80
+ fi
81
+ }
82
+
83
+ _readit_setup_completion
84
+
85
+ # ── Convenience ───────────────────────────────────────────────────────
86
+
87
+ alias ri='readit'