You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add server mode with live reload (rdoc --server) (ruby#1620)
A better attempt of ruby#1151
Implement `rdoc --server[=PORT]` for previewing documentation with
automatic browser refresh on source file changes. The server parses all
sources on startup, serves pages from memory via the Aliki generator,
and watches for file modifications, additions, and deletions —
re-parsing only what changed.
https://github.com/user-attachments/assets/06d5ae7b-cc54-4cc5-a8b0-1cc30177cadb
## Changes
- **New `RDoc::Server`** (`lib/rdoc/server.rb`) — minimal HTTP server
using Ruby's built-in `TCPServer` (no WEBrick or external dependencies)
- Thread-per-connection with `Connection: close`
- Persistent Aliki generator instance rendering pages to strings
- In-memory page cache with full invalidation on changes
- Live reload via inline JS polling `/__status` endpoint every 1 second
- Background file watcher polling source file mtimes every 1 second
- Incremental re-parse: only changed files are re-parsed, old data
removed first
- Detection of new and deleted source files
- **`--server[=PORT]`** CLI option (default port 4000) and `rdoc:server`
Rake task
- **`RDoc::Store#remove_file`** — removes a file's entries from the
store hashes
- **`RDoc::Store#clear_file_contributions`** — surgically removes a
file's methods, constants, comments, includes, extends, and aliases from
its classes/modules, preserving classes that span multiple files.
Supports `keep_position:` for server re-parse to preserve comment
ordering.
- **`RDoc::RDoc#relative_path_for`** — extracted path normalization
(against `options.root` and `options.page_dir`) shared by `parse_file`
and the server
- **`Darkfish#refresh_store_data`** — extracted for reuse by the server
after re-parsing
- **`RDoc::Servlet` → `RDoc::RI::Servlet`** — moved to clarify
RI-specific usage
## Security & robustness
- Binds to `127.0.0.1` only (localhost)
- Path traversal protection in asset serving (`File.expand_path`
containment check)
- Proper HTTP error responses: 400, 404, 405, 500
- 5-second `IO.select` read timeout on client sockets
- Mutex protects all store mutations, generator refresh, and cache
invalidation atomically
- Individual `parse_file` errors rescued so one failure doesn't block
remaining files
- Watcher thread uses `@running` flag with clean shutdown via
`Thread#join`
## Known limitations
- **Full cache invalidation:** any file change clears all cached pages.
Rendering is fast (~ms per page); parsing is the expensive part and is
done incrementally.
- **Template/CSS changes:** require server restart (only source files
are watched).
---------
Co-authored-by: Sutou Kouhei <kou@clear-code.com>
8.**Stop server**: Kill the HTTP server process when done
334
360
335
-
**Tip:** Keep HTTP server running during iteration. Just regenerate with `bundle exec rake rerdoc` between changes.
361
+
**Note:** The server watches source files, not template files. If you modify `.rhtml` templates or CSS in the template directory, restart the server to pick up those changes.
362
+
363
+
## Visual Testing with Playwright CLI
364
+
365
+
Use `npx playwright` to take screenshots of generated documentation — works with both the live-reload server and static `_site/` output.
For server-specific E2E testing (endpoint checks, live-reload verification, file change detection), use the `/test-server` skill.
336
383
337
384
## Notes for AI Agents
338
385
@@ -345,64 +392,3 @@ When making changes to theme CSS or templates (e.g., Darkfish or Aliki themes):
345
392
4.**Use `rake rerdoc`** to regenerate documentation (not just `rdoc`)
346
393
5.**Verify generated files** with `rake verify_generated`
347
394
6.**Don't edit generated files** directly (in `lib/rdoc/markdown/` and `lib/rdoc/rd/`)
348
-
349
-
## Playwright MCP for Testing Generated Documentation
350
-
351
-
The Playwright MCP server enables visual inspection and interaction with generated HTML documentation. This is useful for verifying CSS styling, layout issues, and overall appearance.
352
-
353
-
**MCP Server:**`@playwright/mcp` (Microsoft's official browser automation server)
354
-
355
-
### Setup
356
-
357
-
The Playwright MCP server can be used with any MCP-compatible AI tool (Claude Code, Cursor, GitHub Copilot, OpenAI Agents, etc.).
358
-
359
-
**Claude Code:**
360
-
361
-
```bash
362
-
/plugin playwright
363
-
```
364
-
365
-
**Other MCP-compatible tools:**
366
-
367
-
```bash
368
-
npx @playwright/mcp@latest
369
-
```
370
-
371
-
Configure your tool to connect to this MCP server. Playwright launches its own browser instance automatically - no manual browser setup or extensions required.
If you encounter `DevTools remote debugging is disallowed by the system admin`, Chrome's debugging is blocked by the machine's policy. Use Firefox instead:
376
-
377
-
```bash
378
-
# Install Firefox for Playwright
379
-
npx playwright install firefox
380
-
381
-
# Add Playwright MCP with Firefox to your project (creates/updates .mcp.json)
# Start a simple HTTP server in the _site directory (use an available port)
396
-
cd _site && python3 -m http.server 8000
397
-
```
398
-
399
-
If port 8000 is already in use, try another port (e.g., `python3 -m http.server 9000`).
400
-
401
-
Then ask the AI assistant to inspect the documentation. It will use the appropriate Playwright tools (`browser_navigate`, `browser_snapshot`, `browser_take_screenshot`, etc.) based on your request.
402
-
403
-
**Example requests:**
404
-
405
-
- "Navigate to `http://localhost:8000` and take a screenshot"
406
-
- "Take a screenshot of the RDoc module page"
407
-
- "Check if code blocks are rendering properly on the Markup page"
408
-
- "Compare the index page before and after my CSS changes"
Copy file name to clipboardExpand all lines: README.md
+35Lines changed: 35 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -180,6 +180,41 @@ There are also a few community-maintained themes for RDoc:
180
180
181
181
Please follow the theme's README for usage instructions.
182
182
183
+
## Live Preview Server
184
+
185
+
RDoc includes a built-in server for previewing documentation while you edit source files. It parses your code once on startup, then watches for changes and auto-refreshes the browser.
186
+
187
+
```shell
188
+
rdoc --server
189
+
```
190
+
191
+
This starts a server at `http://localhost:4000`. You can specify a different port:
192
+
193
+
```shell
194
+
rdoc --server=8080
195
+
```
196
+
197
+
Or use the Rake task:
198
+
199
+
```shell
200
+
rake rdoc:server
201
+
```
202
+
203
+
### How It Works
204
+
205
+
- Parses all source files on startup and serves pages from memory using the Aliki theme
206
+
- A background thread polls file mtimes every second
207
+
- When a file changes, only that file is re-parsed — the browser refreshes automatically
208
+
- New files are detected and added; deleted files are removed
209
+
210
+
**No external dependencies.** The server uses Ruby's built-in `TCPServer` (`socket` stdlib) — no WEBrick or other gems required.
211
+
212
+
### Limitations
213
+
214
+
-**Reopened classes and file deletion.** If a class is defined across multiple files (e.g. `Foo` in both `a.rb` and `b.rb`), deleting one file removes the entire class from the store, including parts from the other file. Saving the remaining file triggers a re-parse that restores it.
215
+
-**Full cache invalidation.** Any file change clears all cached pages. This is simple and correct — rendering is fast (~ms per page), parsing is the expensive part and is done incrementally.
216
+
-**No HTTPS or HTTP/2.** The server is intended for local development preview only.
217
+
183
218
## Bugs
184
219
185
220
See [CONTRIBUTING.md](CONTRIBUTING.md) for information on filing a bug report. It's OK to file a bug report for anything you're having a problem with. If you can't figure out how to make RDoc produce the output you like that is probably a documentation bug.
0 commit comments