From 9acca53da40dfb56e18188ae202c3c73a0097d11 Mon Sep 17 00:00:00 2001 From: Julio Estrada Date: Mon, 9 Jun 2025 21:17:56 -0400 Subject: [PATCH] feat: add Antora and AsciiDoc preview scripts --- .gitignore | 14 + DEVELOPMENT.md | 289 ++++++++++++++++++ README.md | 114 ++----- boostlook_antora_preview.rb | 264 ++++++++++++++++ ...review.rb => boostlook_asciidoc_preview.rb | 0 doc/antora_specimen/.gitignore | 16 + doc/antora_specimen/playbook.yml | 18 ++ 7 files changed, 619 insertions(+), 96 deletions(-) create mode 100644 DEVELOPMENT.md create mode 100755 boostlook_antora_preview.rb rename boostlook_preview.rb => boostlook_asciidoc_preview.rb (100%) create mode 100644 doc/antora_specimen/.gitignore create mode 100644 doc/antora_specimen/playbook.yml diff --git a/.gitignore b/.gitignore index 84a7f19..9be64f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,16 @@ doc/html .DS_Store + +# Antora build artifacts +doc/antora_specimen/build/ +doc/antora_specimen/node_modules/ +**/build/site/ + +# Node.js and npm artifacts +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Antora cache +.cache/ diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..4e1f083 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,289 @@ +# BoostLook Development Guide + +This guide explains how to develop and test BoostLook styling using two complementary preview workflows: simple AsciiDoc testing and production-like Antora testing. + +## Overview + +BoostLook provides two preview workflows for developing and testing CSS changes: + +- **Preview with AsciiDoc**: Fast iteration with simple AsciiDoc files for quick CSS testing +- **Preview with Antora**: Comprehensive testing using real Boost documentation content via Antora Specimen + +Both workflows provide automatic file watching, rebuilding, and browser preview to streamline your development process. + +## Preview Workflows + +### Preview with AsciiDoc + +**Use Case**: Rapid CSS iteration and basic styling verification +**Script**: `boostlook_asciidoc_preview.rb` +**Content**: Your local AsciiDoc files (e.g., `doc/specimen.adoc`) +**Build System**: Boost.Build (b2) +**Speed**: Fast, immediate feedback + +This workflow monitors AsciiDoc, HTML, and CSS files for changes, automatically rebuilding via Boost.Build and opening the rendered HTML in your browser. + +### Preview with Antora + +**Use Case**: Realistic testing with actual Boost documentation structure and content +**Script**: `boostlook_antora_preview.rb` +**Content**: Real Boost.URL documentation fetched from GitHub +**Build System**: Antora site generator +**Speed**: More comprehensive, production-like environment + +This workflow uses **Antora Specimen** - a testing setup that fetches official Boost.URL documentation and applies your local BoostLook styling, providing a realistic testing environment with actual production content. + +## Prerequisites + +### Common Requirements +- **Ruby** (>= 2.7 recommended) +- **Listen Gem** – Install via `gem install listen` + +### Preview with AsciiDoc Requirements + +- **Asciidoctor Gem**: Install via `gem install asciidoctor`. +- **Boost.Build (b2)**: Ensure `b2` is installed and available in your system's `PATH`. You can verify this by running `which b2` or `b2 --version`. +- **Boost.Build Configuration (`user-config.jam`)**: This is a critical step. You must tell Boost.Build where to find your `asciidoctor` executable. + 1. Find the full path to `asciidoctor` by running: + ```sh + which asciidoctor + ``` + The output will be a path like `/usr/local/bin/asciidoctor`. + + 2. Create or edit the file `user-config.jam` in your home directory (`$HOME/user-config.jam` on Linux/macOS). + + 3. Add the following line to the file, using the path from step 1: + ```jam + # Tell Boost.Build where to find the asciidoctor executable + using asciidoctor : /usr/local/bin/asciidoctor ; + ``` + +### Preview with Antora Requirements +- **Node.js** – For Antora CLI +- **Antora CLI** – Install via `npm install -g @antora/cli @antora/site-generator` + +## Quick Start + +### Preview with AsciiDoc + +1. **Install Prerequisites**: + ```bash + # Check Ruby installation + ruby -v + + # Install required gems + gem install asciidoctor listen + + # Verify Boost.Build availability + which b2 + ``` + +2. **Prepare Content**: + - Place AsciiDoc files in the `doc/` directory + - Default test file: `doc/specimen.adoc` + +3. **Start Preview**: + ```bash + # From project root + ruby boostlook_asciidoc_preview.rb + ``` + +4. **Development Workflow**: + - Edit `boostlook.css` or AsciiDoc files in `doc/` + - Script automatically detects changes and rebuilds + - Browser opens automatically with rendered content + - Refresh browser to see changes + +### Preview with Antora + +1. **Install Prerequisites**: + ```bash + # Install Antora CLI + npm install -g @antora/cli @antora/site-generator + + # Install Ruby gem for file watching + gem install listen + ``` + +2. **Start Preview** (with automatic setup): + ```bash + # Force rebuild and start watching + ruby boostlook_antora_preview.rb --rebuild + ``` + +3. **Development Workflow**: + - Edit `boostlook.css` → Triggers automatic rebuild + - Edit `boostlook.rb` → Triggers automatic rebuild + - View changes in browser (auto-opened) + - Repeat until styling is perfect + +## File Structure + +### Preview with AsciiDoc Structure +``` +boostlook/ +├── boostlook.css # Your main CSS file +├── boostlook.rb # Antora extension (Ruby) +├── boostlook_asciidoc_preview.rb # AsciiDoc preview script +└── doc/ + ├── specimen.adoc # Test AsciiDoc file + └── ... # Other AsciiDoc files +``` + +### Preview with Antora Structure +``` +boostlook/ +├── boostlook.css # Your main CSS file +├── boostlook.rb # Antora extension (Ruby) +├── boostlook_antora_preview.rb # Antora preview script +└── doc/ + └── antora_specimen/ + ├── playbook.yml # Antora configuration + └── build/ # Generated site (git-ignored) + └── site/ + ├── index.html # Entry point + └── _/css/ + └── boostlook.css # Your CSS (auto-copied) +``` + +## What You're Testing Against + +### Preview with AsciiDoc +- **Content**: Your custom AsciiDoc files +- **Structure**: Simple document structure +- **Elements**: Basic typography, code blocks, tables +- **Speed**: Very fast iteration cycles + +### Preview with Antora +- **Content**: Official Boost.URL documentation from GitHub +- **Structure**: Actual Antora-generated documentation +- **Elements**: Real typography, code blocks, tables, navigation, etc. +- **Complexity**: Multi-level navigation, cross-references, production patterns + +## Configuration + +### AsciiDoc Preview Configuration +The AsciiDoc preview uses your existing Boost.Build configuration. Ensure your `build.jam` or similar build files are properly configured for BoostLook integration. + +### Antora Preview Configuration (`doc/antora_specimen/playbook.yml`) +```yaml +site: + title: Boostlook Antora Specimen + url: / + start_page: url::index.adoc + +content: + sources: + - url: https://github.com/boostorg/url.git + branches: develop + start_path: doc + +ui: + bundle: + url: https://github.com/boostorg/website-v2-docs/releases/download/ui-master/ui-bundle.zip + snapshot: true + +output: + dir: ./build/site +``` + +**Key Points:** +- **No git submodules** - Content fetched automatically +- **Remote UI bundle** - Official Boost documentation UI +- **Your CSS overrides** - Applied automatically after build + +## Preview Script Features + +### AsciiDoc Preview Features +- **File Watching**: Monitors `doc/` directory and root CSS files +- **Automatic Building**: Uses Boost.Build (b2) for rendering +- **Browser Integration**: Opens rendered HTML automatically +- **Cross-platform**: Works on macOS, Linux, Windows + +### Antora Preview Features +- **Automatic CSS Override**: Copies your current `boostlook.css` over outdated UI bundle version +- **Smart Rebuilding**: CSS changes trigger full rebuild (processed by Ruby extension) +- **Content Fetching**: Automatically downloads latest Boost.URL documentation +- **File Hash Checking**: Avoids unnecessary rebuilds + +## Manual Testing Commands + +### Preview with AsciiDoc (Manual) +```bash +# Build once without watching +b2 doc/specimen.html + +# Serve locally (if needed) +python -m http.server 8000 +``` + +### Preview with Antora (Manual) +```bash +# Build once without watching +cd doc/antora_specimen +npx antora --fetch playbook.yml + +# Copy your current CSS +cp ../../boostlook.css build/site/_/css/boostlook.css + +# Serve locally +npx http-server build/site -p 8080 +``` + +## Troubleshooting + +### Preview with AsciiDoc Issues + +**Error: `error: no generators were found for type 'HTML'`** + +- **Cause**: This is the most common issue. It means Boost.Build (`b2`) cannot find the `asciidoctor` executable. +- **Solution**: You must configure your `$HOME/user-config.jam` file. Please follow the instructions in the **"Boost.Build Configuration (`user-config.jam`)"** section under Prerequisites. + +**Error: `command not found: b2`** + +- **Cause**: The Boost.Build `b2` executable is not in your system's `PATH`. +- **Solution**: Install Boost.Build and ensure its location is added to your `PATH`. Verify with `which b2`. + +**Script must be run from the project root** + +- **Cause**: The script expects to be run from the main `boostlook/` directory. +- **Solution**: Make sure you are in the project's root directory before running `ruby boostlook_asciidoc_preview.rb`. + +**Warnings like `www-browser: not found` or `xdg-open: ... not found`** + +- **Cause**: These warnings may appear on some Linux systems if the script cannot find a default command-line web browser. +- **Solution**: These are usually harmless and can be ignored if a graphical browser still opens. To resolve them, you can install a common utility like `xdg-utils` (`sudo apt-get install xdg-utils` on Debian/Ubuntu). + +### Preview with Antora Issues + +**Build Fails:** +```bash +# Check Antora installation +npx antora --version + +# Check if playbook is valid +cd doc/antora_specimen +npx antora playbook.yml --dry-run +``` + +**CSS Not Updating:** +```bash +# Force complete rebuild +ruby boostlook_antora_preview.rb --rebuild + +# Manually verify CSS copy +ls -la doc/antora_specimen/build/site/_/css/boostlook.css +``` + +**Preview Script Issues:** +```bash +# Check if listen gem is installed +gem list | grep listen + +# Install if missing +gem install listen +``` + +**Node.js/Antora Issues:** +- Ensure Node.js is installed: `node --version` +- Install/reinstall Antora: ` diff --git a/README.md b/README.md index f860e92..1d68458 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,33 @@ # BoostLook -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. +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. -Example of integration into a doc Jamfile: -``` +## Integration + +Example integration into a doc Jamfile: +```jam html mp11.html : mp11.adoc : /boost/boostlook//boostlook mp11-docinfo-footer.html ; ``` -Noto font files are covered under the Open Font License: - -https://fonts.google.com/noto/use - -## Live Preview for AsciiDoc Documentation - -BoostLook includes a **live preview** feature to streamline local development and review of AsciiDoc documentation. This allows for automatic rendering and real-time browser preview of changes made to [`specimen.adoc`](/doc/specimen.adoc) and [`boostlook.css`](/boostlook.css) files. - -### Overview - -The preview functionality is handled by a Ruby script ([`boostlook_preview.rb`](./boostlook_preview.rb)). This script monitors AsciiDoc, HTML, and CSS files for changes, automatically rebuilding and opening the rendered HTML in your default web browser. - ---- - -### Prerequisites - -Ensure the following dependencies are installed: - -- **Ruby** (>= 2.7 recommended) -- **Asciidoctor** – Install via `gem install asciidoctor` -- **Listen Gem** – Install via `gem install listen` -- **Boost.Build (b2)** – Required for builds invoked by the script. Ensure it is installed and available in your system's PATH. - ---- - -### Usage and Detailed Steps - -1. **Install Ruby and Required Gems**: - - Ensure Ruby is installed on your system. You can check by running: - ```bash - ruby -v - ``` - If Ruby is not installed, follow the instructions on [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/) to install it. - - Install Asciidoctor: - ```bash - gem install asciidoctor - ``` - - Install the Listen gem: - ```bash - gem install listen - ``` - -2. **Install Boost.Build (b2)**: - - Follow the instructions on the [Boost.Build website](https://boostorg.github.io/build/) to install `b2`. - - Ensure `b2` is available in your system's PATH by running: - ```bash - which b2 - ``` - -3. **Locate Specimen AsciiDoc File**: - - Place your AsciiDoc files in the `doc` directory. The default file is `doc/specimen.adoc`. - - The default file structure should include: - - ``` - /boostlook - ├── doc - │ └── specimen.adoc <-- - │ └── ... - ├── boostlook.css - └── boostlook_preview.rb - └── boostlook.rb - └── ... - ``` - -4. **Navigate to the project directory**: - ```bash - cd /path/to/boostlook - ``` - -5. **Run the preview script**: - - Ensure you're in the root folder - ```bash - ruby boostlook_preview.rb - ``` - -6. **Edit and Preview**: - - Edit your AsciiDoc (specimen.adoc) or CSS (boostlook.css) files. - - The script will automatically detect changes and rebuild the documentation. - - Refresh the browser to see changes. +## Development -7. **Refresh Your Browser** to view changes. +For CSS development, testing, and preview workflows, see **[DEVELOPMENT.md](DEVELOPMENT.md)**: ---- +- **Preview with AsciiDoc**: Quick CSS testing with simple AsciiDoc files +- **Preview with Antora**: Production testing with real Boost documentation content +- Setup instructions, prerequisites, and troubleshooting -### Troubleshooting +## Font License -- **Script Not Running**: - - Ensure all prerequisites are installed correctly. - - Check for any error messages in the terminal and resolve them accordingly. +Noto font files are covered under the Open Font License: https://fonts.google.com/noto/use -- **Changes Not Reflecting**: - - Ensure the files being edited are within the monitored directories (`doc` and root directory). - - Verify that the browser is refreshing automatically or manually refresh the browser. +## Files -- **Boost.Build (b2) Not Found**: - - Ensure `b2` is installed and available in your system's PATH. - - Run `which b2` to verify its availability. +- `boostlook.css` - Main stylesheet +- `boostlook.rb` - Antora extension +- `boostlook_asciidoc_preview.rb` - AsciiDoc preview script +- `boostlook_antora_preview.rb` - Antora preview script +- Font files: `*.woff`, `*.woff2`, `*.ttf` diff --git a/boostlook_antora_preview.rb b/boostlook_antora_preview.rb new file mode 100755 index 0000000..e19777f --- /dev/null +++ b/boostlook_antora_preview.rb @@ -0,0 +1,264 @@ +#!/usr/bin/env ruby + +require 'listen' +require 'fileutils' +require 'logger' +require 'pathname' +require 'open3' +require 'digest/md5' + +# BoostlookAntoraSpecimenPreview handles building the Antora specimen site and monitoring changes +class BoostlookAntoraSpecimenPreview + # Define relevant paths + PATHS = { + source_css: 'boostlook.css', + source_rb: 'boostlook.rb', + antora_dir: 'doc/antora_specimen', + build_dir: 'doc/antora_specimen/build/site', + build_css: 'doc/antora_specimen/build/site/_/css/site.css', + playbook: 'doc/antora_specimen/playbook.yml' + }.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 + @last_rb_hash = nil # Store the last Ruby file hash + @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 files exist + unless File.exist?(PATHS[:source_css]) + @logger.error("Source CSS file not found: #{PATHS[:source_css]}") + exit 1 + end + + unless File.exist?(PATHS[:source_rb]) + @logger.error("Source Ruby extension not found: #{PATHS[:source_rb]}") + 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 + else + @logger.info("Using existing build. Run with --rebuild to force a fresh build.") + end + + # Store initial file hashes + @last_css_hash = calculate_file_hash(PATHS[:source_css]) + @last_rb_hash = calculate_file_hash(PATHS[:source_rb]) + + open_in_browser + end + + # Builds the Antora site + def build_antora_site + @logger.info("Building Antora site with official Boost.URL content...") + + Dir.chdir(PATHS[:antora_dir]) do + # Use --fetch since we're pulling remote content + cmd = 'npx antora --fetch playbook.yml' + @logger.info("Fetching remote Boost.URL content and building site...") + + unless system(cmd) + @logger.error("Antora site build failed") + exit 1 + end + end + + @logger.info("Antora site built successfully with boostlook styling applied") + # Copy current boostlook.css to override the one from UI bundle + copy_current_css + true + end + + # Copy current boostlook.css to the built site + def copy_current_css + target_css = File.join(PATHS[:build_dir], '_/css/boostlook.css') + + if File.exist?(target_css) + @logger.info("Copying current #{PATHS[:source_css]} to built site...") + FileUtils.cp(PATHS[:source_css], target_css) + @logger.info("Updated built site with current boostlook.css") + else + @logger.warn("Target CSS file not found: #{target_css}") + end + end + + # Calculate MD5 hash of a file + def calculate_file_hash(file_path) + Digest::MD5.hexdigest(File.read(file_path)) + end + + # Rebuilds the entire site (useful when Ruby extension changes) + def rebuild_site + @logger.info("Rebuilding entire site due to boostlook.rb changes...") + FileUtils.rm_rf(PATHS[:build_dir]) if File.exist?(PATHS[:build_dir]) + build_antora_site + end + + # Opens the generated HTML file in the default web browser + def open_in_browser + return if @file_opened + + index_file = File.join(PATHS[:build_dir], 'index.html') + + unless File.exist?(index_file) + @logger.error("Site index not found: #{index_file}") + return + end + + cmd = OS_BROWSER_COMMANDS.find { |platform, _| RUBY_PLATFORM =~ platform }&.last + if cmd + system("#{cmd} #{index_file}") + @file_opened = true + @logger.info("Opened site in browser: #{index_file}") + else + @logger.warn("Unsupported OS. Please open #{index_file} manually") + end + end + + # Sets up file listeners to watch for changes and trigger updates + def watch_files + @logger.info("Watching for changes in boostlook files...") + + @listener = Listen.to('.', latency: 0.5, only: /\.(css|rb)$/) do |modified, added, _| + # Skip if we're already processing a change to avoid loops + next if @processing_change + + files = modified + added + + css_changed = files.any? { |file| File.basename(file) == File.basename(PATHS[:source_css]) } + rb_changed = files.any? { |file| File.basename(file) == File.basename(PATHS[:source_rb]) } + + if css_changed || rb_changed + @processing_change = true + + if rb_changed + # Ruby extension changed - need full rebuild + current_rb_hash = calculate_file_hash(PATHS[:source_rb]) + if current_rb_hash != @last_rb_hash + @logger.info("#{PATHS[:source_rb]} changed, rebuilding site...") + rebuild_site + @last_rb_hash = current_rb_hash + @last_css_hash = calculate_file_hash(PATHS[:source_css]) # Update CSS hash too + end + elsif css_changed + # CSS changed - just rebuild (CSS is processed by Ruby extension) + current_css_hash = calculate_file_hash(PATHS[:source_css]) + if current_css_hash != @last_css_hash + @logger.info("#{PATHS[:source_css]} changed, rebuilding site...") + rebuild_site + @last_css_hash = current_css_hash + end + end + + @processing_change = false + 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 Specimen Preview ===") + @logger.info("Watching boostlook.css and boostlook.rb for changes") + @logger.info("Testing against official Boost.URL documentation") + @logger.info("") + @logger.info("Changes detected will trigger automatic rebuilds:") + @logger.info(" • #{PATHS[:source_css]} → Full rebuild (CSS processed by extension)") + @logger.info(" • #{PATHS[:source_rb]} → Full rebuild (Ruby extension changed)") + @logger.info("") + @logger.info("To view the styled 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 + +# Handle command line arguments +if __FILE__ == $0 + # Check for --rebuild flag + if ARGV.include?('--rebuild') + FileUtils.rm_rf('doc/antora_specimen/build') if File.exist?('doc/antora_specimen/build') + puts "Build directory cleared. Starting fresh build..." + end + + BoostlookAntoraSpecimenPreview.new.run +end diff --git a/boostlook_preview.rb b/boostlook_asciidoc_preview.rb similarity index 100% rename from boostlook_preview.rb rename to boostlook_asciidoc_preview.rb diff --git a/doc/antora_specimen/.gitignore b/doc/antora_specimen/.gitignore new file mode 100644 index 0000000..9be64f5 --- /dev/null +++ b/doc/antora_specimen/.gitignore @@ -0,0 +1,16 @@ +doc/html +.DS_Store + +# Antora build artifacts +doc/antora_specimen/build/ +doc/antora_specimen/node_modules/ +**/build/site/ + +# Node.js and npm artifacts +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Antora cache +.cache/ diff --git a/doc/antora_specimen/playbook.yml b/doc/antora_specimen/playbook.yml new file mode 100644 index 0000000..220a78d --- /dev/null +++ b/doc/antora_specimen/playbook.yml @@ -0,0 +1,18 @@ +site: + title: Boostlook Antora Specimen + url: / + start_page: url::index.adoc + +content: + sources: + - url: https://github.com/boostorg/url.git + branches: develop + start_path: doc + +ui: + bundle: + url: https://github.com/boostorg/website-v2-docs/releases/download/ui-master/ui-bundle.zip + snapshot: true + +output: + dir: ./build/site