@peaske7/readit 0.2.0 → 0.3.0-rc.0

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 (179) 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 +152 -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 +890 -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 +233 -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/MermaidEnhancer.svelte +218 -0
  68. package/src/components/MermaidModal.svelte +67 -0
  69. package/src/components/RawModal.svelte +126 -0
  70. package/src/components/ReanchorConfirm.svelte +30 -0
  71. package/src/components/SettingsModal.svelte +220 -0
  72. package/src/components/ShortcutCapture.svelte +82 -0
  73. package/src/components/ShortcutList.svelte +145 -0
  74. package/src/components/TabBar.svelte +52 -0
  75. package/src/components/TableOfContents.svelte +125 -0
  76. package/src/components/ui/ActionLink.svelte +40 -0
  77. package/src/components/ui/{Button.tsx → Button.svelte} +19 -20
  78. package/src/components/ui/Dialog.svelte +97 -0
  79. package/src/components/ui/DropdownMenu.svelte +85 -0
  80. package/src/components/ui/DropdownMenuItem.svelte +38 -0
  81. package/src/components/ui/DropdownMenuSeparator.svelte +11 -0
  82. package/src/components/ui/{Text.tsx → Text.svelte} +18 -23
  83. package/src/env.d.ts +6 -0
  84. package/src/index.css +141 -166
  85. package/src/lib/__fixtures__/bench-data.ts +0 -13
  86. package/src/lib/anchor.bench.ts +1 -12
  87. package/src/lib/anchor.test.ts +0 -8
  88. package/src/lib/anchor.ts +0 -4
  89. package/src/lib/comment-storage.bench.ts +49 -0
  90. package/src/lib/comment-storage.test.ts +103 -33
  91. package/src/lib/comment-storage.ts +25 -18
  92. package/src/lib/export.bench.ts +21 -0
  93. package/src/lib/export.ts +0 -1
  94. package/src/lib/fetch-or-throw.test.ts +59 -0
  95. package/src/lib/fetch-or-throw.ts +12 -0
  96. package/src/{hooks/useHeadings.test.ts → lib/headings.test.ts} +10 -24
  97. package/src/{hooks/useHeadings.ts → lib/headings.ts} +11 -13
  98. package/src/lib/highlight/core.test.ts +0 -5
  99. package/src/lib/highlight/dom.ts +52 -216
  100. package/src/lib/highlight/highlight-registry.ts +221 -0
  101. package/src/lib/highlight/highlight.bench.ts +92 -0
  102. package/src/lib/highlight/highlighter.ts +112 -132
  103. package/src/lib/highlight/resolver.ts +5 -79
  104. package/src/lib/highlight/types.ts +0 -5
  105. package/src/lib/html-text.test.ts +162 -0
  106. package/src/lib/html-text.ts +161 -0
  107. package/src/lib/i18n/en.ts +34 -0
  108. package/src/lib/i18n/ja.ts +34 -0
  109. package/src/lib/i18n/types.ts +33 -0
  110. package/src/lib/key-lock.test.ts +104 -0
  111. package/src/lib/key-lock.ts +23 -0
  112. package/src/lib/margin-layout.bench.ts +61 -0
  113. package/src/lib/margin-layout.ts +0 -7
  114. package/src/lib/markdown-renderer.test.ts +154 -0
  115. package/src/lib/markdown-renderer.ts +178 -0
  116. package/src/lib/mermaid-config.ts +38 -0
  117. package/src/lib/mermaid-renderer.ts +162 -0
  118. package/src/lib/mermaid-worker.ts +60 -0
  119. package/src/lib/positions.ts +31 -24
  120. package/src/lib/shortcut-registry.ts +244 -0
  121. package/src/lib/utils.ts +0 -29
  122. package/src/main.ts +16 -0
  123. package/src/schema.ts +16 -5
  124. package/src/server.ts +355 -95
  125. package/src/stores/app.svelte.ts +231 -0
  126. package/src/stores/locale.svelte.ts +46 -0
  127. package/src/stores/settings.svelte.ts +90 -0
  128. package/src/stores/shortcuts.svelte.ts +104 -0
  129. package/src/stores/ui.svelte.ts +12 -0
  130. package/src/template.ts +104 -0
  131. package/src/test-setup.ts +47 -0
  132. package/svelte.config.js +5 -0
  133. package/tsconfig.json +2 -2
  134. package/vite.config.ts +23 -3
  135. package/vscode-readit/.mcp.json +7 -0
  136. package/vscode-readit/.vscodeignore +7 -0
  137. package/vscode-readit/bun.lock +78 -0
  138. package/vscode-readit/icon.svg +10 -0
  139. package/vscode-readit/package.json +110 -0
  140. package/vscode-readit/src/extension.ts +117 -0
  141. package/vscode-readit/src/server-manager.ts +272 -0
  142. package/vscode-readit/src/webview-provider.ts +204 -0
  143. package/vscode-readit/tsconfig.json +20 -0
  144. package/e2e/fixtures/sample.html +0 -13
  145. package/src/App.tsx +0 -368
  146. package/src/components/ActionsMenu.tsx +0 -91
  147. package/src/components/DocumentViewer/CodeBlock.tsx +0 -160
  148. package/src/components/DocumentViewer/DocumentViewer.tsx +0 -230
  149. package/src/components/DocumentViewer/MermaidDiagram.tsx +0 -136
  150. package/src/components/Header.tsx +0 -54
  151. package/src/components/InlineEditor.tsx +0 -74
  152. package/src/components/MarginNote.tsx +0 -185
  153. package/src/components/MarginNotes.tsx +0 -23
  154. package/src/components/RawModal.tsx +0 -144
  155. package/src/components/ReanchorConfirm.tsx +0 -36
  156. package/src/components/SettingsModal.tsx +0 -232
  157. package/src/components/TabBar.tsx +0 -60
  158. package/src/components/TableOfContents.tsx +0 -108
  159. package/src/components/comments/CommentBadge.tsx +0 -49
  160. package/src/components/comments/CommentInput.tsx +0 -86
  161. package/src/components/comments/CommentListItem.tsx +0 -90
  162. package/src/components/comments/CommentManager.tsx +0 -129
  163. package/src/components/comments/CommentNav.tsx +0 -109
  164. package/src/components/ui/ActionLink.tsx +0 -28
  165. package/src/components/ui/Dialog.tsx +0 -116
  166. package/src/components/ui/DropdownMenu.tsx +0 -158
  167. package/src/contexts/CommentContext.tsx +0 -198
  168. package/src/contexts/LocaleContext.tsx +0 -76
  169. package/src/contexts/PositionsContext.tsx +0 -16
  170. package/src/contexts/SettingsContext.tsx +0 -133
  171. package/src/hooks/useClickOutside.ts +0 -31
  172. package/src/hooks/useCommentNavigation.ts +0 -107
  173. package/src/hooks/useComments.ts +0 -311
  174. package/src/hooks/useDocument.ts +0 -157
  175. package/src/hooks/useScrollSpy.ts +0 -77
  176. package/src/hooks/useTextSelection.ts +0 -86
  177. package/src/lib/highlight/worker.ts +0 -45
  178. package/src/main.tsx +0 -13
  179. package/src/store.ts +0 -222
