Conversation
- Add sidebar navigation with class list (always visible, collapsible on mobile) - Add client-side search across classes and methods (JavaScript, no server) - Modern responsive CSS with dark mode support (Catppuccin color palette) - Syntax highlighting for beamtalk code blocks in doc comments - Class hierarchy tree visualization on index page - Methods grouped by category: class methods, instance methods, inherited - Source link per method pointing to GitHub repo (lib/ files) - Mobile responsive with hamburger menu toggle - Keyboard shortcut (/) to focus search - All assets embedded as const strings (no external dependencies) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📝 WalkthroughWalkthroughDoc generator now records per-class source roots/files and per-method line numbers, builds a persistent sidebar and class hierarchy, emits a client-side search index (search.js), adds beamtalk syntax highlighting, and injects source links into generated class/method HTML pages. Changes
Sequence DiagramsequenceDiagram
participant User
participant CLI as "CLI Command"
participant Parser as "BEAM Parser"
participant Generator as "Doc Generator"
participant Assets as "Asset Builder"
participant Output as "Output Dir"
User->>CLI: run `beamtalk doc lib/ --output docs/api`
CLI->>Parser: read BEAM files and doc comments
Parser->>Parser: extract ClassInfo (incl. source_root/file) and MethodInfo (incl. line_number)
Parser-->>Generator: classes + metadata
Generator->>Generator: build sidebar HTML and hierarchy tree
Generator->>Assets: build search index and templates
Assets->>Output: write `search.js`, CSS, other assets
Generator->>Output: write `index.html` and per-class pages (with highlighted code and source links)
CLI-->>User: static docs generated in output dir
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@crates/beamtalk-cli/src/commands/doc.rs`:
- Around line 1171-1184: The code double-escapes doc comment summaries: the
manual .replace('\\', "\\\\").replace('"', "\\\"") applied when building summary
(from class.doc_comment) is then passed to json_escape(&summary), causing
backslashes to be quadrupled; remove the manual escaping step and assign summary
to the raw first line (e.g., let summary =
class.doc_comment.as_ref().and_then(|d|
d.lines().next()).unwrap_or("").to_string();) so that json_escape(&summary)
alone performs correct escaping before index_entries.push(...) which constructs
the JSON entry using class.name and summary.
- Around line 1382-1391: The loop that advances j over a quoted string can
overflow when a backslash appears as the last character: in the block that
checks if chars[j] == '\\', guard the escape increment so you never advance past
len (e.g., replace the unconditional j += 1 inside the if with a conditional
that only increments when j + 1 < len, or break/stop the loop when the backslash
is the final char), and ensure before using chars[i..j] you verify j <= len;
update the code around variables j, chars, quote, len, and i to perform that
bounds check to avoid panics when a string literal ends with a trailing
backslash.
- Around line 1354-1364: The loop that scans block comments (variables chars, j,
len) stops with the condition j + 1 < len which causes the last character to be
dropped for unterminated comments; change the loop to scan until the end (e.g.,
while j < len && !(chars[j] == '*' && j + 1 < len && chars[j + 1] == '/')) and
then after the loop, if a closing "*/" was found (j + 1 < len) advance j by 2,
otherwise set j = len so the unterminated comment consumes to the end without
losing the final character.
🧹 Nitpick comments (3)
crates/beamtalk-cli/src/commands/doc.rs (3)
1005-1011: Consider making the GitHub URL configurable.The source link URL is hardcoded to
jamesc/beamtalkon themainbranch withlib/prefix. This prevents usage with forks, feature branches, or different directory structures.Consider accepting a base URL pattern via CLI flag (e.g.,
--source-url "https://github.com/user/repo/blob/{branch}/{path}#L{line}") or deriving it from git remote config.
1266-1271: Incomplete HTML escaping in "No results" message.The query is escaped with only
replace(/</g,'<'), missing>,&, and quotes. For consistency with theesc()function used elsewhere, consider:resultsDiv.className = 'search-results active'; - resultsDiv.innerHTML = '<h2>Search Results</h2><p>No results for "' + - q.replace(/</g,'<') + '"</p>'; + resultsDiv.innerHTML = '<h2>Search Results</h2><p>No results for "' + + esc(q) + '"</p>'; return;
860-863: Active state pattern works but is fragile.The string replace approach to add the
activeclass relies on exact HTML structure matching. This works but could break if the sidebar format changes. Consider an alternative like passing the active class name tobuild_sidebar_html.
There was a problem hiding this comment.
Pull request overview
This PR significantly enhances the beamtalk doc command to generate ExDoc/rustdoc-quality HTML documentation with modern UI features including sidebar navigation, client-side search, syntax highlighting, and responsive design.
Changes:
- Adds sidebar navigation with always-visible class list and active state highlighting
- Implements JavaScript-based search across classes and methods with keyboard shortcut support (
/to focus) - Adds custom syntax highlighter for Beamtalk code blocks with support for keywords, strings, numbers, comments, symbols, and class names
- Implements class hierarchy tree visualization on the index page
- Adds source links to GitHub for each method (with line numbers)
- Introduces modern responsive CSS with Catppuccin color palette and dark mode via
prefers-color-scheme - Embeds all assets (CSS, JS) as const strings for zero external dependencies
- Fix double escaping bug in search index summary text - Fix unterminated block comment losing last character in highlighter - Fix potential panic with malformed string ending in backslash Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/beamtalk-cli/src/commands/doc.rs (1)
957-977:⚠️ Potential issue | 🟠 MajorInherited methods currently omit source links.
Line 974 calls
write_method_html, which drops source links. The requirement calls for per‑method links; you already haveall_classes, so you can attach the parent’ssource_file.🔧 Suggested fix to include parent source links
for (parent_name, methods) in inherited { let _ = writeln!( html, "<h3>From {}</h3>", class_link(parent_name, all_classes) ); + let parent_source = all_classes + .get(*parent_name) + .and_then(|c| c.source_file.as_deref()); for method in *methods { - write_method_html(html, method, all_classes); + write_method_html_with_source(html, method, parent_source); } }
🤖 Fix all issues with AI agents
In `@crates/beamtalk-cli/src/commands/doc.rs`:
- Around line 169-170: The code currently sets source_file from path.file_name()
which drops subdirectories and later formats links as "lib/{file}", causing
incorrect links for nested or non-lib inputs; update the logic that computes
source_file to store the path relative to the input root (e.g., use
Path::strip_prefix(input_root) or compute a relative path and call
to_string_lossy().into_owned() instead of file_name()), preserve any
subdirectory components, and then change the link-emission code that currently
hard-codes "lib/{file}" to only emit that base when the known root is "lib" or
use a configurable base path (ensure you reference the same source_file variable
and the link-creation block where "lib/{file}" is used).
- Around line 1082-1084: The search input HTML string lacks an accessible label;
update the literal that renders the input (the string containing
id="sidebar-search" and class="sidebar-search") to include an accessible
label—either add an aria-label attribute like aria-label="Search classes" to the
input, or add a visually hidden <label for="sidebar-search">Search
classes</label> alongside it so screen readers announce its purpose; locate the
input by its id "sidebar-search" in the doc rendering code and make the change
there.
- Use .lines().count() for CRLF-safe line number calculation - Use esc() for complete HTML escaping in search results - Add aria-label to search input for accessibility - Preserve relative paths for nested source directories - Pass source root through to link generation instead of hardcoding lib/ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/beamtalk-cli/src/commands/doc.rs (1)
46-61:⚠️ Potential issue | 🟡 MinorFix source links when docs are generated from a single file path.
If the input path is a single file,
source_rootbecomes the file path andstrip_prefixyields an empty relative path, which makes source links malformed (e.g.,Foo.bt/paths). Normalize the root to a directory before passing it intoparse_class_info(and use it for README lookup).🔧 Suggested fix
- let source_path = Utf8PathBuf::from(path); + let source_path = Utf8PathBuf::from(path); + let source_root = if source_path.is_file() { + source_path + .parent() + .unwrap_or_else(|| Utf8Path::new(".")) + .to_path_buf() + } else { + source_path.clone() + }; // Find .bt source files let source_files = find_source_files(&source_path)?; @@ - for file in &source_files { - if let Some(class_info) = parse_class_info(&source_path, file)? { + for file in &source_files { + if let Some(class_info) = parse_class_info(&source_root, file)? { classes.push(class_info); } } @@ - let readme_path = source_path.join("README.md"); + let readme_path = source_root.join("README.md");Also applies to: 170-175, 946-1019
Summary
Upgrades
beamtalk docfrom basic HTML output to ExDoc/rustdoc-quality documentation with modern UI features.Linear issue: https://linear.app/beamtalk/issue/BT-616
Key Changes
/to focus)prefers-color-scheme, mobile-first responsive layoutself)Technical Details
conststrings — zero external dependenciesClassInfo/MethodInfostructsGenerated Output
beamtalk doc lib/ --output docs/apiworks end-to-endSummary by CodeRabbit
New Features
Documentation
Tests