diff --git a/.gitignore b/.gitignore index 84a7f19..dca28e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ doc/html .DS_Store +doc/antora_specimen/build diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4ac83c2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "doc/antora_specimen/content"] + path = doc/antora_specimen/content + url = https://github.com/julioest/antora-specimen.git diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..150cfd0 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,321 @@ +# BoostLook CSS Development Guide + +This guide covers the workflow for developers working on `boostlook.css` and its integration with Boost documentation systems. + +## Table of Contents + +- [Overview](#overview) +- [Development Environment Setup](#development-environment-setup) +- [CSS Development Workflows](#css-development-workflows) + - [AsciiDoc Workflow](#asciidoc-workflow) + - [Antora Workflow](#antora-workflow) +- [File Structure](#file-structure) +- [CSS Architecture](#css-architecture) +- [Testing Your Changes](#testing-your-changes) +- [Integration Guidelines](#integration-guidelines) +- [Troubleshooting](#troubleshooting) + +## Overview + +BoostLook provides a unified styling system for Boost documentation that works with both: + +1. **AsciiDoc** - Traditional single-document rendering via Asciidoctor +2. **Antora** - Multi-component documentation sites + +The main stylesheet `boostlook.css` is designed to work across both systems while maintaining visual consistency. + +## Development Environment Setup + +### Prerequisites + +- **Ruby** (>= 2.7) +- **Node.js** (for Antora) +- **Required Ruby Gems**: + ```bash + gem install asciidoctor listen + ``` +- **Required Node Packages**: + ```bash + npm install -g @antora/cli @antora/site-generator + ``` +- **Boost.Build (b2)** - Available in PATH + +### Project Structure + +``` +boostlook/ +├── boostlook.css # Main stylesheet +├── boostlook.rb # Asciidoctor extension +├── boostlook_preview.rb # AsciiDoc live preview +├── boostlook_antora_preview.rb # Antora live preview +├── doc/ +│ ├── specimen.adoc # Test AsciiDoc document +│ ├── specimen-docinfo-footer.html +│ ├── Jamfile # Boost.Build configuration +│ ├── html/ # AsciiDoc build output +│ └── antora_specimen/ # Antora test site +│ ├── playbook.yml +│ ├── content/ +│ └── build/ +└── fonts/ # Noto font files +``` + +## CSS Development Workflows + +### AsciiDoc Workflow + +Use this workflow when developing styles for traditional AsciiDoc documentation. + +#### 1. Start Live Preview + +```bash +cd /path/to/boostlook +ruby boostlook_preview.rb +``` + +This will: +- Build `doc/specimen.adoc` using Boost.Build +- Open the result in your browser +- Watch for changes to `boostlook.css` and auto-rebuild + +#### 2. Edit CSS + +- Edit `boostlook.css` in your preferred editor +- Changes are automatically detected and trigger a rebuild +- Refresh your browser to see updates + +#### 3. Test Content + +- Edit `doc/specimen.adoc` to test different AsciiDoc elements +- The specimen document includes examples of: + - Headers and sections + - Code blocks + - Tables + - Lists and admonitions + - Cross-references + +#### Monitored Files + +The preview script watches these files for changes: +- `boostlook.css` +- `boostlook.rb` +- `doc/specimen.adoc` +- `doc/specimen-docinfo-footer.html` +- `doc/Jamfile` + +### Antora Workflow + +Use this workflow when developing styles for Antora-based documentation sites. + +#### 1. Start Antora Preview + +```bash +cd /path/to/boostlook +ruby boostlook_antora_preview.rb +``` + +This will: +- Build the Antora specimen site (if not already built) +- Copy `boostlook.css` to the build directory +- Open the site in your browser +- Watch for CSS changes and auto-update + +#### 2. Edit CSS + +- Edit `boostlook.css` in your preferred editor +- Changes are automatically copied to the Antora build +- Refresh your browser to see updates + +#### 3. Test with Real Content + +The Antora specimen includes: +- **Boost.URL** documentation (complete structure) +- **Specimen component** (test content) +- Navigation between components +- Real-world documentation patterns + +#### Features + +- **Fast Updates**: Only CSS is copied on changes (no full rebuild) +- **Hash Checking**: Prevents unnecessary updates +- **Multi-component**: Test navigation and component switching + +## File Structure + +### Core Files + +| File | Purpose | +|------|---------| +| `boostlook.css` | Main stylesheet (161KB, 4300+ lines) | +| `boostlook.rb` | Asciidoctor extension and integration | +| `boostlook_preview.rb` | AsciiDoc development server | +| `boostlook_antora_preview.rb` | Antora development server | + +### Test Documents + +| Path | Purpose | +|------|---------| +| `doc/specimen.adoc` | AsciiDoc test document | +| `doc/antora_specimen/` | Complete Antora test site | +| `doc/antora_specimen/content/url_component/` | Real Boost.URL docs | + +## CSS Architecture + +### Key Sections + +1. **Base Styles** - Typography, colors, layout fundamentals +2. **AsciiDoc Elements** - Styling for `.sect1`, `.listingblock`, etc. +3. **Antora Components** - Navigation, TOC, component switching +4. **Code Highlighting** - Syntax highlighting styles +5. **Responsive Design** - Mobile and tablet adaptations + +### CSS Classes + +#### AsciiDoc-specific +- `.sect1`, `.sect2`, etc. - Section headers +- `.listingblock` - Code blocks +- `.admonitionblock` - Warnings, notes, tips +- `.tableblock` - Tables + +#### Antora-specific +- `.nav-container` - Main navigation +- `.article` - Main content area +- `.toc` - Table of contents +- `.toolbar` - Header toolbar + +### Font Integration + +The stylesheet includes references to Noto fonts: +- `NotoSansDisplay.ttf` - Display text +- `NotoSansMono.ttf` - Monospace code +- Font files are loaded via `@font-face` declarations + +## Testing Your Changes + +### Browser Testing + +Test your changes across: +- **Chrome/Chromium** - Primary development browser +- **Firefox** - Secondary testing +- **Safari** (macOS) - WebKit compatibility +- **Mobile browsers** - Responsive design + +### Content Testing + +#### For AsciiDoc +- Headers (h1-h6) +- Code blocks with syntax highlighting +- Tables with various column types +- Lists (ordered, unordered, definition) +- Admonitions (NOTE, TIP, WARNING, etc.) +- Cross-references and links + +#### For Antora +- Component navigation +- Multi-level page hierarchy +- Search functionality +- Mobile navigation +- Component switching + +### Performance Considerations + +- **CSS Size**: Current file is 161KB - consider impact of additions +- **Font Loading**: Ensure fonts load efficiently +- **Mobile Performance**: Test on slower devices + +## Integration Guidelines + +### Adding New Styles + +1. **Follow existing patterns**: Study current CSS organization +2. **Use semantic naming**: `.boost-` prefix for custom classes +3. **Mobile-first**: Add responsive styles appropriately +4. **Test both systems**: Verify in both AsciiDoc and Antora + +### Modifying Existing Styles + +1. **Test thoroughly**: Changes affect existing documentation +2. **Check specificity**: Avoid overly specific selectors +3. **Maintain consistency**: Keep visual harmony across components + +### Version Control + +- Commit CSS changes with descriptive messages +- Include screenshots for visual changes +- Test builds before pushing + +## Troubleshooting + +### Common Issues + +#### Preview Script Not Starting +```bash +# Check Ruby installation +ruby -v + +# Install missing gems +gem install asciidoctor listen + +# Check Boost.Build +which b2 +``` + +#### Antora Build Fails +```bash +# Check Node.js and Antora +node -v +npx antora --version + +# Clear build and retry +rm -rf doc/antora_specimen/build +ruby boostlook_antora_preview.rb +``` + +#### CSS Changes Not Appearing + +1. **Clear browser cache**: Hard refresh (Ctrl+F5 / Cmd+Shift+R) +2. **Check file permissions**: Ensure CSS files are writable +3. **Verify file paths**: Check console for 404 errors +4. **Restart preview script**: Stop and restart the Ruby script + +#### Font Loading Issues + +- Verify font files are present in project root +- Check browser dev tools for font loading errors +- Ensure CORS headers allow font loading (for file:// URLs) + +### Debug Mode + +Both preview scripts support verbose logging: +```bash +# Add debug logging +RUBY_DEBUG=1 ruby boostlook_preview.rb +``` + +### Manual Builds + +If preview scripts fail, you can build manually: + +**AsciiDoc:** +```bash +cd doc +b2 +``` + +**Antora:** +```bash +cd doc/antora_specimen +npx antora playbook.yml +``` + +## Tips for Efficient Development + +1. **Use browser dev tools**: Inspect elements and test CSS changes live +2. **Keep both previews running**: Test AsciiDoc and Antora simultaneously +3. **Use CSS custom properties**: For consistent colors and measurements +4. **Comment your changes**: Help future developers understand your choices +5. **Test edge cases**: Very long titles, nested lists, complex tables + +--- + +For questions or issues, refer to the main [README.md](README.md) or check the project's issue tracker. diff --git a/README.md b/README.md index f860e92..ea80ffc 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ This is a set of stylesheets, templates, and code for Asciidoctor and Antora rendered documentation to give it a uniform look and feel befitting the quality of Boost. +## Documentation + +- **[DEVELOPMENT.md](DEVELOPMENT.md)** - Complete guide for developers working on `boostlook.css` +- **[Live Preview Setup](#live-preview-for-asciidoc-documentation)** - Quick start for AsciiDoc preview + +## Integration + Example of integration into a doc Jamfile: ``` html mp11.html : mp11.adoc diff --git a/boostlook_antora_preview.rb b/boostlook_antora_preview.rb new file mode 100755 index 0000000..7fe8847 --- /dev/null +++ b/boostlook_antora_preview.rb @@ -0,0 +1,240 @@ +#!/usr/bin/env ruby + +require 'listen' +require 'fileutils' +require 'logger' +require 'pathname' +require 'open3' +require 'digest/md5' + +# BoostlookAntoraPreview handles building the Antora specimen site and monitoring CSS changes +class BoostlookAntoraPreview + # Define relevant paths + PATHS = { + source_css: 'boostlook.css', + antora_dir: 'doc/antora_specimen', + build_dir: 'doc/antora_specimen/build/site', + build_css: 'doc/antora_specimen/build/site/_/css/boostlook.css', + playbook: 'doc/antora_specimen/playbook.yml', + ui_bundle: 'doc/antora_specimen/ui/ui-bundle.zip' + }.freeze + + # OS-specific commands to open the default web browser + OS_BROWSER_COMMANDS = { + /darwin/ => 'open', # macOS + /linux/ => 'xdg-open', # Linux + /mingw|mswin/ => 'start' # Windows + }.freeze + + def initialize + # Initialize the logger + @logger = Logger.new($stdout) + @logger.level = Logger::INFO + @logger.formatter = ->(_, _, _, msg) { "#{msg}\n" } + + @file_opened = false # Flag to prevent multiple browser openings + @shutdown_requested = false # Flag to handle graceful shutdown + @antora_version = nil # Will store the detected Antora version + @last_css_hash = nil # Store the last CSS file hash to avoid loops + @processing_change = false # Flag to prevent recursive change detection + end + + # Entry point to run the preview + def run + check_dependencies + ensure_site_built + setup_signal_traps + watch_files + end + + private + + # Check if Antora is installed and get its version + def check_dependencies + stdout, status = Open3.capture2('npx antora --version 2>/dev/null') + + unless status.success? + @logger.error("'npx antora' command failed. Please install Antora: npm i @antora/cli @antora/site-generator") + exit 1 + end + + # Extract version number + @antora_version = stdout.strip + @logger.info("Using Antora version: #{@antora_version}") + + # Check if source CSS exists + unless File.exist?(PATHS[:source_css]) + @logger.error("Source CSS file not found: #{PATHS[:source_css]}") + exit 1 + end + + # Check if playbook exists + unless File.exist?(PATHS[:playbook]) + @logger.error("Antora playbook not found: #{PATHS[:playbook]}") + exit 1 + end + end + + # Ensures the Antora site is built + def ensure_site_built + # If build directory doesn't exist or is empty, build the site + unless File.directory?(PATHS[:build_dir]) && !Dir.empty?(PATHS[:build_dir]) + @logger.info("Build directory not found or empty. Building Antora site...") + build_antora_site + end + + # After building, copy the current CSS to the build directory + if File.exist?(PATHS[:build_css]) + @logger.info("Copying current CSS to build directory...") + # Store the initial CSS hash + @last_css_hash = calculate_file_hash(PATHS[:source_css]) + copy_css_file + open_in_browser + else + @logger.error("Build CSS path not found after site build: #{PATHS[:build_css]}") + exit 1 + end + end + + # Builds the Antora site + def build_antora_site + @logger.info("Building Antora site...") + + Dir.chdir(PATHS[:antora_dir]) do + cmd = 'npx antora playbook.yml' + + # Add --fetch flag if UI bundle is configured as a remote URL in playbook + if ui_bundle_is_remote? + cmd = 'npx antora --fetch playbook.yml' + @logger.info("Remote UI bundle detected, using --fetch flag") + end + + if system(cmd) + @logger.info("Antora site built successfully") + true + else + @logger.error("Antora site build failed") + exit 1 + end + end + end + + # Check if the UI bundle in the playbook is configured as a remote URL + def ui_bundle_is_remote? + return false unless File.exist?(PATHS[:playbook]) + + content = File.read(PATHS[:playbook]) + ui_bundle_line = content.match(/^\s*ui:\s*$.*?^\s*bundle:\s*$.*?^\s*url:\s*(.+?)$/m) + + return false unless ui_bundle_line + + url = ui_bundle_line[1].strip + # Consider it remote if it starts with http://, https://, or git:// + url.start_with?('http://', 'https://', 'git://') + end + + # Calculate MD5 hash of a file + def calculate_file_hash(file_path) + Digest::MD5.hexdigest(File.read(file_path)) + end + + # Copies the CSS file to the build directory + def copy_css_file + begin + FileUtils.cp(PATHS[:source_css], PATHS[:build_css]) + @logger.info("CSS file updated: #{PATHS[:build_css]}") + true + rescue => e + @logger.error("Failed to copy CSS file: #{e.message}") + false + end + end + + # Opens the generated HTML file in the default web browser + def open_in_browser + return if @file_opened + + cmd = OS_BROWSER_COMMANDS.find { |platform, _| RUBY_PLATFORM =~ platform }&.last + if cmd + system("#{cmd} #{PATHS[:build_dir]}/index.html") + @file_opened = true + @logger.info("Opened site in browser: #{PATHS[:build_dir]}/index.html") + else + @logger.warn("Unsupported OS. Please open #{PATHS[:build_dir]}/index.html manually") + end + end + + # Sets up file listeners to watch for changes and trigger updates + def watch_files + @logger.info("Watching for changes in #{PATHS[:source_css]}...") + + @listener = Listen.to(File.dirname(PATHS[:source_css]), latency: 0.5) do |modified, added, _| + # Skip if we're already processing a change to avoid loops + next if @processing_change + + files = modified + added + css_file_changed = files.any? { |file| File.basename(file) == File.basename(PATHS[:source_css]) } + + if css_file_changed + # Calculate the new hash + current_hash = calculate_file_hash(PATHS[:source_css]) + + # Only process if the hash has actually changed + if current_hash != @last_css_hash + @processing_change = true + @logger.info("#{PATHS[:source_css]} changed, updating build directory...") + copy_css_file + @last_css_hash = current_hash + @processing_change = false + end + end + end + + @listener.start + + # Print instructions for the user + print_instructions + + # Keep the script running until shutdown is requested + until @shutdown_requested + sleep 1 + end + + shutdown + end + + # Prints usage instructions + def print_instructions + build_url = "file://#{File.expand_path(PATHS[:build_dir])}/index.html" + + @logger.info("") + @logger.info("=== Boostlook Antora Preview ===") + @logger.info("CSS file is being watched for changes") + @logger.info("Any changes to #{PATHS[:source_css]} will be automatically copied to the build directory") + @logger.info("") + @logger.info("To view the site, open this URL in your browser:") + @logger.info(" #{build_url}") + @logger.info("") + @logger.info("Press Ctrl+C to stop the preview") + @logger.info("================================") + @logger.info("") + end + + # Sets up signal traps to handle graceful shutdown on interrupt or terminate signals + def setup_signal_traps + Signal.trap("INT") { @shutdown_requested = true } + Signal.trap("TERM") { @shutdown_requested = true } + end + + # Performs shutdown procedures, such as stopping the file listener + def shutdown + @logger.info("Shutting down...") + @listener&.stop + exit + end +end + +# Run the preview +if __FILE__ == $0 + BoostlookAntoraPreview.new.run +end diff --git a/doc/antora_specimen/content b/doc/antora_specimen/content new file mode 160000 index 0000000..d1fceb5 --- /dev/null +++ b/doc/antora_specimen/content @@ -0,0 +1 @@ +Subproject commit d1fceb5897a578d36f16668881e067ae919b595b diff --git a/doc/antora_specimen/playbook.yml b/doc/antora_specimen/playbook.yml new file mode 100644 index 0000000..5f70925 --- /dev/null +++ b/doc/antora_specimen/playbook.yml @@ -0,0 +1,21 @@ +site: + title: Boostlook Antora Specimen + url: / + start_page: url::index.adoc + +content: + sources: + - url: ./content/url_component + - url: https://github.com/julioest/antora-specimen.git + branches: main + start_path: specimen_component + +ui: + bundle: + url: ./ui/ui-bundle.zip + # Or use the remote URL option + # url: https://github.com/boostorg/website-v2-docs/releases/download/ui-master/ui-bundle.zip + # snapshot: true + +output: + dir: ./build/site diff --git a/doc/antora_specimen/ui/ui-bundle.zip b/doc/antora_specimen/ui/ui-bundle.zip new file mode 100644 index 0000000..13a0383 Binary files /dev/null and b/doc/antora_specimen/ui/ui-bundle.zip differ