nathanhoad-moredown 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,86 @@
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_toc(Document *p, char **doc)
21
+ {
22
+ Paragraph *pp;
23
+ int last_hnumber = 0;
24
+ Cstring res;
25
+
26
+ CREATE(res);
27
+ RESERVE(res, 100);
28
+
29
+ *doc = 0;
30
+
31
+ if ( !(p && p->ctx) ) return -1;
32
+ if ( ! (p->ctx->flags & TOC) ) return 0;
33
+
34
+ for ( pp = p->code; pp ; pp = pp->next ) {
35
+ if ( pp->typ == HDR && pp->text ) {
36
+
37
+ if ( last_hnumber == pp->hnumber )
38
+ Csprintf(&res, "%*s</li>\n", pp->hnumber, "");
39
+ else while ( last_hnumber > pp->hnumber ) {
40
+ Csprintf(&res, "%*s</li>\n%*s</ul>\n",
41
+ last_hnumber, "",
42
+ last_hnumber-1,"");
43
+ --last_hnumber;
44
+ }
45
+
46
+ while ( pp->hnumber > last_hnumber ) {
47
+ Csprintf(&res, "\n%*s<ul>\n", pp->hnumber, "");
48
+ ++last_hnumber;
49
+ }
50
+ Csprintf(&res, "%*s<li><a href=\"#", pp->hnumber, "");
51
+ mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Csputc, &res);
52
+ Csprintf(&res, "\">");
53
+ Csreparse(&res, T(pp->text->text), S(pp->text->text), 0);
54
+ Csprintf(&res, "</a>");
55
+ }
56
+ }
57
+
58
+ while ( last_hnumber > 0 ) {
59
+ Csprintf(&res, "%*s</li>\n%*s</ul>\n",
60
+ last_hnumber, "", last_hnumber, "");
61
+ --last_hnumber;
62
+ }
63
+ /* HACK ALERT! HACK ALERT! HACK ALERT! */
64
+ *doc = T(res); /* we know that a T(Cstring) is a character pointer */
65
+ /* so we can simply pick it up and carry it away, */
66
+ return S(res); /* leaving the husk of the Ctring on the stack */
67
+ /* END HACK ALERT */
68
+ }
69
+
70
+
71
+ /* write an header index
72
+ */
73
+ int
74
+ mkd_generatetoc(Document *p, FILE *out)
75
+ {
76
+ char *buf = 0;
77
+ int sz = mkd_toc(p, &buf);
78
+ int ret = EOF;
79
+
80
+ if ( sz > 0 )
81
+ ret = fwrite(buf, sz, 1, out);
82
+
83
+ if ( buf ) free(buf);
84
+
85
+ return ret;
86
+ }
data/lib/markdown.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rdiscount'
data/lib/moredown.rb ADDED
@@ -0,0 +1,100 @@
1
+ require 'rdiscount'
2
+
3
+ class Moredown < RDiscount
4
+ # Convert youtube videos to preview images (handy for valid RSS)
5
+ attr_accessor :youtube_as_images
6
+
7
+ # Don't use inline CSS for styling
8
+ attr_accessor :has_stylesheet
9
+
10
+ # Process emoticons
11
+ attr_accessor :emotes
12
+
13
+ # Map any relative URLs in the text to absolute URLs
14
+ attr_accessor :base_url
15
+
16
+ # Map headings down a few ranks (eg. :map_headings => 2 would convert h1 to h3)
17
+ attr_accessor :map_headings
18
+
19
+ # Create a Moredown Markdown processor. The +text+ argument
20
+ # should be a string containing Markdown text. Additional arguments may be
21
+ # supplied to set various processing options:
22
+ #
23
+ # * <tt>:extensions</tt> - Any of the following RDiscount Extensions:
24
+ # * <tt>:smart</tt> - Enable SmartyPants processing.
25
+ # * <tt>:filter_styles</tt> - Do not output <tt><style></tt> tags.
26
+ # * <tt>:filter_html</tt> - Do not output any raw HTML tags included in
27
+ # the source text.
28
+ # * <tt>:fold_lines</tt> - RedCloth compatible line folding (not used).
29
+ # * <tt>:youtube_as_images</tt> - Convert youtube videos to preview images (handy for valid RSS).
30
+ # * <tt>:has_stylesheet</tt> - Don't use inline CSS for styling.
31
+ # * <tt>:emotes</tt> - Process emoticons.
32
+ # * <tt>:base_url</tt> - Map any relative URLs in the text to absolute URLs.
33
+ # * <tt>:map_headings</tt> - Map any headings down a few ranks (eg. h1 => h3).
34
+ #
35
+ # NOTE: The <tt>:filter_styles</tt> extension is not yet implemented.
36
+ def initialize text, args = {}
37
+ @youtube_as_images = args[:youtube_as_images]
38
+ @has_stylesheet = args[:has_stylesheet]
39
+ @emotes = args[:emotes]
40
+ @base_url = args[:base_url]
41
+ @map_headings = args[:map_headings] || 0
42
+
43
+ if args[:extensions]
44
+ super(text, args[:extensions])
45
+ else
46
+ super(text)
47
+ end
48
+ end
49
+
50
+ def to_html
51
+ # Youtube
52
+ if @youtube_as_images
53
+ @text.gsub!(/!\[(.*)?\]\(youtube:(.+)?\)/) { |match| "<img src=\"http://img.youtube.com/vi/#{$2}/default.jpg\" alt=\"#{$1}\" />" }
54
+ else
55
+ @text.gsub!(/!\[.*?\]\(youtube:(.+)?\)/) { |match| "<object data=\"http://www.youtube.com/v/#{$1}\" type=\"application/x-shockwave-flash\" width=\"425\" height=\"350\"><param name=\"movie\" value=\"http://www.youtube.com/v/#{$1}\" /></object>" }
56
+ end
57
+
58
+ html = super
59
+
60
+ # image alignments
61
+ if @has_stylesheet
62
+ html.gsub!(/<img (.*?) \/>:(left|right|center)/) { |match| "<img class=\"#{$2}\" #{$1} />" }
63
+ else
64
+ html.gsub!(/<img (.*?) \/>:left/) { |match| "<img style=\"float: left; margin: 0 10px 10px 0;\" #{$1} />" }
65
+ html.gsub!(/<img (.*?) \/>:right/) { |match| "<img style=\"float: right; margin: 0 0 10px 10px;\" #{$1} />" }
66
+ html.gsub!(/<img (.*?) \/>:center/) { |match| "<img style=\"display: block; margin: auto;\" #{$1} />" }
67
+ end
68
+
69
+ # code
70
+ html.gsub!('<pre>', '<pre class="prettyprint">')
71
+
72
+ # emoticons
73
+ if @emotes
74
+ html.gsub!(':-)', '<img src="/images/emote-smile.png" alt=":-)" width="16" height="16" />')
75
+ html.gsub!(':-P', '<img src="/images/emote-tongue.png" alt=":-P" width="16" height="16" />')
76
+ html.gsub!(':-D', '<img src="/images/emote-grin.png" alt=":-D" width="16" height="16" />')
77
+ html.gsub!(':-(', '<img src="/images/emote-sad.png" alt=":-(" width="16" height="16" />')
78
+ html.gsub!(':-@', '<img src="/images/emote-angry.png" alt=":-@" width="16" height="16" />')
79
+ html.gsub!(';-)', '<img src="/images/emote-wink.png" alt=";-)" width="16" height="16" />')
80
+ end
81
+
82
+ # remap relative urls
83
+ if @base_url
84
+ html.gsub!('"/images/', "\"#{@base_url}/images/")
85
+ html.gsub!('<a href="/', "<a href=\"#{@base_url}/")
86
+ end
87
+
88
+ # remap headings down a few notches
89
+ if @map_headings > 0
90
+ html.gsub!(/<(\/)?h(\d)>/) { |match| "<#{$1}h#{$2.to_i + @map_headings}>" }
91
+ end
92
+
93
+ html
94
+ end
95
+
96
+ # Process some text in Markdown format
97
+ def self.text_to_html text, args = {}
98
+ Moredown.new(text, args).to_html
99
+ end
100
+ end
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.5'
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,46 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'rdiscount'
3
+ s.version = '1.3.5'
4
+ s.summary = "Fast Implementation of Gruber's Markdown in C"
5
+ s.date = '2009-07-26'
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/Csio.c
17
+ ext/amalloc.h
18
+ ext/config.h
19
+ ext/cstring.h
20
+ ext/docheader.c
21
+ ext/dumptree.c
22
+ ext/extconf.rb
23
+ ext/generate.c
24
+ ext/markdown.c
25
+ ext/markdown.h
26
+ ext/mkdio.c
27
+ ext/mkdio.h
28
+ ext/rdiscount.c
29
+ ext/resource.c
30
+ ext/toc.c
31
+ lib/markdown.rb
32
+ lib/rdiscount.rb
33
+ rdiscount.gemspec
34
+ test/benchmark.rb
35
+ test/benchmark.txt
36
+ test/markdown_test.rb
37
+ test/rdiscount_test.rb
38
+ ]
39
+ # = MANIFEST =
40
+ s.test_files = ["test/markdown_test.rb", "test/rdiscount_test.rb"]
41
+ s.extra_rdoc_files = ["COPYING"]
42
+ s.extensions = ["ext/extconf.rb"]
43
+ s.executables = ["rdiscount"]
44
+ s.require_paths = ["lib"]
45
+ s.rubyforge_project = 'wink'
46
+ end