| // Licensed under the Apache-2.0 license |
| |
| use std::{ |
| env, |
| path::{Path, PathBuf}, |
| process::{Command, Stdio}, |
| }; |
| |
| use xshell::{cmd, Shell}; |
| |
| type DynError = Box<dyn std::error::Error>; |
| |
| pub(crate) fn docs() -> Result<(), DynError> { |
| check_mdbook()?; |
| check_mermaid()?; |
| |
| println!("Running: mdbook"); |
| let sh = Shell::new()?; |
| let project_root = project_root(); |
| let docs_dir = project_root.join("docs"); |
| let dest_dir = project_root.join("target/book"); |
| |
| // Create docs directory if it doesn't exist |
| if !docs_dir.exists() { |
| create_default_docs_structure(&docs_dir)?; |
| } |
| |
| sh.change_dir(&docs_dir); |
| cmd!(sh, "mdbook build --dest-dir {dest_dir}").run()?; |
| |
| println!( |
| "Docs built successfully: view at {}/index.html", |
| dest_dir.display() |
| ); |
| |
| Ok(()) |
| } |
| |
| fn check_mdbook() -> Result<(), DynError> { |
| let status = Command::new("mdbook") |
| .args(["--help"]) |
| .stdout(Stdio::null()) |
| .stderr(Stdio::null()) |
| .status(); |
| |
| if status.is_ok() { |
| return Ok(()); |
| } |
| |
| println!("mdbook not found; installing..."); |
| let sh = Shell::new()?; |
| cmd!(sh, "cargo install mdbook").run()?; |
| |
| Ok(()) |
| } |
| |
| fn check_mermaid() -> Result<(), DynError> { |
| let status = Command::new("mdbook-mermaid") |
| .args(["--help"]) |
| .stdout(Stdio::null()) |
| .stderr(Stdio::null()) |
| .status(); |
| |
| if status.is_ok() { |
| return Ok(()); |
| } |
| |
| println!("mdbook-mermaid not found; installing..."); |
| let sh = Shell::new()?; |
| cmd!(sh, "cargo install mdbook-mermaid").run()?; |
| |
| Ok(()) |
| } |
| |
| fn create_default_docs_structure(docs_dir: &Path) -> Result<(), DynError> { |
| let sh = Shell::new()?; |
| sh.create_dir(docs_dir)?; |
| |
| // Create book.toml |
| let book_toml = docs_dir.join("book.toml"); |
| sh.write_file( |
| &book_toml, |
| r#"[book] |
| authors = ["OpenProt Team"] |
| language = "en" |
| multilingual = false |
| src = "src" |
| title = "OpenProt Documentation" |
| |
| [preprocessor.mermaid] |
| command = "mdbook-mermaid" |
| |
| [output.html] |
| "#, |
| )?; |
| |
| // Create src directory and SUMMARY.md |
| let src_dir = docs_dir.join("src"); |
| sh.create_dir(&src_dir)?; |
| |
| let summary_md = src_dir.join("SUMMARY.md"); |
| sh.write_file( |
| &summary_md, |
| r#"# Summary |
| |
| [Introduction](./introduction.md) |
| |
| # User Guide |
| |
| - [Getting Started](./getting-started.md) |
| - [Usage](./usage.md) |
| |
| # Developer Guide |
| |
| - [Architecture](./architecture.md) |
| - [Contributing](./contributing.md) |
| "#, |
| )?; |
| |
| // Create introduction.md |
| let intro_md = src_dir.join("introduction.md"); |
| sh.write_file(&intro_md, r#"# Introduction |
| |
| Welcome to the OpenProt documentation! |
| |
| This documentation provides comprehensive information about the OpenProt project, including user guides, developer documentation, and API references. |
| |
| ## What is OpenProt? |
| |
| OpenProt is a Rust-based project that provides... |
| |
| ## Quick Start |
| |
| To get started with OpenProt: |
| |
| ```bash |
| cargo xtask build |
| cargo xtask test |
| ``` |
| |
| For more detailed instructions, see the [Getting Started](./getting-started.md) guide. |
| "#)?; |
| |
| // Create getting-started.md |
| let getting_started_md = src_dir.join("getting-started.md"); |
| sh.write_file( |
| &getting_started_md, |
| r#"# Getting Started |
| |
| ## Prerequisites |
| |
| - Rust 1.70 or later |
| - Cargo |
| |
| ## Installation |
| |
| Clone the repository: |
| |
| ```bash |
| git clone <repository-url> |
| cd openprot |
| ``` |
| |
| Build the project: |
| |
| ```bash |
| cargo xtask build |
| ``` |
| |
| Run tests: |
| |
| ```bash |
| cargo xtask test |
| ``` |
| |
| ## Next Steps |
| |
| - Read the [Usage](./usage.md) guide |
| - Check out the [Architecture](./architecture.md) documentation |
| - Learn about [Contributing](./contributing.md) |
| "#, |
| )?; |
| |
| // Create usage.md |
| let usage_md = src_dir.join("usage.md"); |
| sh.write_file( |
| &usage_md, |
| r#"# Usage |
| |
| ## Available Commands |
| |
| The project uses xtask for automation. Here are the available commands: |
| |
| ### Build Commands |
| |
| ```bash |
| cargo xtask build # Build the project |
| cargo xtask check # Run cargo check |
| cargo xtask clippy # Run clippy lints |
| ``` |
| |
| ### Test Commands |
| |
| ```bash |
| cargo xtask test # Run all tests |
| ``` |
| |
| ### Formatting Commands |
| |
| ```bash |
| cargo xtask fmt # Format code |
| cargo xtask fmt --check # Check formatting |
| ``` |
| |
| ### Distribution Commands |
| |
| ```bash |
| cargo xtask dist # Create distribution |
| ``` |
| |
| ### Documentation Commands |
| |
| ```bash |
| cargo xtask docs # Build documentation |
| ``` |
| |
| ### Utility Commands |
| |
| ```bash |
| cargo xtask clean # Clean build artifacts |
| cargo xtask cargo-lock # Manage Cargo.lock |
| ``` |
| "#, |
| )?; |
| |
| // Create architecture.md |
| let arch_md = src_dir.join("architecture.md"); |
| sh.write_file( |
| &arch_md, |
| r#"# Architecture |
| |
| ## Project Structure |
| |
| ``` |
| openprot/ |
| ├── openprot/ # Main application |
| │ ├── src/ |
| │ │ ├── lib.rs # Library code |
| │ │ └── main.rs # Binary entry point |
| │ └── Cargo.toml |
| ├── xtask/ # Build automation |
| │ ├── src/ |
| │ │ ├── main.rs # Task runner |
| │ │ ├── cargo_lock.rs # Cargo.lock management |
| │ │ └── docs.rs # Documentation generation |
| │ └── Cargo.toml |
| ├── docs/ # Documentation source |
| ├── .cargo/ # Cargo configuration |
| └── Cargo.toml # Workspace configuration |
| ``` |
| |
| ## Components |
| |
| ### Main Application (`openprot/`) |
| |
| The main application provides... |
| |
| ### Build System (`xtask/`) |
| |
| The xtask system provides automated build tasks including: |
| |
| - Building and testing |
| - Code formatting and linting |
| - Distribution creation |
| - Documentation generation |
| - Dependency management |
| |
| ### Documentation (`docs/`) |
| |
| Documentation is built using mdbook and includes: |
| |
| - User guides |
| - Developer documentation |
| - API references |
| - Architecture documentation |
| "#, |
| )?; |
| |
| // Create contributing.md |
| let contrib_md = src_dir.join("contributing.md"); |
| sh.write_file( |
| &contrib_md, |
| r#"# Contributing |
| |
| ## Development Setup |
| |
| 1. Clone the repository |
| 2. Install dependencies: `cargo xtask check` |
| 3. Run tests: `cargo xtask test` |
| 4. Format code: `cargo xtask fmt` |
| |
| ## Code Style |
| |
| - Use `cargo xtask fmt` to format code |
| - Run `cargo xtask clippy` to check for lints |
| - Ensure all tests pass with `cargo xtask test` |
| |
| ## Documentation |
| |
| - Update documentation in the `docs/` directory |
| - Build docs with `cargo xtask docs` |
| - Documentation is built with mdbook |
| |
| ## Pull Requests |
| |
| 1. Fork the repository |
| 2. Create a feature branch |
| 3. Make your changes |
| 4. Run the full test suite |
| 5. Submit a pull request |
| |
| ## Issues |
| |
| Please report issues on the GitHub issue tracker. |
| "#, |
| )?; |
| |
| println!( |
| "Created default documentation structure in {}", |
| docs_dir.display() |
| ); |
| Ok(()) |
| } |
| |
| fn project_root() -> PathBuf { |
| Path::new(&env!("CARGO_MANIFEST_DIR")) |
| .ancestors() |
| .nth(1) |
| .map(|p| p.to_path_buf()) |
| .unwrap_or_else(|| PathBuf::from(".")) |
| } |