@@ -0,0 +1,101 @@
1
+ package server
2
+
3
+ type Comment struct {
4
+ ID string `json:"id"`
5
+ SelectedText string `json:"selectedText"`
6
+ Comment string `json:"comment"`
7
+ CreatedAt string `json:"createdAt"`
8
+ StartOffset int `json:"startOffset"`
9
+ EndOffset int `json:"endOffset"`
10
+ LineHint string `json:"lineHint,omitempty"`
11
+ AnchorConfidence string `json:"anchorConfidence,omitempty"`
12
+ AnchorPrefix string `json:"anchorPrefix,omitempty"`
13
+ }
14
+
15
+ type Heading struct {
16
+ ID string `json:"id"`
17
+ Text string `json:"text"`
18
+ Level int `json:"level"`
19
+ }
20
+
21
+ type FileState struct {
22
+ FilePath string
23
+ FileName string
24
+ Content []byte
25
+ RenderedHTML string
26
+ Headings []Heading
27
+ IsLoaded bool
28
+ }
29
+
30
+ type ShortcutBinding struct {
31
+ Key string `json:"key"`
32
+ Alt bool `json:"alt,omitempty"`
33
+ Ctrl bool `json:"ctrl,omitempty"`
34
+ Meta bool `json:"meta,omitempty"`
35
+ Shift bool `json:"shift,omitempty"`
36
+ }
37
+
38
+ type Keybinding struct {
39
+ ID string `json:"id"`
40
+ Binding *ShortcutBinding `json:"binding,omitempty"`
41
+ Enabled bool `json:"enabled"`
42
+ }
43
+
44
+ type Settings struct {
45
+ Version int `json:"version"`
46
+ FontFamily string `json:"fontFamily"`
47
+ Keybindings []Keybinding `json:"keybindings,omitempty"`
48
+ }
49
+
50
+ type CommentFile struct {
51
+ Source string
52
+ Hash string
53
+ Version int
54
+ Comments []Comment
55
+ }
56
+
57
+ type InlineData struct {
58
+ Files []FileRef `json:"files"`
59
+ ActiveFile string `json:"activeFile"`
60
+ Clean bool `json:"clean"`
61
+ WorkingDir string `json:"workingDirectory"`
62
+ Documents map[string]InlineDocData `json:"documents"`
63
+ Settings Settings `json:"settings"`
64
+ }
65
+
66
+ type FileRef struct {
67
+ Path string `json:"path"`
68
+ FileName string `json:"fileName"`
69
+ }
70
+
71
+ type InlineDocData struct {
72
+ Headings []Heading `json:"headings"`
73
+ Comments []Comment `json:"comments"`
74
+ }
75
+
76
+ const (
77
+ AnchorExact = "exact"
78
+ AnchorNormalized = "normalized"
79
+ AnchorFuzzy = "fuzzy"
80
+ AnchorUnresolved = "unresolved"
81
+ )
82
+
83
+ const (
84
+ FontSerif = "serif"
85
+ FontSansSerif = "sans-serif"
86
+ )
87
+
88
+ const (
89
+ FormatVersion = 1
90
+ HashLength = 16
91
+ MaxSelectionLength = 1000
92
+ TruncationMarker = "\n...\n"
93
+ AnchorPrefixLength = 200
94
+ )
95
+
96
+ const (
97
+ DefaultSearchWindow = 500
98
+ DefaultFuzzyThreshold = 5
99
+ MaxFuzzyTextLength = 200
100
+ FuzzySearchWindow = 2000
101
+ )
@@ -0,0 +1,74 @@
1
+ package server
2
+
3
+ import (
4
+ "sync"
5
+ "time"
6
+
7
+ "github.com/fsnotify/fsnotify"
8
+ )
9
+
10
+ type Watcher struct {
11
+ fsWatcher *fsnotify.Watcher
12
+ debounce map[string]*time.Timer
13
+ onChange func(filePath string)
14
+ mu sync.Mutex
15
+ done chan struct{}
16
+ }
17
+
18
+ func NewWatcher(onChange func(string)) (*Watcher, error) {
19
+ fsw, err := fsnotify.NewWatcher()
20
+ if err != nil {
21
+ return nil, err
22
+ }
23
+
24
+ w := &Watcher{
25
+ fsWatcher: fsw,
26
+ debounce: make(map[string]*time.Timer),
27
+ onChange: onChange,
28
+ done: make(chan struct{}),
29
+ }
30
+
31
+ go w.loop()
32
+ return w, nil
33
+ }
34
+
35
+ func (w *Watcher) loop() {
36
+ for {
37
+ select {
38
+ case event, ok := <-w.fsWatcher.Events:
39
+ if !ok {
40
+ return
41
+ }
42
+ if event.Has(fsnotify.Write) || event.Has(fsnotify.Create) {
43
+ w.debounceChange(event.Name)
44
+ }
45
+ case _, ok := <-w.fsWatcher.Errors:
46
+ if !ok {
47
+ return
48
+ }
49
+ case <-w.done:
50
+ return
51
+ }
52
+ }
53
+ }
54
+
55
+ func (w *Watcher) debounceChange(path string) {
56
+ w.mu.Lock()
57
+ defer w.mu.Unlock()
58
+
59
+ if t, ok := w.debounce[path]; ok {
60
+ t.Stop()
61
+ }
62
+ w.debounce[path] = time.AfterFunc(100*time.Millisecond, func() {
63
+ w.onChange(path)
64
+ })
65
+ }
66
+
67
+ func (w *Watcher) Add(path string) error {
68
+ return w.fsWatcher.Add(path)
69
+ }
70
+
71
+ func (w *Watcher) Close() {
72
+ close(w.done)
73
+ _ = w.fsWatcher.Close()
74
+ }
package/index.html CHANGED
@@ -3,20 +3,10 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>readit - Markdown Review</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com">
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
- <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📖</text></svg>">
10
- <script>
11
- (() => {
12
- var t = localStorage.getItem("readit:theme");
13
- var d = t === "dark" || (t !== "light" && matchMedia("(prefers-color-scheme: dark)").matches);
14
- if (d) document.documentElement.classList.add("dark");
15
- })();
16
- </script>
6
+ <title>readit</title>
17
7
  </head>
