[![Build Status](https://github.com/orium/cargo-rdme/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/orium/cargo-rdme/actions/workflows/ci.yml?query=branch%3Amain)
[![Code Coverage](https://codecov.io/gh/orium/cargo-rdme/branch/main/graph/badge.svg)](https://codecov.io/gh/orium/cargo-rdme)
[![Dependency status](https://deps.rs/repo/github/orium/cargo-rdme/status.svg)](https://deps.rs/repo/github/orium/cargo-rdme)
[![crates.io](https://img.shields.io/crates/v/cargo-rdme.svg)](https://crates.io/crates/cargo-rdme)
[![Downloads crates.io](https://img.shields.io/crates/d/cargo-rdme.svg?label=crates.io%20downloads)](https://crates.io/crates/cargo-rdme)
[![Downloads github](https://img.shields.io/github/downloads/orium/cargo-rdme/total.svg?label=github%20downloads)](https://github.com/orium/cargo-rdme/releases)
[![Github stars](https://img.shields.io/github/stars/orium/cargo-rdme?style=flat&logo=github)](https://github.com/orium/cargo-rdme/stargazers)
[![License](https://img.shields.io/crates/l/cargo-rdme.svg)](./LICENSE.md)

# Cargo rdme

<!-- cargo-rdme start -->

Cargo command to create your README from your crate’s documentation.

## Installation

You can install cargo rdme with cargo by running `cargo install cargo-rdme`.

Cargo rdme uses rustdoc to resolve [intralinks](#intralinks), which requires a specific
nightly rust toolchain (pinned by cargo rdme).
Install it with `cargo rdme install-rust-toolchain-for-intralinks`.

## Usage

Cargo rdme will insert your crate’s documentation in your README file. To control where the
documentation will be inserted you need to insert a marker: `<!-- cargo-rdme -->`. For example,
you can start your README with some glorious badges and follow up with the rustdoc
documentation:

```markdown
[![Build Status](https://example.org/badge.svg)](https://example.org/link-to-ci)

<!-- cargo-rdme -->
```

After running `cargo rdme` you will find your README to be something like:

```markdown
[![Build Status](https://example.org/badge.svg)](https://example.org/link-to-ci)

<!-- cargo-rdme start -->

<WHATEVER-YOUR-CRATES-DOC-IS>

<!-- cargo-rdme end -->
```

Whenever change your crate’s documentation you just need to run `cargo rdme` to update your
README file.

## Automatic transformations

The documentation of your crate doesn’t always map directly to a good README. For example,
rust code blocks can have hidden lines. Those should not be shown in the README file.

This section covers the transformation cargo rdme automatically apply to generate a better
README.

### Rust code block

Rust code block are transformed in two ways by cargo rdme:

1. Rust code blocks with lines starting with `#` will be omitted, just like in `rustdoc`.
2. Rust code blocks get annotated with the `rust` markdown tag so it gets proper syntax
   highlighting. We also remove tags that only concern `rustdoc` such as `should_panic`.

In the table below you can see an example of these modification. The code block now is
tagged with `rust` and hidden lines were removed:

<table border="1">
<col span="1" width="40%">
<col span="1" width="40%">
</colgroup>
<tr>
<th><center>Crate’s rustdoc</center></th>
<th><center>README.md</center></th>
<tr>
<tr>
<td>

```rust
//! To check if a number is prime do:
//!
//! ```
//! # fn main() {
//! for i in 2.. {
//!     if is_prime(i) {
//!         println!("{i}");
//!     }
//! }
//! # }
//! ```
```

</td>
<td>

````markdown
To check if a number is prime do:

```rust
for i in 2.. {
    if is_prime(i) {
        println!("{i}");
    }
}
```
````

</td>
</tr>
</table>

### Intralinks

Rust documentation can contain [links to items defined in the crate](https://doc.rust-lang.org/stable/rustdoc/linking-to-items-by-name.html).
This links would not make sense in your README file, so cargo rdme automatically generate
links to [docs.rs](https://docs.rs) for these intralinks.

Take a look at the example below:

<table border="1">
<col span="1" width="40%">
<col span="1" width="40%">
</colgroup>
<tr>
<th><center>Crate’s rustdoc</center></th>
<th><center>README.md</center></th>
<tr>
<tr>
<td>

```rust
//! To check if a number is prime use
//! [`is_prime`](crate::is_prime).
```

</td>
<td>

```markdown
To check if a number is prime use
[`is_prime`](https://docs.rs/prime/latest/prime/fn.is_prime.html).
```

</td>
</tr>
</table>

To resolve intralinks, cargo rdme invokes `rustdoc` on your crate and consumes its JSON output.
It requires a specific nightly rust toolchain, because rustdoc’s JSON output is unstable (see
[rust-lang/rust#76578](https://github.com/rust-lang/rust/issues/76578)) and can break between
nightly updates. Install it with `cargo rdme install-rust-toolchain-for-intralinks`.
Alternatively, if you are sure that another installed toolchain is compatible, you can either set
`rustdoc-toolchain` in the `intralinks` section of the configuration file or the
`CARGO_RDME_RUSTDOC_TOOLCHAIN` environment variable to a specific toolchain version, or to
`"default"` in order to use the default toolchain.

### Heading levels

The heading levels in the crate’s documentation will, by default, be nested under the level
of the section of the README where it is inserted into. This behavior can be changed with
the `--heading-base-level` command line flag, or in the configuration file (see example
below).

## Configuration file

If the default behavior of `cargo rdme` is not appropriate for your project you can crate a
configuration file `.cargo-rdme.toml` in the root of your project. This is how that
configuration file can look like:

```toml
# Override the README file path. When this is not set cargo rdme will use the file path defined
# in the project’s `Cargo.toml`.
readme-path = "MY-README.md"

# What line terminator to use when generating the README file. This can be "lf" or "crlf".
line-terminator = "lf"

# If you are using a workspace to hold multiple projects, use this to select the project from
# which to extract the documentation from. It can be useful to also set `readme-path` to create
# the README file in the root of the project.
workspace-project = "subproject"

# Defines the base heading level to use when inserting the crate’s documentation in the
# README. If this is not set the crate’s documentation will be inserted with its sections
# belonging to the README section where the insertion happens.
heading-base-level = 0

# The default entrypoint will be `src/lib.rs`. You can change that in the `entrypoint` table.
[entrypoint]
# The entrypoint type can be "lib" or "bin".
type = "bin"
# When you set type to "bin" the entrypoint default to `src/main.rs`. If you have binary targets
# specified in your cargo manifest you can select them by name with `bin-name`.
bin-name = "my-bin-name"

[intralinks]
# If this is set the intralinks will be stripping in the README file.
strip-links = false

# Enable all features when calling rustdoc to resolve intralinks.
# all-features = true
# Features to enable when calling rustdoc to resolve intralinks.
features = ["foo", "bar"]
# Disable default features when calling rustdoc to resolve intralinks.
no-default-features = false

[intralinks.docs]
# Layout of the documentation URLs. Either `docs-rs` (default), which produces URLs like
# `{base-url}/{crate}/{version}/{path}`, or `flat`, which produces URLs like
# `{base-url}/{path}` (the same layout as `cargo doc` output).
layout = "docs-rs"
# Base URL for documentation links. Defaults to `https://docs.rs` when `layout = "docs-rs"`.
# Required when `layout = "flat"`.
base-url = "https://mydocs.rs"
# Version segment used in documentation URLs. Defaults to `latest`. Must not be set when
# `layout = "flat"`.
version = "1.0.0"
```

These setting can be overridden with command line flags. Run `cargo rdme --help` for more
information.

## Integration with CI

To verify that your README is up to date with your crate’s documentation you can run
`cargo rdme --check`. The exit code will be `0` if the README is up to date, `3` if it’s
not, or `4` if there were warnings.

If you use GitHub Actions you can add this step to verify if the README is up to date:

```yaml
- name: Check if the README is up to date.
  run: |
    cargo install cargo-rdme
    # If you use intralinks, install the specific nightly rust toolchain cargo-rdme requires:
    cargo rdme install-rust-toolchain-for-intralinks
    cargo rdme --check
```

<!-- cargo-rdme end -->
