cargo_wiki/
lib.rs

1// Uncomment it when you are generating doc with feature `doc_examples`
2// #![feature(more_maybe_bounds)]
3
4use crate::wiki::generator::generate_wiki;
5use crate::wiki::CrateExt;
6use anyhow::Result;
7use clap::{Parser, ValueEnum};
8use rustdoc_types::Crate;
9use std::env::current_dir;
10use std::fs;
11use std::fs::create_dir_all;
12use std::path::Path;
13
14#[cfg(feature = "doc_examples")]
15pub mod _examples;
16pub mod generators;
17pub mod rust_doc;
18pub mod wiki;
19
20#[derive(Parser, Debug)]
21#[command(name = "cargo wiki")]
22pub struct Configuration {
23    /// The package to document. See [cargo-pkgid](https://doc.rust-lang.org/cargo/commands/cargo-pkgid.html)
24    /// for the SPEC format.
25    #[arg(short, long, default_value_t = String::new())]
26    pub package: String,
27    #[arg(long, default_value_t = false)]
28    pub workspace: bool,
29    /// Space or comma separated list of features to activate. Features of workspace members may be
30    /// enabled with package-name/feature-name syntax. This flag may be specified multiple times,
31    /// which enables all specified features.
32    #[arg(short, long, default_value_t = String::new())]
33    pub features: String,
34    /// Activate all available features of all selected packages.
35    #[arg(long, default_value_t = false)]
36    pub all_features: bool,
37    /// Do not activate the default feature of the selected packages.
38    #[arg(long, default_value_t = false)]
39    pub no_default_features: bool,
40    #[arg(long, default_value_t = false)]
41    pub document_private_items: bool,
42    #[arg(long, default_value_t = false)]
43    pub no_deps: bool,
44    #[arg(short, long, value_enum, default_value_t = MarkdownFlavor::GitHub)]
45    pub markdown_flavor: MarkdownFlavor,
46    // TODO: Add more arguments to support more features
47    // refer: https://doc.rust-lang.org/cargo/commands/cargo-doc.html
48    // refer: https://doc.rust-lang.org/cargo/commands/cargo-rustdoc.html
49}
50
51/// Markdown Flavor to be used
52#[derive(Debug, ValueEnum, Clone)]
53pub enum MarkdownFlavor {
54    /// GitHub Markdown Flavor
55    GitHub,
56    /// GitLab Markdown Flavor
57    GitLab,
58    // TODO: Add support for other markdown flavors
59}
60
61pub const WIKI_OUTPUT_PATH: &str = "target/wiki";
62pub const WIKI_CACHE_PATH: &str = "target/wiki_cache";
63
64pub fn gen_path(path: &str) -> Result<()> {
65    let wiki_output_path =
66        Path::new(&current_dir().expect(
67            "Failed to get the current directory where the `cargo wiki` command is running.",
68        ))
69        .join(path);
70
71    if !wiki_output_path.exists() {
72        create_dir_all(wiki_output_path)?
73    }
74    Ok(())
75}
76
77pub const RUSTDOC_OUTPUT: &str = "target/doc";
78
79pub fn generate_doc_for_entire_dir(configuration: Configuration) -> Result<()> {
80    let rustdoc_path =
81        Path::new(&current_dir().expect(
82            "Failed to get the current directory where the `cargo wiki` command is running.",
83        ))
84        .join(RUSTDOC_OUTPUT);
85
86    let dir_iterator = fs::read_dir(&rustdoc_path).map_err(|_| {
87        anyhow::Error::msg(format!("Failed to read contents of '{:?}'", &rustdoc_path))
88    })?;
89
90    for entry in dir_iterator {
91        let entry = entry?;
92        let file_type = entry.file_type();
93
94        if let Ok(file_type) = file_type {
95            if file_type.is_file() && entry.path().extension() == Some("json".as_ref()) {
96                let crate_type = Crate::from_file(&entry.path())?;
97                generate_wiki(&configuration, crate_type)?;
98            }
99        } else {
100            eprintln!("Failed to know the type of {:?}", entry.path());
101        }
102    }
103
104    Ok(())
105}