18
- <body class="min-h-screen">
19
- <div id="root"></div>
20
- <script type="module" src="/src/main.tsx"></script>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.ts"></script>
21
11
  </body>
22
12
  </html>
@@ -0,0 +1,64 @@
1
+ -- Health check for readit.nvim
2
+ -- Run with :checkhealth readit
3
+
4
+ local M = {}
5
+
6
+ function M.check()
7
+ vim.health.start("readit.nvim")
8
+
9
+ -- Check bun
10
+ local readit = require("readit")
11
+ local bun_path = readit.config.bun_path or "bun"
12
+ local bun_exec = vim.fn.exepath(bun_path)
13
+
14
+ if bun_exec ~= "" then
15
+ local version = vim.fn.system(bun_path .. " --version")
16
+ vim.health.ok("bun found: " .. vim.trim(version) .. " (" .. bun_exec .. ")")
17
+ else
18
+ vim.health.error(
19
+ "bun not found",
20
+ { "Install Bun: https://bun.sh", "Or set bun_path in setup()" }
21
+ )
22
+ end
23
+
24
+ -- Check readit CLI
25
+ local readit_exec = vim.fn.exepath("readit")
26
+ if readit_exec ~= "" then
27
+ vim.health.ok("readit CLI found: " .. readit_exec)
28
+ else
29
+ local dist = vim.fn.expand("~/.readit/dist/index.js")
30
+ if vim.fn.filereadable(dist) == 1 then
31
+ vim.health.ok("readit dist found: " .. dist)
32
+ else
33
+ vim.health.warn(
34
+ "readit CLI not in PATH",
35
+ { "Install: npm install -g @peaske7/readit", "Or: bun add -g @peaske7/readit" }
36
+ )
37
+ end
38
+ end
39
+
40
+ -- Check curl (needed for server communication)
41
+ if vim.fn.exepath("curl") ~= "" then
42
+ vim.health.ok("curl found")
43
+ else
44
+ vim.health.error("curl not found (required for server API calls)")
45
+ end
46
+
47
+ -- Check server status
48
+ if readit._server_port then
49
+ vim.health.ok("Server running on port " .. readit._server_port)
50
+ else
51
+ vim.health.info("Server not running (will start on :ReaditOpen)")
52
+ end
53
+
54
+ -- Check for comments directory
55
+ local comments_dir = vim.fn.expand("~/.readit/comments")
56
+ if vim.fn.isdirectory(comments_dir) == 1 then
57
+ local count = #vim.fn.glob(comments_dir .. "/**/*.comments.md", false, true)
58
+ vim.health.ok("Comments directory exists (" .. count .. " comment files)")
59
+ else
60
+ vim.health.info("No comments directory yet (~/.readit/comments/)")
61
+ end
62
+ end
63
+
64
+ return M