|
8 | 8 | // option. This file may not be copied, modified, or distributed
|
9 | 9 | // except according to those terms.
|
10 | 10 |
|
| 11 | +#[allow(cstack)]; // each rendering task runs on a fixed stack segment. |
| 12 | + |
11 | 13 | use std::fmt;
|
12 |
| -use std::rt::io::Reader; |
13 |
| -use std::rt::io::pipe::PipeStream; |
14 |
| -use std::rt::io::process::{ProcessConfig, Process, CreatePipe}; |
| 14 | +use std::libc; |
15 | 15 | use std::rt::io;
|
| 16 | +use std::vec; |
16 | 17 |
|
17 | 18 | pub struct Markdown<'self>(&'self str);
|
18 | 19 |
|
| 20 | +static OUTPUT_UNIT: libc::size_t = 64; |
| 21 | + |
| 22 | +type sd_markdown = libc::c_void; // this is opaque to us |
| 23 | + |
| 24 | +// this is a large struct of callbacks we don't use |
| 25 | +type sd_callbacks = [libc::size_t, ..26]; |
| 26 | + |
| 27 | +struct html_toc_data { |
| 28 | + header_count: libc::c_int, |
| 29 | + current_level: libc::c_int, |
| 30 | + level_offset: libc::c_int, |
| 31 | +} |
| 32 | + |
| 33 | +struct html_renderopt { |
| 34 | + toc_data: html_toc_data, |
| 35 | + flags: libc::c_uint, |
| 36 | + link_attributes: Option<extern "C" fn(*buf, *buf, *libc::c_void)>, |
| 37 | +} |
| 38 | + |
| 39 | +struct buf { |
| 40 | + data: *u8, |
| 41 | + size: libc::size_t, |
| 42 | + asize: libc::size_t, |
| 43 | + unit: libc::size_t, |
| 44 | +} |
| 45 | + |
| 46 | +// sundown FFI |
| 47 | +extern { |
| 48 | + fn sdhtml_renderer(callbacks: *sd_callbacks, |
| 49 | + options_ptr: *html_renderopt, |
| 50 | + render_flags: libc::c_uint); |
| 51 | + fn sd_markdown_new(extensions: libc::c_uint, |
| 52 | + max_nesting: libc::size_t, |
| 53 | + callbacks: *sd_callbacks, |
| 54 | + opaque: *libc::c_void) -> *sd_markdown; |
| 55 | + fn sd_markdown_render(ob: *buf, |
| 56 | + document: *u8, |
| 57 | + doc_size: libc::size_t, |
| 58 | + md: *sd_markdown); |
| 59 | + fn sd_markdown_free(md: *sd_markdown); |
| 60 | + |
| 61 | + fn bufnew(unit: libc::size_t) -> *buf; |
| 62 | + fn bufrelease(b: *buf); |
| 63 | + |
| 64 | +} |
| 65 | + |
| 66 | +fn render(w: &mut io::Writer, s: &str) { |
| 67 | + // This code is all lifted from examples/sundown.c in the sundown repo |
| 68 | + unsafe { |
| 69 | + let ob = bufnew(OUTPUT_UNIT); |
| 70 | + let options = html_renderopt { |
| 71 | + toc_data: html_toc_data { |
| 72 | + header_count: 0, |
| 73 | + current_level: 0, |
| 74 | + level_offset: 0, |
| 75 | + }, |
| 76 | + flags: 0, |
| 77 | + link_attributes: None, |
| 78 | + }; |
| 79 | + let callbacks: sd_callbacks = [0, ..26]; |
| 80 | + |
| 81 | + sdhtml_renderer(&callbacks, &options, 0); |
| 82 | + let markdown = sd_markdown_new(0, 16, &callbacks, |
| 83 | + &options as *html_renderopt as *libc::c_void); |
| 84 | + |
| 85 | + do s.as_imm_buf |data, len| { |
| 86 | + sd_markdown_render(ob, data, len as libc::size_t, markdown); |
| 87 | + } |
| 88 | + sd_markdown_free(markdown); |
| 89 | + |
| 90 | + do vec::raw::buf_as_slice((*ob).data, (*ob).size as uint) |buf| { |
| 91 | + w.write(buf); |
| 92 | + } |
| 93 | + |
| 94 | + bufrelease(ob); |
| 95 | + } |
| 96 | +} |
| 97 | + |
19 | 98 | impl<'self> fmt::Default for Markdown<'self> {
|
20 | 99 | fn fmt(md: &Markdown<'self>, fmt: &mut fmt::Formatter) {
|
| 100 | + // This is actually common enough to special-case |
21 | 101 | if md.len() == 0 { return; }
|
22 | 102 |
|
23 |
| - // Create the pandoc process |
24 |
| - do io::io_error::cond.trap(|err| { |
25 |
| - fail2!("Error executing `pandoc`: {}", err.desc); |
26 |
| - }).inside { |
27 |
| - let io = ~[CreatePipe(PipeStream::new().unwrap(), true, false), |
28 |
| - CreatePipe(PipeStream::new().unwrap(), false, true)]; |
29 |
| - let args = ProcessConfig { |
30 |
| - program: "pandoc", |
31 |
| - args: [], |
32 |
| - env: None, |
33 |
| - cwd: None, |
34 |
| - io: io, |
35 |
| - }; |
36 |
| - let mut p = Process::new(args).expect("couldn't fork for pandoc"); |
37 |
| - |
38 |
| - // Write the markdown to stdin and close it. |
39 |
| - p.io[0].get_mut_ref().write(md.as_bytes()); |
40 |
| - p.io[0] = None; |
41 |
| - |
42 |
| - // Ferry the output from pandoc over to the destination buffer. |
43 |
| - let mut buf = [0, ..1024]; |
44 |
| - loop { |
45 |
| - match p.io[1].get_mut_ref().read(buf) { |
46 |
| - None | Some(0) => { break } |
47 |
| - Some(n) => { |
48 |
| - fmt.buf.write(buf.slice_to(n)); |
49 |
| - } |
50 |
| - } |
51 |
| - } |
52 |
| - } |
| 103 | + render(fmt.buf, md.as_slice()); |
53 | 104 | }
|
54 | 105 | }
|
0 commit comments