Skip to content
This repository has been archived by the owner on Jul 9, 2023. It is now read-only.

Cargo subcommand to perform pluggable expansions against rustdoc #20

Open
dtolnay opened this issue Jan 22, 2019 · 3 comments
Open

Cargo subcommand to perform pluggable expansions against rustdoc #20

dtolnay opened this issue Jan 22, 2019 · 3 comments

Comments

@dtolnay
Copy link
Owner

dtolnay commented Jan 22, 2019

In the GitBook that backs https://serde.rs, I use several GitBook plugins, a few of which I wrote myself.

For example I have a plugin that lets me insert playground links into code blocks. Here is an invocation right from the homepage: markdown (shown below) and rendered here with the "Run" link.

!PLAYGROUND a58fc361e02c4c0a08fd99cacd9567d1
```rust
/*
 * rust code
 */
```

Similarly a file name plugin -- markdown here and rendered here.

!FILENAME Cargo.toml
```toml
[dependencies]
serde = "1.0"
serde_derive = "1.0"
```

Here is the documentation on GitBook plugins: https://toolchain.gitbook.com/plugins/create.html
The way this one of mine is implemented is by running some regex replacements against the pre-rendered and post-rendered markdown comment. The whole implementation is just a few lines of JavaScript.

"page:before": function(page) {
    page.content = page.content.replace(/(!FILENAME .*)/g, '$1\n');
    page.content = page.content.replace(/(!PLAYGROUND .*)/g, '$1\n');
    return page;
},

"page": function(page) {
    var pattern = /<p>!FILENAME (.+)<\/p>/g;
    var tag = '<div><p class="code-filename">$1</p></div>';
    page.content = page.content.replace(pattern, tag);

    var pattern = /<p>!PLAYGROUND (.+)<\/p>\n<pre>/g;
    var tag = '<pre><a class="playground-link" target="_blank" href="https://play.rust-lang.org/?gist=$1"></a>';
    page.content = page.content.replace(pattern, tag);

    return page;
}

I would be interested in having the same capability to run snippets of logic against my pre-rendered and post-rendered rustdoc. I would like to have a Cargo subcommand:

cargo plugin-doc

which forwards to cargo doc but executes plugins before (on the Markdown) and after (on the HTML).

Plugins would be listed as metadata in Cargo.toml:

[package.metadata.rustdoc]
plugins = ["playground-links", "..."]

Plugins would be installed as ordinary binaries like cargo install rustdoc-plugin-playground-links. This project also involves developing the library for writing plugins. Mirroring the GitBook system, plugin code might look something like:

use rustdoc_plugin::{Page, Plugin};

struct PlaygroundLinksPlugin;

// Both functions are optional and do nothing by default, so you can
// implement just one or the other.
impl Plugin for PlaygroundLinksPlugin {
    fn page_before(page: &mut Page) {
        /* ... */
    }
    fn page_after(page: &mut Page) {
        /* ... */
    }
}

fn main() {
    rustdoc_plugin::main(PlaygroundLinksPlugin);
}
@pickfire
Copy link

Would it be good to add hooks in rustdoc instead of adding these to another crate? If possible, I would like to help on this.

@dtolnay
Copy link
Owner Author

dtolnay commented Oct 5, 2019

I think it would be substantially easier to experiment with this on its own outside of the main rustdoc codebase.

After there is a working product and it's something people like, we could start making a case for including it in rustdoc.

@astaninger
Copy link

I would like to give this a shot, if it hasn't already been done

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants