5 unstable releases

0.11.0 Dec 15, 2021
0.10.2 Nov 3, 2021
0.10.1 Oct 5, 2021
0.10.0 Oct 3, 2021
0.9.0 Jul 22, 2021

#279 in Procedural macros

Download history 381/week @ 2021-10-07 548/week @ 2021-10-14 863/week @ 2021-10-21 581/week @ 2021-10-28 815/week @ 2021-11-04 654/week @ 2021-11-11 888/week @ 2021-11-18 347/week @ 2021-11-25 465/week @ 2021-12-02 509/week @ 2021-12-09 340/week @ 2021-12-16 25/week @ 2021-12-23 103/week @ 2021-12-30 281/week @ 2022-01-06 226/week @ 2022-01-13 248/week @ 2022-01-20

866 downloads per month
Used in 14 crates (via doku)

MIT license

31KB
846 lines

Doku   crates-badge docs-badge

Doku is a framework for building textual, aesthetic documentation directly from the code; it allows to generate docs for configuration files, HTTP endpoints, and so on.

Say goodbye to stale, hand-written documentation - with Doku, code is the documentation!

Example

[dependencies]
doku = "0.11"
use doku::Document;
use serde::Deserialize;

#[derive(Deserialize, Document)]
struct Config {
    /// Database's engine
    db_engine: DbEngine,

    /// Database's host
    #[doku(example = "localhost")]
    db_host: String,

    /// Database's port
    #[doku(example = "5432")]
    db_port: usize,
}

#[derive(Deserialize, Document)]
enum DbEngine {
    #[serde(rename = "pgsql")]
    PostgreSQL,

    #[serde(rename = "mysql")]
    MySQL,
}

fn main() {
    println!("{}", doku::to_json::<Config>());
}
{
  // Database's engine
  "db_engine": "pgsql" | "mysql",
  // Database's host
  "db_host": "localhost",
  // Database's port
  "db_port": 5432
}

You'll find more examples in ./doku/examples; there's also a documentation at https://docs.rs/doku/.

Contributing

Found a bug, have an idea? Please let us know on GitHub - patches are welcome, too!

If you want to try hacking on Doku, the entry points are:

As for the end-to-end tests, you'll find them inside ./doku/tests.

The way those tests work is that each test-directory contains an input file called input.rs and a set of output files called output.<something>.json.

The input.rs contains a Rust code defining a type called Ty - which can be an enum, a struct, whatever is required for the test - and a top-level comment that specifies which testing-function you want to execute on that type - e.g.:

// run: to_json()

#[derive(Document)]
pub struct Ty {
    foo: Vec<String>,
}

Our procedural macro then finds all of those input.rs-s, reads their // run:, and generates tests resembling:

#[test]
fn test() {
    mod source {
        include!("./path/to/that/input.rs");
    }
    
    to_json::<source::Ty>(/* ... */);
}

That to_json(), and rest of the testing-functions, generate a documentation for Ty and compare the actual input (as generated from the code) to the expected one (as present inside output.<something>.json) - when there's a mismatch, the test fails:

thread '...' panicked at '
Found differences between `...` and `...`:
...

When a test fails, you'll see that next to the output.<something>.json file, there appears a new one, called output.<something>.json.new; this *.new file will contain the test's actual result, and it's up to you to decide if this actual result is the correct one.

If the *.new file looks fine, you can either:

  • manually delete output.<something>.json and then rename output.<something>.json.new to output.<something>.json,

  • or, if you have make and fd installed, you can execute make bless - this will automatically fix all of the tests.

Happy hacking!

License

Licensed under the MIT license.

Dependencies

~0.6–1MB
~23K SLoC