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.
@@ -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
+ }
@@ -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
+ }
@@ -0,0 +1 @@
1
+ require 'rdiscount'
@@ -0,0 +1,153 @@
1
+ require 'rdiscount'
2
+
3
+ class Moredown < RDiscount
4
+ VERSION = '1.0.4'
5
+
6
+ # Don't use inline CSS for styling
7
+ attr_accessor :has_stylesheet
8
+
9
+ # Process emoticons
10
+ attr_accessor :emotes
11
+
12
+ # Map any relative URLs in the text to absolute URLs
13
+ attr_accessor :base_url
14
+
15
+ # Map headings down a few ranks (eg. :map_headings => 2 would convert h1 to h3)
16
+ attr_accessor :map_headings
17
+
18
+ # Use SwfObject2 if available (eg. :swfobject => { :src => 'swfobject.js', :version => '10', :fallback => 'No Flash' })
19
+ attr_accessor :swfobject
20
+
21
+ # Create a Moredown Markdown processor. The +text+ argument
22
+ # should be a string containing Markdown text. Additional arguments may be
23
+ # supplied to set various processing options:
24
+ #
25
+ # * <tt>:extensions</tt> - Any of the following RDiscount Extensions:
26
+ # * <tt>:smart</tt> - Enable SmartyPants processing.
27
+ # * <tt>:filter_styles</tt> - Do not output <tt><style></tt> tags.
28
+ # * <tt>:filter_html</tt> - Do not output any raw HTML tags included in
29
+ # the source text.
30
+ # * <tt>:fold_lines</tt> - RedCloth compatible line folding (not used).
31
+ # * <tt>:has_stylesheet</tt> - Don't use inline CSS for styling.
32
+ # * <tt>:emotes</tt> - Process emoticons.
33
+ # * <tt>:base_url</tt> - Map any relative URLs in the text to absolute URLs.
34
+ # * <tt>:map_headings</tt> - Map any headings down a few ranks (eg. h1 => h3).
35
+ # * <tt>:swfobject</tt> - Use SwfObject2 if available (eg. :swfobject => { :src => 'swfobject.js', :version => '10', :fallback => 'No Flash' })
36
+ #
37
+ # NOTE: The <tt>:filter_styles</tt> extension is not yet implemented.
38
+ def initialize text, args = {}
39
+ @has_stylesheet = args[:has_stylesheet]
40
+ @emotes = args[:emotes]
41
+ @base_url = args[:base_url]
42
+ @map_headings = args[:map_headings] || 0
43
+ @swfobject = args[:swfobject]
44
+
45
+ # each swfobject needs a unique id
46
+ @next_flash_id = 0
47
+
48
+ if args[:extensions]
49
+ super(text, args[:extensions])
50
+ else
51
+ super(text)
52
+ end
53
+ end
54
+
55
+ def to_html
56
+ html = super
57
+
58
+ # flash movies (including youtube)
59
+ html.gsub!(/<img src="(flash|youtube):(.*?)"\s?(?:title="(.*?)")? alt="(.*)" \/>/) do |match|
60
+ # grab width and height
61
+ if $3
62
+ sizes = $3.split(' ')
63
+ sizes = { :width => sizes[0], :height => sizes[1] }
64
+ else
65
+ sizes = {}
66
+ end
67
+
68
+ # check the source
69
+ if $1.downcase == "youtube"
70
+ url = "http://www.youtube.com/v/#{$2}"
71
+ sizes = { :width => 425, :height => 350 }.merge sizes
72
+ else
73
+ url = $2
74
+ end
75
+
76
+ flash_tag url, sizes
77
+ end
78
+
79
+ # image alignments
80
+ if @has_stylesheet
81
+ html.gsub!(/<img (.*?) \/>:(left|right|center)/) { |match| "<img class=\"#{$2}\" #{$1} />" }
82
+ else
83
+ html.gsub!(/<img (.*?) \/>:left/) { |match| "<img style=\"float: left; margin: 0 10px 10px 0;\" #{$1} />" }
84
+ html.gsub!(/<img (.*?) \/>:right/) { |match| "<img style=\"float: right; margin: 0 0 10px 10px;\" #{$1} />" }
85
+ html.gsub!(/<img (.*?) \/>:center/) { |match| "<img style=\"display: block; margin: auto;\" #{$1} />" }
86
+ end
87
+
88
+ # code
89
+ html.gsub!('<pre>', '<pre class="prettyprint">')
90
+
91
+ # emoticons
92
+ if @emotes
93
+ html.gsub!(':-)', '<img src="/images/emote-smile.png" alt=":-)" width="16" height="16" />')
94
+ html.gsub!(':-P', '<img src="/images/emote-tongue.png" alt=":-P" width="16" height="16" />')
95
+ html.gsub!(':-D', '<img src="/images/emote-grin.png" alt=":-D" width="16" height="16" />')
96
+ html.gsub!(':-(', '<img src="/images/emote-sad.png" alt=":-(" width="16" height="16" />')
97
+ html.gsub!(':-@', '<img src="/images/emote-angry.png" alt=":-@" width="16" height="16" />')
98
+ html.gsub!(';-)', '<img src="/images/emote-wink.png" alt=";-)" width="16" height="16" />')
99
+ end
100
+
101
+ # remap relative urls
102
+ if @base_url
103
+ html.gsub!('"/images/', "\"#{@base_url}/images/")
104
+ html.gsub!('<a href="/', "<a href=\"#{@base_url}/")
105
+ end
106
+
107
+ # remap headings down a few notches
108
+ if @map_headings > 0
109
+ html.gsub!(/<(\/)?h(\d)>/) { |match| "<#{$1}h#{$2.to_i + @map_headings}>" }
110
+ end
111
+
112
+ # add the js for swfobject
113
+ if @swfobject
114
+ swfobjects = []
115
+ 1.upto(@next_flash_id).each do |n|
116
+ swfobjects << "swfobject.registerObject(\"swf-#{n}\", \"#{@swfobject[:version]}\");\n"
117
+ end
118
+
119
+ # html seems to need to go after the swfobject javascript
120
+ html = "<script type=\"text/javascript\" src=\"#{@swfobject[:src]}\"></script><script type=\"text/javascript\">\n/*<![CDATA[*/\n#{swfobjects}/*]]>*/\n</script>\n#{html}"
121
+ end
122
+
123
+ html
124
+ end
125
+
126
+ # Process some text in Markdown format
127
+ def self.text_to_html text, args = {}
128
+ Moredown.new(text, args).to_html
129
+ end
130
+
131
+
132
+ protected
133
+ def flash_tag url, args = {}
134
+ args = {:width => 400, :height => 300, :fallback => 'Flash is not available.'}.merge args
135
+
136
+ if url.include? 'youtube.com'
137
+ fallback = "<a href=\"#{url}\"><img src=\"http://img.youtube.com/vi/#{url.split('/').last}/default.jpg\" alt=\"\" /></a>"
138
+ elsif @swfobject
139
+ fallback = @swfobject[:fallback]
140
+ else
141
+ fallback = args[:fallback]
142
+ end
143
+
144
+ return "<object id=\"swf-#{@next_flash_id += 1}\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"#{args[:width]}\" height=\"#{args[:height]}\">" \
145
+ +"<param name=\"movie\" value=\"#{url}\" />" \
146
+ +"<!--[if !IE]>-->" \
147
+ +"<object type=\"application/x-shockwave-flash\" data=\"#{url}\" width=\"#{args[:width]}\" height=\"#{args[:height]}\">" \
148
+ +"<!--<![endif]-->#{fallback}<!--[if !IE]>-->" \
149
+ +"</object>" \
150
+ +"<!--<![endif]-->" \
151
+ +"</object>"
152
+ end
153
+ end
@@ -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'