diff --git a/README.md b/README.md index 74dc960..0df058c 100644 --- a/README.md +++ b/README.md @@ -73,19 +73,29 @@ mod my_module { // where the documentation will be generated. let docs_path = std::env::var("DOCS_DIR").unwrap_or("target/docs".to_string()); -let mut engine = rhai::Engine::new(); - -// We register the module defined in the previous code block for this example, +// Create a new engine and register all modules that need to have documentation generated for them. +// In this example, the module defined in the previous code block is registered into the engine, // but you could register other functions and types ... +let mut engine = rhai::Engine::new(); engine.register_static_module("my_module", exported_module!(my_module).into()); -let docs = rhai_autodocs::options() +/// Export the documentation as a [`ModuleDocumentation`]. You could stop here and generate +/// you own docs from this structure. +let docs = rhai_autodocs::export::options() .include_standard_packages(false) - .generate(&engine) + .export(&engine) .expect("failed to generate documentation"); -// Write the documentation in a file, or output to stdout, etc. -for (name, docs) in rhai_autodocs::generate_for_docusaurus(&docs).expect("failed to generate mdx for docusaurus") { +/// Or you could use pre-defined templates for docusaurus or mdbook. +/// Here, documentation is generated for docusaurus with some options. +let mdx = rhai_autodocs::generate::docusaurus() + .with_slug("/docs/api") + .build(&docs) + .expect("failed to generate mdx for docusaurus"); + +/// Iterate over the generated documentation for every modules. +for (name, docs) in mdx { + // Write the documentation in a file, or output to stdout, or anything really. println!("docs for module {name}"); println!("{docs}"); } diff --git a/examples/basic/main.rs b/examples/basic/main.rs index 08857b8..ccfc7b5 100644 --- a/examples/basic/main.rs +++ b/examples/basic/main.rs @@ -46,10 +46,10 @@ fn main() { let path = "./my-module.md"; // register custom functions and types ... - let docs = rhai_autodocs::module::options::options() + let docs = rhai_autodocs::export::options() .include_standard_packages(false) .order_items_with(rhai_autodocs::module::options::ItemsOrder::ByIndex) - .generate(&engine) + .export(&engine) .expect("failed to generate documentation"); // Write the documentation in a file. diff --git a/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/global.mdx b/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/global.mdx index b8436c8..583bf65 100644 --- a/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/global.mdx +++ b/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/global.mdx @@ -1,6 +1,6 @@ --- title: global -slug: /global +slug: /docs/api/global --- import Tabs from '@theme/Tabs'; diff --git a/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/my_module.mdx b/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/my_module.mdx index 012f551..e079e1d 100644 --- a/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/my_module.mdx +++ b/examples/docusaurus/docusaurus-example/docs/rhai-autodocs/my_module.mdx @@ -1,6 +1,6 @@ --- title: my_module -slug: /my_module +slug: /docs/api/my_module --- import Tabs from '@theme/Tabs'; diff --git a/examples/docusaurus/main.rs b/examples/docusaurus/main.rs index 1ee63b4..dd885a0 100644 --- a/examples/docusaurus/main.rs +++ b/examples/docusaurus/main.rs @@ -1,5 +1,4 @@ use rhai::plugin::*; -use rhai_autodocs::generate_for_docusaurus; /// My own module. #[export_module] @@ -152,17 +151,21 @@ fn main() { engine.build_type::(); // Generate documentation structure. - let docs = rhai_autodocs::module::options() + let docs = rhai_autodocs::export::options() .include_standard_packages(false) .order_items_with(rhai_autodocs::module::options::ItemsOrder::ByIndex) .format_sections_with(rhai_autodocs::module::options::SectionFormat::Tabs) - .generate(&engine) + .export(&engine) .expect("failed to generate documentation"); let path = "./examples/docusaurus/docusaurus-example/docs/rhai-autodocs"; // Write the documentation in files for docusaurus. - for (name, doc) in generate_for_docusaurus(&docs).unwrap() { + for (name, doc) in rhai_autodocs::generate::docusaurus() + .with_slug("/docs/api") + .build(&docs) + .unwrap() + { std::fs::write( std::path::PathBuf::from_iter([path, &format!("{}.mdx", &name)]), doc, diff --git a/examples/mdbook/main.rs b/examples/mdbook/main.rs index 7e7048e..0e1677f 100644 --- a/examples/mdbook/main.rs +++ b/examples/mdbook/main.rs @@ -1,5 +1,4 @@ use rhai::plugin::*; -use rhai_autodocs::generate_for_mdbook; /// My own module. #[export_module] @@ -52,17 +51,17 @@ fn main() { engine.register_static_module("my_module", exported_module!(my_module).into()); // register custom functions and types ... - let docs = rhai_autodocs::module::options() + let docs = rhai_autodocs::export::options() .include_standard_packages(false) .order_items_with(rhai_autodocs::module::options::ItemsOrder::ByIndex) .format_sections_with(rhai_autodocs::module::options::SectionFormat::Tabs) - .generate(&engine) + .export(&engine) .expect("failed to generate documentation"); let path = "./examples/mdbook/mdbook-example/src"; // Write the documentation in files. - for (name, doc) in generate_for_mdbook(&docs).unwrap() { + for (name, doc) in rhai_autodocs::generate::mdbook().build(&docs).unwrap() { std::fs::write( std::path::PathBuf::from_iter([path, &format!("{}.md", &name)]), doc, diff --git a/examples/mdbook/mdbook-example/src/my_module.md b/examples/mdbook/mdbook-example/src/my_module.md index 9629ec0..aae34cb 100644 --- a/examples/mdbook/mdbook-example/src/my_module.md +++ b/examples/mdbook/mdbook-example/src/my_module.md @@ -2,7 +2,7 @@ ```Namespace: global/my_module``` -
+

fn hello_world

```rust,ignore @@ -10,8 +10,6 @@ fn hello_world(message: String) ``` - -
@@ -33,15 +31,13 @@

-
+

fn add

```rust,ignore fn add(a: int, b: int) -> int ``` - -
diff --git a/src/handlebars/docusaurus/header.hbs b/src/handlebars/docusaurus/header.hbs index f6492d2..bc8f220 100644 --- a/src/handlebars/docusaurus/header.hbs +++ b/src/handlebars/docusaurus/header.hbs @@ -1,6 +1,6 @@ --- title: {{title}} -slug: /{{slug}} +slug: {{slug}} --- import Tabs from '@theme/Tabs'; diff --git a/src/lib.rs b/src/lib.rs index d3ec895..17ce9aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,66 +8,110 @@ pub mod module; pub use glossary::ModuleGlossary; pub use module::{ - options::{options, ItemsOrder, MarkdownProcessor, SectionFormat}, + options::{export, ItemsOrder, MarkdownProcessor, SectionFormat}, ModuleDocumentation, }; use serde_json::json; -/// Generate documentation for the docusaurus markdown processor. -/// -/// Returns a hashmap with the name of the module as the key and its raw documentation as the value. -pub fn generate_for_docusaurus( - module: &ModuleDocumentation, -) -> Result, handlebars::RenderError> { - let mut hbs_registry = handlebars::Handlebars::new(); +#[derive(Default)] +pub struct DocusaurusOptions { + pub(crate) slug: Option, +} + +impl DocusaurusOptions { + /// Format the slug in the metadata section of the generated MDX document by concatenating the `slug` parameter with the module name. + /// + /// For example, if the documentation for a module called `my_module` is generated with + /// the slug `/docs/api/`, the slug set in the document will be `/docs/api/my_module`. + /// + /// By default the root `/` path is used. + pub fn with_slug(mut self, slug: &str) -> Self { + self.slug = Some(slug.to_string()); + + self + } + + /// Build MDX documentation for docusaurus from the given module documentation struct. + /// + /// Returns a hashmap with the name of the module as the key and its raw documentation as the value. + pub fn build( + self, + module: &ModuleDocumentation, + ) -> Result, handlebars::RenderError> { + let mut hbs_registry = handlebars::Handlebars::new(); + + hbs_registry + .register_template_string( + "docusaurus-module", + include_str!("handlebars/docusaurus/header.hbs"), + ) + .expect("template is valid"); - hbs_registry - .register_template_string( + // A partial used to keep indentation for mdx to render correctly. + hbs_registry + .register_partial("ContentPartial", "{{{content}}}") + .expect("partial is valid"); + + generate( + module, "docusaurus-module", - include_str!("handlebars/docusaurus/header.hbs"), + self.slug.as_deref(), + &hbs_registry, ) - .expect("template is valid"); + } +} - // A partial used to keep indentation for mdx to render correctly. - hbs_registry - .register_partial("ContentPartial", "{{{content}}}") - .expect("partial is valid"); +#[derive(Default)] +pub struct MDBookOptions; - generate(module, "docusaurus-module", &hbs_registry) -} +impl MDBookOptions { + /// Build html documentation for mdbook from the given module documentation struct. + /// + /// Returns a hashmap with the name of the module as the key and its raw documentation as the value. + pub fn build( + self, + module: &ModuleDocumentation, + ) -> Result, handlebars::RenderError> { + let mut hbs_registry = handlebars::Handlebars::new(); -/// Generate documentation for the mdbook markdown processor. -/// -/// Returns a hashmap with the name of the module as the key and its raw documentation as the value. -pub fn generate_for_mdbook( - module: &ModuleDocumentation, -) -> Result, handlebars::RenderError> { - let mut hbs_registry = handlebars::Handlebars::new(); + hbs_registry + .register_template_string( + "mdbook-module", + include_str!("handlebars/mdbook/header.hbs"), + ) + .expect("template is valid"); - hbs_registry - .register_template_string( - "mdbook-module", - include_str!("handlebars/mdbook/header.hbs"), - ) - .expect("template is valid"); + // A partial used to keep indentation for md to render correctly. + hbs_registry + .register_partial("ContentPartial", "{{{content}}}") + .expect("partial is valid"); - // A partial used to keep indentation for md to render correctly. - hbs_registry - .register_partial("ContentPartial", "{{{content}}}") - .expect("partial is valid"); + generate(module, "mdbook-module", None, &hbs_registry) + } +} - generate(module, "mdbook-module", &hbs_registry) +pub mod generate { + /// Create a new builder to generate documentation for docusaurus from a [`ModuleDocumentation`] object. + pub fn docusaurus() -> super::DocusaurusOptions { + super::DocusaurusOptions::default() + } + + /// Create a new builder to generate documentation for mdbook from a [`ModuleDocumentation`] object. + pub fn mdbook() -> super::MDBookOptions { + super::MDBookOptions::default() + } } fn generate( module: &ModuleDocumentation, template: &str, + slug: Option<&str>, hbs_registry: &handlebars::Handlebars, ) -> Result, handlebars::RenderError> { let mut documentation = std::collections::HashMap::default(); let data = json!({ "title": module.name, - "slug": module.name, + "slug": slug.map_or(format!("/{}", module.name), |slug| format!("{}/{}", slug, module.name)), "description": module.documentation, "namespace": module.namespace, "items": module.items, @@ -79,7 +123,7 @@ fn generate( ); for sub in &module.sub_modules { - documentation.extend(generate(sub, template, hbs_registry)?); + documentation.extend(generate(sub, template, slug, hbs_registry)?); } Ok(documentation) diff --git a/src/module.rs b/src/module.rs index c86b381..ab2c7e3 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,8 +1,6 @@ pub mod error; pub mod options; -pub use self::options::options; - use self::{error::AutodocsError, options::Options}; use crate::custom_types::CustomTypesMetadata; use crate::doc_item::DocItem; @@ -47,7 +45,7 @@ pub(crate) struct ModuleMetadata { /// # Errors /// * Failed to generate function metadata as json. /// * Failed to parse module metadata. -pub fn generate_module_documentation( +pub(crate) fn generate_module_documentation( engine: &rhai::Engine, options: &Options, ) -> Result { @@ -145,9 +143,8 @@ pub(crate) fn group_functions( #[cfg(test)] mod test { - use crate::{generate_for_docusaurus, module::options::ItemsOrder}; + use crate::{export, generate, module::options::ItemsOrder}; - use super::*; use rhai::plugin::*; /// My own module. @@ -180,16 +177,17 @@ mod test { fn test_order_by_index() { let mut engine = rhai::Engine::new(); + // register custom functions and types ... engine.register_static_module("my_module", rhai::exported_module!(my_module).into()); - // register custom functions and types ... - let docs = options::options() + // export documentation with option. + let docs = export::options() .include_standard_packages(false) .order_items_with(ItemsOrder::ByIndex) - .generate(&engine) + .export(&engine) .expect("failed to generate documentation"); - let docs = generate_for_docusaurus(&docs).unwrap(); + let docs = generate::docusaurus().build(&docs).unwrap(); pretty_assertions::assert_eq!( docs.get("global") diff --git a/src/module/options.rs b/src/module/options.rs index 9962bbf..f7a7bd3 100644 --- a/src/module/options.rs +++ b/src/module/options.rs @@ -26,9 +26,11 @@ pub struct Options { pub(crate) include_standard_packages: bool, } -/// Create new options used to configure docs generation. -pub fn options() -> Options { - Options::default() +pub mod export { + /// Create new options used to configure docs generation. + pub fn options() -> super::Options { + super::Options::default() + } } impl Options { @@ -66,7 +68,7 @@ impl Options { /// # Errors /// * Failed to generate function metadata as json. /// * Failed to parse module metadata. - pub fn generate(self, engine: &rhai::Engine) -> Result { + pub fn export(self, engine: &rhai::Engine) -> Result { generate_module_documentation(engine, &self) } @@ -79,7 +81,7 @@ impl Options { /// # Errors /// * Failed to generate function metadata as json. /// * Failed to parse module metadata. - pub fn generate_with_glossary( + pub fn export_with_glossary( &self, engine: &rhai::Engine, ) -> Result<(ModuleDocumentation, ModuleGlossary), AutodocsError> {