Skip to content

Commit

Permalink
Implement a markdown renderer (rust-lang#1018)
Browse files Browse the repository at this point in the history
Use case: when trying to `mdbook test` a file that has many `include`
directives, and a test fails, the line numbers in the `rustdoc` output
don't match the line numbers in the original markdown file.

Turning on the markdown renderer implemented here lets you see what is
being passed to `rustdoc` by saving the markdown after the preprocessors
have run.

This renderer could be helpful for debugging many preprocessors, but
it's probably not useful in the general case, so it's turned off by
default.
  • Loading branch information
carols10cents authored and Dylan-DPC committed Aug 30, 2019
1 parent 653db8d commit 9552ad5
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ format, however there's nothing stopping a renderer from doing static analysis
of a book in order to validate links or run tests. Some existing renderers are:
- `html` - the built-in renderer which will generate a HTML version of the book
- `markdown` - the built-in renderer (disabled by default) which will run
preprocessors then output the resulting Markdown. Useful for debugging
preprocessors.
- [`linkcheck`] - a backend which will check that all links are valid
- [`epub`] - an experimental EPUB generator
Expand Down
20 changes: 20 additions & 0 deletions book-example/src/format/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,26 @@ heading-split-level = 3
copy-js = true
```

### Markdown Renderer

The Markdown renderer will run preprocessors and then output the resulting
Markdown. This is mostly useful for debugging preprocessors, especially in
conjunction with `mdbook test` to see the Markdown that `mdbook` is passing
to `rustdoc`.

The Markdown renderer is included with `mdbook` but disabled by default.
Enable it by adding an emtpy table to your `book.toml` as follows:

```toml
[output.markdown]
```

There are no configuration options for the Markdown renderer at this time;
only whether it is enabled or disabled.

See [the preprocessors documentation](#configuring-preprocessors) for how to
specify which preprocessors should run before the Markdown renderer.

### Custom Renderers

A custom renderer can be enabled by adding a `[output.foo]` table to your
Expand Down
4 changes: 3 additions & 1 deletion src/book/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::errors::*;
use crate::preprocess::{
CmdPreprocessor, IndexPreprocessor, LinkPreprocessor, Preprocessor, PreprocessorContext,
};
use crate::renderer::{CmdRenderer, HtmlHandlebars, RenderContext, Renderer};
use crate::renderer::{CmdRenderer, HtmlHandlebars, MarkdownRenderer, RenderContext, Renderer};
use crate::utils;

use crate::config::Config;
Expand Down Expand Up @@ -336,6 +336,8 @@ fn determine_renderers(config: &Config) -> Vec<Box<dyn Renderer>> {
renderers.extend(output_table.iter().map(|(key, table)| {
if key == "html" {
Box::new(HtmlHandlebars::new()) as Box<dyn Renderer>
} else if key == "markdown" {
Box::new(MarkdownRenderer::new()) as Box<dyn Renderer>
} else {
interpret_custom_renderer(key, table)
}
Expand Down
46 changes: 46 additions & 0 deletions src/renderer/markdown_renderer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::book::BookItem;
use crate::errors::*;
use crate::renderer::{RenderContext, Renderer};
use crate::utils;

use std::fs;

#[derive(Default)]
/// A renderer to output the Markdown after the preprocessors have run. Mostly useful
/// when debugging preprocessors.
pub struct MarkdownRenderer;

impl MarkdownRenderer {
/// Create a new `MarkdownRenderer` instance.
pub fn new() -> Self {
MarkdownRenderer
}
}

impl Renderer for MarkdownRenderer {
fn name(&self) -> &str {
"markdown"
}

fn render(&self, ctx: &RenderContext) -> Result<()> {
let destination = &ctx.destination;
let book = &ctx.book;

if destination.exists() {
utils::fs::remove_dir_content(destination)
.chain_err(|| "Unable to remove stale Markdown output")?;
}

trace!("markdown render");
for item in book.iter() {
if let BookItem::Chapter(ref ch) = *item {
utils::fs::write_file(&ctx.destination, &ch.path, ch.content.as_bytes())?;
}
}

fs::create_dir_all(&destination)
.chain_err(|| "Unexpected error when constructing destination path")?;

Ok(())
}
}
2 changes: 2 additions & 0 deletions src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
//! [RenderContext]: struct.RenderContext.html
pub use self::html_handlebars::HtmlHandlebars;
pub use self::markdown_renderer::MarkdownRenderer;

mod html_handlebars;
mod markdown_renderer;

use shlex::Shlex;
use std::fs;
Expand Down

0 comments on commit 9552ad5

Please sign in to comment.