rtomayko-rdiscount 1.3.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/resource.c ADDED
@@ -0,0 +1,169 @@
1
+ /* markdown: a C implementation of John Gruber's Markdown markup language.
2
+ *
3
+ * Copyright (C) 2007 David L Parsons.
4
+ * The redistribution terms are provided in the COPYRIGHT file that must
5
+ * be distributed with this source code.
6
+ */
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+ #include <stdarg.h>
10
+ #include <stdlib.h>
11
+ #include <time.h>
12
+ #include <ctype.h>
13
+
14
+ #include "config.h"
15
+
16
+ #include "cstring.h"
17
+ #include "markdown.h"
18
+ #include "amalloc.h"
19
+
20
+ /* free a (single) line
21
+ */
22
+ void
23
+ ___mkd_freeLine(Line *ptr)
24
+ {
25
+ DELETE(ptr->text);
26
+ free(ptr);
27
+ }
28
+
29
+
30
+ /* free a list of lines
31
+ */
32
+ void
33
+ ___mkd_freeLines(Line *p)
34
+ {
35
+ if (p->next)
36
+ ___mkd_freeLines(p->next);
37
+ ___mkd_freeLine(p);
38
+ }
39
+
40
+
41
+ /* bye bye paragraph.
42
+ */
43
+ void
44
+ ___mkd_freeParagraph(Paragraph *p)
45
+ {
46
+ if (p->next)
47
+ ___mkd_freeParagraph(p->next);
48
+ if (p->down)
49
+ ___mkd_freeParagraph(p->down);
50
+ if (p->text)
51
+ ___mkd_freeLines(p->text);
52
+ if (p->ident)
53
+ free(p->ident);
54
+ free(p);
55
+ }
56
+
57
+
58
+ /* bye bye footnotes.
59
+ */
60
+ void
61
+ ___mkd_freefootnotes(MMIOT *f)
62
+ {
63
+ int i;
64
+
65
+ if ( f->footnotes ) {
66
+ for (i=0; i < S(*f->footnotes); i++) {
67
+ DELETE(T(*f->footnotes)[i].tag);
68
+ DELETE(T(*f->footnotes)[i].link);
69
+ DELETE(T(*f->footnotes)[i].title);
70
+ }
71
+ DELETE(*f->footnotes);
72
+ free(f->footnotes);
73
+ }
74
+ }
75
+
76
+
77
+ /* initialize a new MMIOT
78
+ */
79
+ void
80
+ ___mkd_initmmiot(MMIOT *f, void *footnotes)
81
+ {
82
+ if ( f ) {
83
+ memset(f, 0, sizeof *f);
84
+ CREATE(f->in);
85
+ CREATE(f->out);
86
+ CREATE(f->Q);
87
+ if ( footnotes )
88
+ f->footnotes = footnotes;
89
+ else {
90
+ f->footnotes = malloc(sizeof f->footnotes[0]);
91
+ CREATE(*f->footnotes);
92
+ }
93
+ }
94
+ }
95
+
96
+
97
+ /* free the contents of a MMIOT, but leave the object alone.
98
+ */
99
+ void
100
+ ___mkd_freemmiot(MMIOT *f, void *footnotes)
101
+ {
102
+ if ( f ) {
103
+ DELETE(f->in);
104
+ DELETE(f->out);
105
+ DELETE(f->Q);
106
+ if ( f->footnotes != footnotes )
107
+ ___mkd_freefootnotes(f);
108
+ memset(f, 0, sizeof *f);
109
+ }
110
+ }
111
+
112
+
113
+ /* free lines up to an barrier.
114
+ */
115
+ void
116
+ ___mkd_freeLineRange(Line *anchor, Line *stop)
117
+ {
118
+ Line *r = anchor->next;
119
+
120
+ if ( r != stop ) {
121
+ while ( r && (r->next != stop) )
122
+ r = r->next;
123
+ if ( r ) r->next = 0;
124
+ ___mkd_freeLines(anchor->next);
125
+ }
126
+ anchor->next = 0;
127
+ }
128
+
129
+
130
+ /* clean up everything allocated in __mkd_compile()
131
+ */
132
+ void
133
+ mkd_cleanup(Document *doc)
134
+ {
135
+ if ( doc ) {
136
+ if ( doc->ctx ) {
137
+ ___mkd_freemmiot(doc->ctx, 0);
138
+ free(doc->ctx);
139
+ }
140
+
141
+ if ( doc->code) ___mkd_freeParagraph(doc->code);
142
+ if ( doc->headers ) ___mkd_freeLines(doc->headers);
143
+ if ( T(doc->content) ) ___mkd_freeLines(T(doc->content));
144
+ memset(doc, 0, sizeof doc[0]);
145
+ free(doc);
146
+ }
147
+ }
148
+
149
+
150
+ /* write output in XML format
151
+ */
152
+ void
153
+ ___mkd_xml(char *p, int size, FILE *out)
154
+ {
155
+ char c;
156
+
157
+ while ( size-- > 0 ) {
158
+ if ( !isascii(c = *p++) )
159
+ continue;
160
+ switch (c) {
161
+ case '<': fputs("&lt;", out); break;
162
+ case '>': fputs("&gt;", out); break;
163
+ case '&': fputs("&amp;", out); break;
164
+ case '"': fputs("&quot;", out); break;
165
+ case '\'':fputs("&apos;", out); break;
166
+ default: putc(c,out); break;
167
+ }
168
+ }
169
+ }
data/ext/toc.c ADDED
@@ -0,0 +1,62 @@
1
+ /*
2
+ * toc -- spit out a table of contents based on header blocks
3
+ *
4
+ * Copyright (C) 2008 Jjgod Jiang, David L Parsons.
5
+ * The redistribution terms are provided in the COPYRIGHT file that must
6
+ * be distributed with this source code.
7
+ */
8
+ #include "config.h"
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <ctype.h>
12
+
13
+ #include "cstring.h"
14
+ #include "markdown.h"
15
+ #include "amalloc.h"
16
+
17
+ /* write an header index
18
+ */
19
+ int
20
+ mkd_generatetoc(Document *p, FILE *output)
21
+ {
22
+ Paragraph *pp;
23
+
24
+ int last_hnumber = 0,
25
+ first_hnumber = 0;
26
+
27
+ if ( !(p && p->ctx) ) return -1;
28
+ if ( ! (p->ctx->flags & TOC) ) return 0;
29
+
30
+ for ( pp = p->code; pp ; pp = pp->next ) {
31
+ if ( pp->typ == HDR && pp->text ) {
32
+
33
+ if ( last_hnumber == pp->hnumber )
34
+ fprintf(output, "%*s</li>\n", pp->hnumber, "");
35
+ else while ( last_hnumber > pp->hnumber ) {
36
+ fprintf(output, "%*s</li>\n%*s</ul>\n",
37
+ last_hnumber, "",
38
+ last_hnumber-1,"");
39
+ --last_hnumber;
40
+ }
41
+
42
+ while ( pp->hnumber > last_hnumber ) {
43
+ fprintf(output, "\n%*s<ul>\n", pp->hnumber, "");
44
+ ++last_hnumber;
45
+ }
46
+ fprintf(output, "%*s<li><a href=\"#", pp->hnumber, "");
47
+ mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), putc, output);
48
+ fprintf(output, "\">");
49
+ mkd_text(T(pp->text->text), S(pp->text->text), output, 0);
50
+ fprintf(output, "</a>");
51
+ }
52
+ }
53
+
54
+ while ( last_hnumber > 0 ) {
55
+ fprintf(output, "%*s</li>\n%*s</ul>\n",
56
+ last_hnumber, "", last_hnumber, "");
57
+ --last_hnumber;
58
+ }
59
+
60
+ return 0;
61
+ }
62
+
data/lib/markdown.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rdiscount'
data/lib/rdiscount.rb ADDED
@@ -0,0 +1,72 @@
1
+ # Discount is an implementation of John Gruber's Markdown markup
2
+ # language in C. It implements all of the language as described in
3
+ # {Markdown Syntax}[http://daringfireball.net/projects/markdown/syntax]
4
+ # and passes the Markdown 1.0 test suite. The RDiscount extension makes
5
+ # the Discount processor available via a Ruby C Extension library.
6
+ #
7
+ # === Usage
8
+ #
9
+ # RDiscount implements the basic protocol popularized by RedCloth and adopted
10
+ # by BlueCloth:
11
+ # require 'rdiscount'
12
+ # markdown = RDiscount.new("Hello World!")
13
+ # puts markdown.to_html
14
+ #
15
+ # === Replacing BlueCloth
16
+ #
17
+ # Inject RDiscount into your BlueCloth-using code by replacing your bluecloth
18
+ # require statements with the following:
19
+ # begin
20
+ # require 'rdiscount'
21
+ # BlueCloth = RDiscount
22
+ # rescue LoadError
23
+ # require 'bluecloth'
24
+ # end
25
+ #
26
+ class RDiscount
27
+ VERSION = '1.3.1.1'
28
+
29
+ # Original Markdown formatted text.
30
+ attr_reader :text
31
+
32
+ # Set true to have smarty-like quote translation performed.
33
+ attr_accessor :smart
34
+
35
+ # Do not output <style> tags included in the source text.
36
+ attr_accessor :filter_styles
37
+
38
+ # Do not output any raw HTML included in the source text.
39
+ attr_accessor :filter_html
40
+
41
+ # RedCloth compatible line folding -- not used for Markdown but
42
+ # included for compatibility.
43
+ attr_accessor :fold_lines
44
+
45
+ # Enable Table Of Contents generation
46
+ attr_accessor :generate_toc
47
+
48
+ # Create a RDiscount Markdown processor. The +text+ argument
49
+ # should be a string containing Markdown text. Additional arguments may be
50
+ # supplied to set various processing options:
51
+ #
52
+ # * <tt>:smart</tt> - Enable SmartyPants processing.
53
+ # * <tt>:filter_styles</tt> - Do not output <tt><style></tt> tags.
54
+ # * <tt>:filter_html</tt> - Do not output any raw HTML tags included in
55
+ # the source text.
56
+ # * <tt>:fold_lines</tt> - RedCloth compatible line folding (not used).
57
+ #
58
+ # NOTE: The <tt>:filter_styles</tt> extension is not yet implemented.
59
+ def initialize(text, *extensions)
60
+ @text = text
61
+ @smart = nil
62
+ @filter_styles = nil
63
+ @filter_html = nil
64
+ @fold_lines = nil
65
+ extensions.each { |e| send("#{e}=", true) }
66
+ end
67
+
68
+ end
69
+
70
+ Markdown = RDiscount unless defined? Markdown
71
+
72
+ require 'rdiscount.so'
data/rdiscount.gemspec ADDED
@@ -0,0 +1,47 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'rdiscount'
3
+ s.version = '1.3.1.1'
4
+ s.summary = "Fast Implementation of Gruber's Markdown in C"
5
+ s.date = '2009-01-31'
6
+ s.email = 'r@tomayko.com'
7
+ s.homepage = 'http://github.com/rtomayko/rdiscount'
8
+ s.has_rdoc = true
9
+ s.authors = ["Ryan Tomayko", "Andrew White"]
10
+ # = MANIFEST =
11
+ s.files = %w[
12
+ COPYING
13
+ README.markdown
14
+ Rakefile
15
+ bin/rdiscount
16
+ ext/amalloc.h
17
+ ext/config.h
18
+ ext/cstring.h
19
+ ext/docheader.c
20
+ ext/dumptree.c
21
+ ext/extconf.rb
22
+ ext/generate.c
23
+ ext/markdown.c
24
+ ext/markdown.h
25
+ ext/mkdio.c
26
+ ext/mkdio.h
27
+ ext/rbstrio.c
28
+ ext/rbstrio.h
29
+ ext/rdiscount.c
30
+ ext/resource.c
31
+ ext/toc.c
32
+ lib/markdown.rb
33
+ lib/rdiscount.rb
34
+ rdiscount.gemspec
35
+ test/benchmark.rb
36
+ test/benchmark.txt
37
+ test/markdown_test.rb
38
+ test/rdiscount_test.rb
39
+ ]
40
+ # = MANIFEST =
41
+ s.test_files = ["test/markdown_test.rb", "test/rdiscount_test.rb"]
42
+ s.extra_rdoc_files = ["COPYING"]
43
+ s.extensions = ["ext/extconf.rb"]
44
+ s.executables = ["rdiscount"]
45
+ s.require_paths = ["lib"]
46
+ s.rubyforge_project = 'wink'
47
+ end
data/test/benchmark.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+
3
+ iterations = 100
4
+ test_file = "#{File.dirname(__FILE__)}/benchmark.txt"
5
+ implementations = %w[BlueCloth RDiscount Maruku PEGMarkdown]
6
+
7
+ # Attempt to require each implementation and remove any that are not
8
+ # installed.
9
+ implementations.reject! do |class_name|
10
+ begin
11
+ module_path =
12
+ if class_name == 'PEGMarkdown'
13
+ 'peg_markdown'
14
+ else
15
+ class_name.downcase
16
+ end
17
+ require module_path
18
+ false
19
+ rescue LoadError => boom
20
+ module_path.tr! '_', '-'
21
+ puts "#{class_name} excluded. Try: gem install #{module_path}"
22
+ true
23
+ end
24
+ end
25
+
26
+ # Grab actual class objects.
27
+ implementations.map! { |class_name| Object.const_get(class_name) }
28
+
29
+ # The actual benchmark.
30
+ def benchmark(implementation, text, iterations)
31
+ start = Time.now
32
+ iterations.times do |i|
33
+ implementation.new(text).to_html
34
+ end
35
+ Time.now - start
36
+ end
37
+
38
+ # Read test file
39
+ test_data = File.read(test_file)
40
+
41
+ # Prime the pump
42
+ puts "Spinning up ..."
43
+ implementations.each { |impl| benchmark(impl, test_data, 1) }
44
+
45
+ # Run benchmarks; gather results.
46
+ puts "Running benchmarks ..."
47
+ results =
48
+ implementations.inject([]) do |r,impl|
49
+ GC.start
50
+ r << [ impl, benchmark(impl, test_data, iterations) ]
51
+ end
52
+
53
+ puts "Results for #{iterations} iterations:"
54
+ results.each do |impl,time|
55
+ printf " %10s %09.06fs total time, %09.06fs average\n", "#{impl}:", time, time / iterations
56
+ end
@@ -0,0 +1,306 @@
1
+ Markdown: Basics
2
+ ================
3
+
4
+ <ul id="ProjectSubmenu">
5
+ <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
6
+ <li><a class="selected" title="Markdown Basics">Basics</a></li>
7
+ <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
8
+ <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
9
+ <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
10
+ </ul>
11
+
12
+
13
+ Getting the Gist of Markdown's Formatting Syntax
14
+ ------------------------------------------------
15
+
16
+ This page offers a brief overview of what it's like to use Markdown.
17
+ The [syntax page] [s] provides complete, detailed documentation for
18
+ every feature, but Markdown should be very easy to pick up simply by
19
+ looking at a few examples of it in action. The examples on this page
20
+ are written in a before/after style, showing example syntax and the
21
+ HTML output produced by Markdown.
22
+
23
+ It's also helpful to simply try Markdown out; the [Dingus] [d] is a
24
+ web application that allows you type your own Markdown-formatted text
25
+ and translate it to XHTML.
26
+
27
+ **Note:** This document is itself written using Markdown; you
28
+ can [see the source for it by adding '.text' to the URL] [src].
29
+
30
+ [s]: /projects/markdown/syntax "Markdown Syntax"
31
+ [d]: /projects/markdown/dingus "Markdown Dingus"
32
+ [src]: /projects/markdown/basics.text
33
+
34
+
35
+ ## Paragraphs, Headers, Blockquotes ##
36
+
37
+ A paragraph is simply one or more consecutive lines of text, separated
38
+ by one or more blank lines. (A blank line is any line that looks like a
39
+ blank line -- a line containing nothing spaces or tabs is considered
40
+ blank.) Normal paragraphs should not be intended with spaces or tabs.
41
+
42
+ Markdown offers two styles of headers: *Setext* and *atx*.
43
+ Setext-style headers for `<h1>` and `<h2>` are created by
44
+ "underlining" with equal signs (`=`) and hyphens (`-`), respectively.
45
+ To create an atx-style header, you put 1-6 hash marks (`#`) at the
46
+ beginning of the line -- the number of hashes equals the resulting
47
+ HTML header level.
48
+
49
+ Blockquotes are indicated using email-style '`>`' angle brackets.
50
+
51
+ Markdown:
52
+
53
+ A First Level Header
54
+ ====================
55
+
56
+ A Second Level Header
57
+ ---------------------
58
+
59
+ Now is the time for all good men to come to
60
+ the aid of their country. This is just a
61
+ regular paragraph.
62
+
63
+ The quick brown fox jumped over the lazy
64
+ dog's back.
65
+
66
+ ### Header 3
67
+
68
+ > This is a blockquote.
69
+ >
70
+ > This is the second paragraph in the blockquote.
71
+ >
72
+ > ## This is an H2 in a blockquote
73
+
74
+
75
+ Output:
76
+
77
+ <h1>A First Level Header</h1>
78
+
79
+ <h2>A Second Level Header</h2>
80
+
81
+ <p>Now is the time for all good men to come to
82
+ the aid of their country. This is just a
83
+ regular paragraph.</p>
84
+
85
+ <p>The quick brown fox jumped over the lazy
86
+ dog's back.</p>
87
+
88
+ <h3>Header 3</h3>
89
+
90
+ <blockquote>
91
+ <p>This is a blockquote.</p>
92
+
93
+ <p>This is the second paragraph in the blockquote.</p>
94
+
95
+ <h2>This is an H2 in a blockquote</h2>
96
+ </blockquote>
97
+
98
+
99
+
100
+ ### Phrase Emphasis ###
101
+
102
+ Markdown uses asterisks and underscores to indicate spans of emphasis.
103
+
104
+ Markdown:
105
+
106
+ Some of these words *are emphasized*.
107
+ Some of these words _are emphasized also_.
108
+
109
+ Use two asterisks for **strong emphasis**.
110
+ Or, if you prefer, __use two underscores instead__.
111
+
112
+ Output:
113
+
114
+ <p>Some of these words <em>are emphasized</em>.
115
+ Some of these words <em>are emphasized also</em>.</p>
116
+
117
+ <p>Use two asterisks for <strong>strong emphasis</strong>.
118
+ Or, if you prefer, <strong>use two underscores instead</strong>.</p>
119
+
120
+
121
+
122
+ ## Lists ##
123
+
124
+ Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
125
+ `+`, and `-`) as list markers. These three markers are
126
+ interchangable; this:
127
+
128
+ * Candy.
129
+ * Gum.
130
+ * Booze.
131
+
132
+ this:
133
+
134
+ + Candy.
135
+ + Gum.
136
+ + Booze.
137
+
138
+ and this:
139
+
140
+ - Candy.
141
+ - Gum.
142
+ - Booze.
143
+
144
+ all produce the same output:
145
+
146
+ <ul>
147
+ <li>Candy.</li>
148
+ <li>Gum.</li>
149
+ <li>Booze.</li>
150
+ </ul>
151
+
152
+ Ordered (numbered) lists use regular numbers, followed by periods, as
153
+ list markers:
154
+
155
+ 1. Red
156
+ 2. Green
157
+ 3. Blue
158
+
159
+ Output:
160
+
161
+ <ol>
162
+ <li>Red</li>
163
+ <li>Green</li>
164
+ <li>Blue</li>
165
+ </ol>
166
+
167
+ If you put blank lines between items, you'll get `<p>` tags for the
168
+ list item text. You can create multi-paragraph list items by indenting
169
+ the paragraphs by 4 spaces or 1 tab:
170
+
171
+ * A list item.
172
+
173
+ With multiple paragraphs.
174
+
175
+ * Another item in the list.
176
+
177
+ Output:
178
+
179
+ <ul>
180
+ <li><p>A list item.</p>
181
+ <p>With multiple paragraphs.</p></li>
182
+ <li><p>Another item in the list.</p></li>
183
+ </ul>
184
+
185
+
186
+
187
+ ### Links ###
188
+
189
+ Markdown supports two styles for creating links: *inline* and
190
+ *reference*. With both styles, you use square brackets to delimit the
191
+ text you want to turn into a link.
192
+
193
+ Inline-style links use parentheses immediately after the link text.
194
+ For example:
195
+
196
+ This is an [example link](http://example.com/).
197
+
198
+ Output:
199
+
200
+ <p>This is an <a href="http://example.com/">
201
+ example link</a>.</p>
202
+
203
+ Optionally, you may include a title attribute in the parentheses:
204
+
205
+ This is an [example link](http://example.com/ "With a Title").
206
+
207
+ Output:
208
+
209
+ <p>This is an <a href="http://example.com/" title="With a Title">
210
+ example link</a>.</p>
211
+
212
+ Reference-style links allow you to refer to your links by names, which
213
+ you define elsewhere in your document:
214
+
215
+ I get 10 times more traffic from [Google][1] than from
216
+ [Yahoo][2] or [MSN][3].
217
+
218
+ [1]: http://google.com/ "Google"
219
+ [2]: http://search.yahoo.com/ "Yahoo Search"
220
+ [3]: http://search.msn.com/ "MSN Search"
221
+
222
+ Output:
223
+
224
+ <p>I get 10 times more traffic from <a href="http://google.com/"
225
+ title="Google">Google</a> than from <a href="http://search.yahoo.com/"
226
+ title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
227
+ title="MSN Search">MSN</a>.</p>
228
+
229
+ The title attribute is optional. Link names may contain letters,
230
+ numbers and spaces, but are *not* case sensitive:
231
+
232
+ I start my morning with a cup of coffee and
233
+ [The New York Times][NY Times].
234
+
235
+ [ny times]: http://www.nytimes.com/
236
+
237
+ Output:
238
+
239
+ <p>I start my morning with a cup of coffee and
240
+ <a href="http://www.nytimes.com/">The New York Times</a>.</p>
241
+
242
+
243
+ ### Images ###
244
+
245
+ Image syntax is very much like link syntax.
246
+
247
+ Inline (titles are optional):
248
+
249
+ ![alt text](/path/to/img.jpg "Title")
250
+
251
+ Reference-style:
252
+
253
+ ![alt text][id]
254
+
255
+ [id]: /path/to/img.jpg "Title"
256
+
257
+ Both of the above examples produce the same output:
258
+
259
+ <img src="/path/to/img.jpg" alt="alt text" title="Title" />
260
+
261
+
262
+
263
+ ### Code ###
264
+
265
+ In a regular paragraph, you can create code span by wrapping text in
266
+ backtick quotes. Any ampersands (`&`) and angle brackets (`<` or
267
+ `>`) will automatically be translated into HTML entities. This makes
268
+ it easy to use Markdown to write about HTML example code:
269
+
270
+ I strongly recommend against using any `<blink>` tags.
271
+
272
+ I wish SmartyPants used named entities like `&mdash;`
273
+ instead of decimal-encoded entites like `&#8212;`.
274
+
275
+ Output:
276
+
277
+ <p>I strongly recommend against using any
278
+ <code>&lt;blink&gt;</code> tags.</p>
279
+
280
+ <p>I wish SmartyPants used named entities like
281
+ <code>&amp;mdash;</code> instead of decimal-encoded
282
+ entites like <code>&amp;#8212;</code>.</p>
283
+
284
+
285
+ To specify an entire block of pre-formatted code, indent every line of
286
+ the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,
287
+ and `>` characters will be escaped automatically.
288
+
289
+ Markdown:
290
+
291
+ If you want your page to validate under XHTML 1.0 Strict,
292
+ you've got to put paragraph tags in your blockquotes:
293
+
294
+ <blockquote>
295
+ <p>For example.</p>
296
+ </blockquote>
297
+
298
+ Output:
299
+
300
+ <p>If you want your page to validate under XHTML 1.0 Strict,
301
+ you've got to put paragraph tags in your blockquotes:</p>
302
+
303
+ <pre><code>&lt;blockquote&gt;
304
+ &lt;p&gt;For example.&lt;/p&gt;
305
+ &lt;/blockquote&gt;
306
+ </code></pre>