Skip to content

Add support for alternative backends #507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jan 7, 2018

Conversation

Michael-F-Bryan
Copy link
Contributor

@Michael-F-Bryan Michael-F-Bryan commented Dec 12, 2017

This PR adds support for having alternative (and multiple) backends.

fixes #149

@Michael-F-Bryan
Copy link
Contributor Author

Just an update on this, I've started writing up the "protocol" we'll be using for alternate backends and added it to the user guide.

(rendered)

@Michael-F-Bryan
Copy link
Contributor Author

Michael-F-Bryan commented Dec 23, 2017

Alongside this I've started an experimental alternate backend, mdbook-epub, to see how ergonomic the "alternate backends" design is.

So far I like how backends can be discovered at runtime (meaning I don't have to patch mdbook to add a new one) and how the subprocess design enforces a strict separation between mdbook and the backend. It's a significant improvement over then unruly tangle that the HTML renderer has slowly evolved into!

At the moment I'm confident the general idea is sound, so the next step is to flesh out the mdbook-epub backend some more and see whether the "protocol" is scalable and provides what we need.

It would also be nice to move the mdbook test subcommand out into its own "renderer" ("consumer"?). This should be fairly simple to do seeing as you just need to create a temporary directory, dump individual chapters into it, then run rustdoc over them. Now configuration is more fleshed out it'd be nice to specify dependencies so your book can use crates from crates.io. Having mdbook-test its own bona fide backend would also mean you can have much more user-friendly output (I'm thinking along the lines of cargo test), which would probably be super useful for the Rust Cookbook, Rust-By-Example, and The Book. (@steveklabnik, @budziq, thoughts?)

@Michael-F-Bryan
Copy link
Contributor Author

I've also started work on a mdbook-test backend which uses @budziq's skeptic instead of rustdoc.

I was originally thinking that mdbook test could be shorthand for running the mdbook-test backend (if installed). The problem is that skeptic tests are largely incompatible with rustdoc (skeptic requires a main function) so we'd end up breaking quite a lot of projects currently using mdbook test and inconveniencing a lot of people 😞

As a datapoint, the Rust cookbook already uses skeptic although Rust By Example promote using mdbook test (rustdoc tests).


From my experience implementing the experimental mdbook-epub and mdbook-test backends I've found I'm increasingly liking the way it's implemented. Mucking around with dlopen and loading shared objects as a plugin mechanism is quite brittle and requires the backend and mdbook to be exactly in sync or else you risk segfaults and ABI incompatibilities.

On the other hand, using subprocesses and passing in the input via stdin is a quite robust, meaning a dodgy backend can't crash the entire application, and the JSON format allows a bit of flexibility in that you can still use an old plugin with a newer version of mdbook.

There are still a couple outstanding questions that need to be resolved, but it looks like this backend design will be present in the next major version of mdbook.

@Michael-F-Bryan
Copy link
Contributor Author

I've gone back through the PR and I believe this is about ready to merge 🎉

The next big internals task is to do a big rewrite of the HTML renderer. At the moment it's quite messy and convoluted, and has accumulated a lot of technical debt as bits and pieces get added by different contributors.

With a much more organised renderer, things like #468 should just fall out, and it'll be a lot easier to resolve merge conflicts in #472. I mean you'll still have to rewrite the stuff hooked into the renderer, but that would have had to happen anyway and it's easier to fix with a cleaner design.

@Michael-F-Bryan Michael-F-Bryan merged commit fd7e8d1 into rust-lang:master Jan 7, 2018
@Michael-F-Bryan Michael-F-Bryan deleted the alternate_backends branch January 26, 2018 03:17
Ruin0x11 pushed a commit to Ruin0x11/mdBook that referenced this pull request Aug 30, 2020
* Added a mechanism for creating alternate backends

* Added a CmdRenderer and the ability to have multiple renderers

* Made MDBook::load() autodetect renderers

* Added a couple methods to RenderContext

* Converted RenderContext.version to a String

* Made sure all alternate renderers are invoked as `mdbook-*`

* Factored out the logic for determining which renderer to use

* Added tests for renderer detection

* Made it so `mdbook test` works on the book-example again

* Updated the "For Developers" docs

* Removed `[output.epub]` from the example book's book.toml

* Added a bit more info on how backends should work

* Added a `destination` key to the RenderContext

* Altered how we wait for an alternate backend to finish

* Refactored the Renderer trait to not use MDBook and moved livereload to the template

* Moved info for developers out of the book.toml format chapter

* MOAR docs

* MDBook::build() no longer takes &mut self

* Replaced a bunch of println!()'s with proper log macros

* Cleaned up the build() method and backend discovery

* Added a couple notes and doc-comments

* Found a race condition when backends exit really quickly

* Added support for backends with arguments

* Fixed a funny doc-comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Discussion] New renderers design
1 participant