mirror of
https://github.com/boostorg/boostlook.git
synced 2026-01-19 04:02:14 +00:00
feat: add asciidoc live preview (#27)
- add live preview functionality for local doc development - document setup prerequisites and usage in README - include basic troubleshooting guide - run pre-commit on all files
This commit is contained in:
committed by
Julio C. Estrada
parent
0d189f8dba
commit
8e0507c040
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,4 +1,3 @@
|
|||||||
* text=auto
|
* text=auto
|
||||||
|
|
||||||
*.css text eol=lf
|
*.css text eol=lf
|
||||||
|
|
||||||
|
|||||||
94
README.md
94
README.md
@@ -15,3 +15,97 @@ html mp11.html : mp11.adoc
|
|||||||
Noto font files are covered under the Open Font License:
|
Noto font files are covered under the Open Font License:
|
||||||
|
|
||||||
https://fonts.google.com/noto/use
|
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.
|
||||||
|
|
||||||
|
7. **Refresh Your Browser** to view changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
- **Script Not Running**:
|
||||||
|
- Ensure all prerequisites are installed correctly.
|
||||||
|
- Check for any error messages in the terminal and resolve them accordingly.
|
||||||
|
|
||||||
|
- **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.
|
||||||
|
|
||||||
|
- **Boost.Build (b2) Not Found**:
|
||||||
|
- Ensure `b2` is installed and available in your system's PATH.
|
||||||
|
- Run `which b2` to verify its availability.
|
||||||
|
|||||||
163
boostlook_preview.rb
Executable file
163
boostlook_preview.rb
Executable file
@@ -0,0 +1,163 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'asciidoctor'
|
||||||
|
require 'listen'
|
||||||
|
require 'pathname'
|
||||||
|
require 'logger'
|
||||||
|
|
||||||
|
# AsciidocRenderer handles building AsciiDoc files, monitoring changes, and rendering the output in a browser.
|
||||||
|
class AsciidocRenderer
|
||||||
|
# Define our relevant constant paths
|
||||||
|
PATHS = {
|
||||||
|
jamfile: 'doc/Jamfile',
|
||||||
|
specimen_docinfo_footer: 'doc/specimen-docinfo-footer.html',
|
||||||
|
specimen_adoc: 'doc/specimen.adoc',
|
||||||
|
css: 'boostlook.css',
|
||||||
|
boostlook_rb: 'boostlook.rb',
|
||||||
|
output_dir: 'doc/html'
|
||||||
|
}.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
|
||||||
|
validate_b2 # Ensure Boost.Build is installed
|
||||||
|
end
|
||||||
|
|
||||||
|
# Entry point to run the renderer
|
||||||
|
def run
|
||||||
|
validate_files # Check for the presence of required files
|
||||||
|
initial_build # Perform the initial build and render
|
||||||
|
setup_signal_traps # Setup signal handlers for graceful shutdown
|
||||||
|
watch_files # Start watching for file changes
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Validates that all required files are present
|
||||||
|
def validate_files
|
||||||
|
required_files = [PATHS[:jamfile], PATHS[:specimen_docinfo_footer], PATHS[:specimen_adoc], PATHS[:css], PATHS[:boostlook_rb]]
|
||||||
|
missing_files = required_files.reject { |file| File.exist?(file) }
|
||||||
|
unless missing_files.empty?
|
||||||
|
missing_files.each { |file| @logger.error("Required file #{file} not found") }
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Checks if the 'b2' command (Boost.Build) is available
|
||||||
|
def validate_b2
|
||||||
|
unless system('which b2 > /dev/null 2>&1')
|
||||||
|
@logger.error("'b2' command not found. Please install Boost.Build and ensure it's in your PATH.")
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds the AsciiDoc project using Boost.Build
|
||||||
|
def build_asciidoc
|
||||||
|
Dir.chdir('doc') do
|
||||||
|
if system('b2')
|
||||||
|
@logger.info("Build successful")
|
||||||
|
true
|
||||||
|
else
|
||||||
|
@logger.error("Build failed")
|
||||||
|
false
|
||||||
|
end
|
||||||
|
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[:output_dir]}/specimen.html")
|
||||||
|
@file_opened = true
|
||||||
|
else
|
||||||
|
@logger.warn("Unsupported OS. Please open #{PATHS[:output_dir]}/specimen.html manually")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Performs the initial build and opens the result in the browser
|
||||||
|
def initial_build
|
||||||
|
if build_asciidoc && File.exist?("#{PATHS[:output_dir]}/specimen.html")
|
||||||
|
open_in_browser
|
||||||
|
@logger.info("Rendered #{PATHS[:specimen_adoc]} to #{PATHS[:output_dir]}/specimen.html")
|
||||||
|
else
|
||||||
|
@logger.error("Failed to generate #{PATHS[:output_dir]}/specimen.html")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sets up file listeners to watch for changes and trigger rebuilds
|
||||||
|
def watch_files
|
||||||
|
@listener = Listen.to('doc', '.') do |modified, added, removed|
|
||||||
|
handle_file_changes(modified, added, removed)
|
||||||
|
end
|
||||||
|
|
||||||
|
@listener.ignore(/doc\/html/) # Ignore changes in the output directory
|
||||||
|
@listener.start
|
||||||
|
@logger.info("Watching for changes in 'doc' and root directories (excluding 'doc/html')...")
|
||||||
|
|
||||||
|
# Keep the script running until a shutdown is requested
|
||||||
|
until @shutdown_requested
|
||||||
|
sleep 1
|
||||||
|
end
|
||||||
|
|
||||||
|
shutdown # Perform shutdown procedures
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handles detected file changes by determining if a rebuild is necessary
|
||||||
|
def handle_file_changes(modified, added, removed)
|
||||||
|
@logger.debug("Modified files: #{modified.join(', ')}")
|
||||||
|
@logger.debug("Added files: #{added.join(', ')}") if added.any?
|
||||||
|
@logger.debug("Removed files: #{removed.join(', ')}") if removed.any?
|
||||||
|
|
||||||
|
relevant_files = [
|
||||||
|
File.expand_path(PATHS[:jamfile]),
|
||||||
|
File.expand_path(PATHS[:specimen_docinfo_footer]),
|
||||||
|
File.expand_path(PATHS[:specimen_adoc]),
|
||||||
|
File.expand_path(PATHS[:css]),
|
||||||
|
File.expand_path(PATHS[:boostlook_rb])
|
||||||
|
]
|
||||||
|
|
||||||
|
# Check if any of the changed files are relevant for rebuilding
|
||||||
|
changes_relevant = (modified + added + removed).any? do |file|
|
||||||
|
relevant_files.include?(File.expand_path(file))
|
||||||
|
end
|
||||||
|
|
||||||
|
if changes_relevant
|
||||||
|
@logger.info("Relevant changes detected, rebuilding...")
|
||||||
|
if build_asciidoc && File.exist?("#{PATHS[:output_dir]}/specimen.html")
|
||||||
|
open_in_browser
|
||||||
|
@logger.info("Re-rendered successfully")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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 if @listener
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Instantiate and run the AsciidocRenderer
|
||||||
|
AsciidocRenderer.new.run
|
||||||
@@ -438,7 +438,7 @@ See <<chars_format overview>> for description.
|
|||||||
[#integral_usage_notes_]
|
[#integral_usage_notes_]
|
||||||
* All built-in integral types are allowed except bool which is deleted
|
* All built-in integral types are allowed except bool which is deleted
|
||||||
* from_chars for integral type is constexpr (BOOST_CHARCONV_CONSTEXPR is defined) when:
|
* from_chars for integral type is constexpr (BOOST_CHARCONV_CONSTEXPR is defined) when:
|
||||||
** compiled using `-std=c++14` or newer
|
** compiled using `-std=c++14` or newer
|
||||||
** using a compiler with `\__builtin_ is_constant_evaluated`
|
** using a compiler with `\__builtin_ is_constant_evaluated`
|
||||||
* These functions have been tested to support `\__int128` and `unsigned __int128`
|
* These functions have been tested to support `\__int128` and `unsigned __int128`
|
||||||
|
|
||||||
@@ -993,4 +993,3 @@ This documentation is copyright 2022-2023 Peter Dimov and Matt Borland and is di
|
|||||||
the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].
|
the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].
|
||||||
|
|
||||||
:leveloffset: -1
|
:leveloffset: -1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user