22
22
//! // ... something using html
23
23
//! ```
24
24
25
+ use std:: cast;
25
26
use std:: fmt;
26
- use std:: libc;
27
27
use std:: io;
28
+ use std:: libc;
29
+ use std:: str;
30
+ use std:: unstable:: intrinsics;
28
31
use std:: vec;
29
32
30
33
/// A unit struct which has the `fmt::Default` trait implemented. When
@@ -41,8 +44,10 @@ static MKDEXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
41
44
42
45
type sd_markdown = libc:: c_void ; // this is opaque to us
43
46
44
- // this is a large struct of callbacks we don't use
45
- type sd_callbacks = [ libc:: size_t , ..26 ] ;
47
+ struct sd_callbacks {
48
+ blockcode : extern "C" fn ( * buf , * buf , * buf , * libc:: c_void ) ,
49
+ other : [ libc:: size_t , ..25 ] ,
50
+ }
46
51
47
52
struct html_toc_data {
48
53
header_count : libc:: c_int ,
@@ -56,6 +61,11 @@ struct html_renderopt {
56
61
link_attributes : Option < extern "C" fn ( * buf , * buf , * libc:: c_void ) > ,
57
62
}
58
63
64
+ struct my_opaque {
65
+ opt : html_renderopt ,
66
+ dfltblk : extern "C" fn ( * buf , * buf , * buf , * libc:: c_void ) ,
67
+ }
68
+
59
69
struct buf {
60
70
data : * u8 ,
61
71
size : libc:: size_t ,
@@ -84,7 +94,28 @@ extern {
84
94
85
95
}
86
96
87
- fn render ( w : & mut io:: Writer , s : & str ) {
97
+ pub fn render ( w : & mut io:: Writer , s : & str ) {
98
+ extern fn block ( ob : * buf , text : * buf , lang : * buf , opaque : * libc:: c_void ) {
99
+ unsafe {
100
+ let my_opaque: & my_opaque = cast:: transmute ( opaque) ;
101
+ vec:: raw:: buf_as_slice ( ( * text) . data , ( * text) . size as uint , |text| {
102
+ let text = str:: from_utf8 ( text) ;
103
+ let mut lines = text. lines ( ) . filter ( |l| {
104
+ !l. trim ( ) . starts_with ( "#" )
105
+ } ) ;
106
+ let text = lines. to_owned_vec ( ) . connect ( "\n " ) ;
107
+
108
+ let buf = buf {
109
+ data : text. as_bytes ( ) . as_ptr ( ) ,
110
+ size : text. len ( ) as libc:: size_t ,
111
+ asize : text. len ( ) as libc:: size_t ,
112
+ unit : 0 ,
113
+ } ;
114
+ ( my_opaque. dfltblk ) ( ob, & buf, lang, opaque) ;
115
+ } )
116
+ }
117
+ }
118
+
88
119
// This code is all lifted from examples/sundown.c in the sundown repo
89
120
unsafe {
90
121
let ob = bufnew ( OUTPUT_UNIT ) ;
@@ -100,11 +131,16 @@ fn render(w: &mut io::Writer, s: &str) {
100
131
flags : 0 ,
101
132
link_attributes : None ,
102
133
} ;
103
- let callbacks: sd_callbacks = [ 0 , .. 26 ] ;
134
+ let mut callbacks: sd_callbacks = intrinsics :: init ( ) ;
104
135
105
136
sdhtml_renderer ( & callbacks, & options, 0 ) ;
137
+ let opaque = my_opaque {
138
+ opt : options,
139
+ dfltblk : callbacks. blockcode ,
140
+ } ;
141
+ callbacks. blockcode = block;
106
142
let markdown = sd_markdown_new ( extensions, 16 , & callbacks,
107
- & options as * html_renderopt as * libc:: c_void ) ;
143
+ & opaque as * my_opaque as * libc:: c_void ) ;
108
144
109
145
110
146
sd_markdown_render ( ob, s. as_ptr ( ) , s. len ( ) as libc:: size_t , markdown) ;
@@ -118,6 +154,48 @@ fn render(w: &mut io::Writer, s: &str) {
118
154
}
119
155
}
120
156
157
+ pub fn find_testable_code ( doc : & str , tests : & mut :: test:: Collector ) {
158
+ extern fn block ( _ob : * buf , text : * buf , lang : * buf , opaque : * libc:: c_void ) {
159
+ unsafe {
160
+ if text. is_null ( ) || lang. is_null ( ) { return }
161
+ let ( test, shouldfail, ignore) =
162
+ vec:: raw:: buf_as_slice ( ( * lang) . data ,
163
+ ( * lang) . size as uint , |lang| {
164
+ let s = str:: from_utf8 ( lang) ;
165
+ ( s. contains ( "rust" ) , s. contains ( "should_fail" ) ,
166
+ s. contains ( "ignore" ) )
167
+ } ) ;
168
+ if !test { return }
169
+ vec:: raw:: buf_as_slice ( ( * text) . data , ( * text) . size as uint , |text| {
170
+ let tests: & mut :: test:: Collector = intrinsics:: transmute ( opaque) ;
171
+ let text = str:: from_utf8 ( text) ;
172
+ let mut lines = text. lines ( ) . map ( |l| l. trim_chars ( & '#' ) ) ;
173
+ let text = lines. to_owned_vec ( ) . connect ( "\n " ) ;
174
+ tests. add_test ( text, ignore, shouldfail) ;
175
+ } )
176
+ }
177
+ }
178
+
179
+ unsafe {
180
+ let ob = bufnew ( OUTPUT_UNIT ) ;
181
+ let extensions = MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_TABLES |
182
+ MKDEXT_FENCED_CODE | MKDEXT_AUTOLINK |
183
+ MKDEXT_STRIKETHROUGH ;
184
+ let callbacks = sd_callbacks {
185
+ blockcode : block,
186
+ other : intrinsics:: init ( )
187
+ } ;
188
+
189
+ let tests = tests as * mut :: test:: Collector as * libc:: c_void ;
190
+ let markdown = sd_markdown_new ( extensions, 16 , & callbacks, tests) ;
191
+
192
+ sd_markdown_render ( ob, doc. as_ptr ( ) , doc. len ( ) as libc:: size_t ,
193
+ markdown) ;
194
+ sd_markdown_free ( markdown) ;
195
+ bufrelease ( ob) ;
196
+ }
197
+ }
198
+
121
199
impl < ' a > fmt:: Default for Markdown < ' a > {
122
200
fn fmt ( md : & Markdown < ' a > , fmt : & mut fmt:: Formatter ) {
123
201
// This is actually common enough to special-case
0 commit comments