|
| 1 | +# RDoc Current Feature State (branch: stan-talk-prep) |
| 2 | + |
| 3 | +Research for RubyKaigi talk preparation. Based on code at `/Users/hung-wulo/src/github.com/Shopify/rdoc-talk-prep`. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## 1. Aliki Theme |
| 8 | + |
| 9 | +**What it is:** A modern, from-scratch HTML theme that subclasses `RDoc::Generator::Darkfish`. Authored by Stan Lo. Located at `lib/rdoc/generator/aliki.rb` with templates in `lib/rdoc/generator/template/aliki/`. |
| 10 | + |
| 11 | +### How it differs from Darkfish |
| 12 | + |
| 13 | +| Feature | Darkfish | Aliki | |
| 14 | +|---------|----------|-------| |
| 15 | +| Layout | Two-column (sidebar + content) | Three-column (sidebar + content + right-side TOC) | |
| 16 | +| Dark mode | None | Full dark mode with `data-theme` toggle, localStorage persistence, and system preference detection | |
| 17 | +| CSS size | 702 lines, ships embedded fonts (Lato, SourceCodePro) | 1994 lines, uses system font stack (no embedded fonts = lighter output) | |
| 18 | +| CSS architecture | Flat styles | Design system with CSS custom properties (tokens for colors, spacing, typography, shadows, transitions, z-index) | |
| 19 | +| JS files | 2 files (260 lines total: darkfish.js, search.js) | 7 files: aliki.js, theme-toggle.js, search_controller.js, search_navigation.js, search_ranker.js, c_highlighter.js, bash_highlighter.js | |
| 20 | +| Search | Basic search.js | Custom ranked search with fuzzy matching, namespace/method-aware queries, tiered scoring (exact > prefix > substring > fuzzy), type-aware priority, search snippets, type badges | |
| 21 | +| Search index | Uses JsonIndex generator (separate pass) | Built-in `write_search_index` / `build_search_index` (no extra generator needed), writes `js/search_data.js` | |
| 22 | +| Mobile | No specific mobile support | Responsive grid layout, mobile search modal, hamburger sidebar toggle, viewport-aware JS | |
| 23 | +| Syntax highlighting | None for C or shell code | Client-side C highlighter (keywords, types, macros, strings, preprocessor directives, Ruby C API types like VALUE/ID) and bash/shell highlighter (prompts, commands, options, strings, env vars, comments) | |
| 24 | +| TOC | Server-side sidebar TOC only | Auto-generated right-sidebar "On This Page" TOC from headings with IntersectionObserver scroll-spy, smooth scrolling | |
| 25 | +| Code blocks | Plain `<pre>` | Copy-to-clipboard buttons dynamically added to all `<pre>` elements | |
| 26 | +| Header/Footer | Minimal | Top navbar with brand, search bar, theme toggle; customizable footer via `footer_content` option in `.rdoc_options` | |
| 27 | +| Open Graph / SEO | None | Full Open Graph and Twitter Card meta tags, canonical URL support, rich `<meta>` descriptions | |
| 28 | +| Icons | Silk icon sprites (images/) | Inline SVG symbol sprites (no image files) | |
| 29 | +| Breadcrumbs | Yes | Yes (same approach) | |
| 30 | +| Method entries | Standard list | Styled as "signature cards" (commit dc7a1679) | |
| 31 | +| Ancestor tree | Shows parent class only | Full ancestor chain with recursive nested `<ul>` | |
| 32 | +| Source language | `<pre>` (no class) | `<pre class="c">` or `<pre class="ruby">` via `method.source_language` - enables language-specific highlighting | |
| 33 | + |
| 34 | +### Key design decisions |
| 35 | +- Sidebar is hidden by default with `hidden` attribute, shown by JS on large viewports. This avoids sidebar flicker on mobile page load. |
| 36 | +- Search data is written as `.js` (not `.json`) to avoid CORS issues when viewing generated docs via `file://` protocol. |
| 37 | +- `resolve_url(rel_prefix, url)` helper ensures absolute URLs pass through unchanged while relative URLs get prefixed correctly. |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +## 2. Markdown Support (GFM) |
| 42 | + |
| 43 | +**Parser:** `lib/rdoc/markdown.kpeg` (PEG grammar compiled to `lib/rdoc/markdown.rb`). |
| 44 | + |
| 45 | +### Default extensions enabled |
| 46 | +- `definition_lists` - PHP Markdown Extra style |
| 47 | +- `github` - fenced code blocks, syntax highlighting, tables, strikethrough |
| 48 | +- `html` - raw HTML blocks |
| 49 | +- `notes` - footnotes |
| 50 | +- `strike` - `~~strikethrough~~` |
| 51 | + |
| 52 | +### GFM features supported |
| 53 | +- Fenced code blocks (triple backtick with optional language tag) |
| 54 | +- Tables (header, alignment, body rows with inline markdown in cells) |
| 55 | +- Strikethrough (`~~text~~`) |
| 56 | +- Auto-linking of bare URLs |
| 57 | +- Underscores in words are never treated as emphasis |
| 58 | + |
| 59 | +### `break_on_newline` extension |
| 60 | +- Converts all newlines into hard line breaks (GFM-style). Commit `d62b0321` enabled this by default. **Note:** it is listed as an extension but NOT in `DEFAULT_EXTENSIONS` in the kpeg source - it appears the default enablement may be done elsewhere or the commit was on a different branch. |
| 61 | + |
| 62 | +### Recent markdown improvements (from git log) |
| 63 | +- `bd0e544f` - Fix blockquote lazy continuation parsing |
| 64 | +- `d62b0321` - Enable `break_on_newline` by default |
| 65 | +- `c59a7a89` - Fix table parser consuming lines without pipes |
| 66 | +- `52b24c2d` - Implement escapes in Markdown-to-RDoc conversion |
| 67 | +- `0602d13b` - Align strikethrough with GitHub Markdown spec |
| 68 | +- `39f5a2d9` - Fix backslash handling in table cell code spans |
| 69 | +- `eaac67d3` - Support markdown syntax in table cells |
| 70 | +- `393c0e87` - Add comparison with GitHub Flavored Markdown spec |
| 71 | + |
| 72 | +### Markdown output (`lib/rdoc/markup/to_markdown.rb`) |
| 73 | +- `RDoc::Markup::ToMarkdown` converts RDoc's internal markup tree back to Markdown format |
| 74 | +- Subclasses `ToRdoc`, overrides heading markers to `#`/`##`/etc. |
| 75 | +- Handles lists (bullet, numbered, definition/label) |
| 76 | + |
| 77 | +### What is NOT supported |
| 78 | +- Task lists / checkboxes |
| 79 | +- GitHub-style alerts (`> [!NOTE]`, `> [!WARNING]`) |
| 80 | +- Autolinks without angle brackets (bare URL auto-linking is RDoc-specific, not the GFM autolink extension) |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +## 3. RBS Integration |
| 85 | + |
| 86 | +**Status: Not present in this branch.** |
| 87 | + |
| 88 | +Grep for `rbs`, `RBS`, `type_sig`, `rbs_` across `lib/` returned zero matches. There is no RBS type signature parsing, display, or integration in the generator, parser, or templates. |
| 89 | + |
| 90 | +The memory file mentions prior investigation into "RBS Integration Phase 1" with inline `#:` type sigs in HTML output, but this code is not on the current `stan-talk-prep` branch. |
| 91 | + |
| 92 | +--- |
| 93 | + |
| 94 | +## 4. LLM/AI Support (llms.txt) |
| 95 | + |
| 96 | +**Status: Not present.** |
| 97 | + |
| 98 | +Grep for `llms`, `llm`, `LLM`, `llms.txt` across the entire codebase (`.rb` files and all files) returned zero relevant matches. There is no `llms.txt` generator, no LLM-friendly output format, and no AI-related features. |
| 99 | + |
| 100 | +--- |
| 101 | + |
| 102 | +## 5. Server Mode (Live Reload) |
| 103 | + |
| 104 | +**File:** `lib/rdoc/server.rb` (394 lines) |
| 105 | + |
| 106 | +### Architecture |
| 107 | +- Invoked via `rdoc --server` (added in commit `3c6f5f6f`) |
| 108 | +- Uses Ruby's built-in `TCPServer` - no WEBrick, no external dependencies |
| 109 | +- Binds to `127.0.0.1:<port>` |
| 110 | +- Multi-threaded: one thread per client connection, plus a background file watcher thread |
| 111 | +- Uses the Aliki generator exclusively (`RDoc::Generator::Aliki`) |
| 112 | + |
| 113 | +### Live reload mechanism |
| 114 | +1. Background watcher thread polls source file mtimes every 1 second |
| 115 | +2. Detects modified, new, and deleted files |
| 116 | +3. On change: re-parses only changed files via `@rdoc.parse_file(f)`, clears stale contributions, refreshes generator data, invalidates page cache |
| 117 | +4. Injects a `<script>` polling snippet before `</body>` in every HTML response |
| 118 | +5. Browser polls `/__status` every 1 second, comparing `last_change` timestamp |
| 119 | +6. If timestamp changed, browser does `location.reload()` |
| 120 | + |
| 121 | +### Request routing |
| 122 | +- `/__status` - returns JSON `{last_change: <float>}` for live reload |
| 123 | +- `/css/*`, `/js/*` - serves static assets from Aliki template directory (with path traversal protection) |
| 124 | +- `/js/search_data.js` - dynamically generated search index |
| 125 | +- `/index.html` - calls `@generator.generate_index` |
| 126 | +- `/table_of_contents.html` - calls `@generator.generate_table_of_contents` |
| 127 | +- `/ClassName.html` - looks up class/module in store, renders via generator |
| 128 | +- `/filename.html` - looks up text page in store |
| 129 | +- 404s rendered through `generate_servlet_not_found` |
| 130 | + |
| 131 | +### Page caching |
| 132 | +- Pages are cached in `@page_cache` (hash) |
| 133 | +- Cache is fully invalidated on any file change (entire hash cleared) |
| 134 | +- Mutex protects all shared state (`@page_cache`, `@last_change_time`, store operations) |
| 135 | + |
| 136 | +### Terminal output |
| 137 | +- Prints clickable hyperlink to terminal using OSC 8 escape sequences |
| 138 | +- Logs `<status> <path> (<duration>ms)` for page requests |
| 139 | +- Logs re-parse timing: `Re-parsed <files> (<duration>ms)` |
| 140 | +- Status/asset requests are not logged (to reduce noise) |
| 141 | + |
| 142 | +### Recent fixes |
| 143 | +- `e4e332f2` - Print timing for page requests and re-parsing |
| 144 | +- `237f113d` - Fix deadlock on Ctrl+C |
| 145 | +- `78325e18` - Fix live reload for C files |
| 146 | +- `8323a434` - Fix page links returning 404 |
| 147 | + |
| 148 | +--- |
| 149 | + |
| 150 | +## 6. Markup Generator (`lib/rdoc/generator/markup.rb`) |
| 151 | + |
| 152 | +This is NOT a standalone generator - it is a mixin module (`RDoc::Generator::Markup`) included into `RDoc::CodeObject` and `RDoc::Context::Section`. It provides HTML rendering helpers used by the Darkfish/Aliki generators: |
| 153 | + |
| 154 | +- `description` - renders a CodeObject's comment as HTML |
| 155 | +- `formatter` - creates an `RDoc::Markup::ToHtmlCrossref` formatter for cross-reference linking |
| 156 | +- `aref_to(target_path)` / `as_href(from_path)` - relative URL generation between pages |
| 157 | +- `cvs_url(url, full_path)` - web repository link construction |
| 158 | +- `canonical_url` - builds canonical URL using `@store.options.canonical_root` |
| 159 | +- `RDoc::MethodAttr#markup_code` - converts token stream to HTML with optional line numbers |
| 160 | +- `RDoc::ClassModule#description` - renders from `@comment_location` (multi-file comment support) |
| 161 | + |
| 162 | +The separate `RDoc::Markup::ToMarkdown` class in `lib/rdoc/markup/to_markdown.rb` converts RDoc markup tree back to Markdown text output (headings, lists, etc.) but is not used by any generator for documentation output. |
| 163 | + |
| 164 | +--- |
| 165 | + |
| 166 | +## Summary for Talk |
| 167 | + |
| 168 | +### Shipping / Ready |
| 169 | +1. **Aliki theme** - Complete modern theme with dark mode, responsive layout, three-column design, advanced search, C/bash syntax highlighting, copy-to-clipboard, SVG icons, Open Graph metadata, customizable footer |
| 170 | +2. **Server mode** - Zero-dependency live-reload server using TCPServer, file watching with incremental re-parsing, page caching |
| 171 | +3. **GFM improvements** - Tables with inline markdown, strikethrough aligned with GFM spec, blockquote fixes, fenced code blocks, GFM spec comparison tests |
| 172 | + |
| 173 | +### Not present |
| 174 | +4. **RBS integration** - No type signature display in generated docs |
| 175 | +5. **LLM support** - No `llms.txt` generation or LLM-friendly output |
| 176 | +6. **Markdown output generator** - `ToMarkdown` exists as a formatter but is not wired to any documentation output generator |
0 commit comments