bluecloth 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +23 -0
- data/ext/Csio.c +2 -2
- data/ext/VERSION +1 -1
- data/ext/bluecloth.c +7 -1
- data/ext/cstring.h +3 -3
- data/ext/generate.c +362 -217
- data/ext/markdown.c +7 -6
- data/ext/markdown.h +5 -1
- data/ext/mkdio.c +1 -1
- data/ext/mkdio.h +2 -0
- data/ext/resource.c +13 -5
- data/lib/bluecloth.rb +10 -4
- data/rake/helpers.rb +16 -16
- data/rake/svn.rb +5 -4
- data/spec/bluecloth/links_spec.rb +3 -3
- data/spec/bluecloth_spec.rb +34 -0
- data/spec/discount_spec.rb +67 -0
- data/spec/lib/matchers.rb +29 -29
- metadata +6 -8
data/ext/markdown.c
CHANGED
@@ -35,7 +35,8 @@ static struct kw blocktags[] = { KW("!--"), KW("STYLE"), KW("SCRIPT"),
|
|
35
35
|
KW("H6"), KW("IFRAME"), KW("LISTING"), KW("NOBR"),
|
36
36
|
KW("UL"), KW("P"), KW("OL"), KW("DL"),
|
37
37
|
KW("PLAINTEXT"), KW("PRE"), KW("TABLE"),
|
38
|
-
KW("WBR"), KW("XMP"), SC("HR"), SC("BR")
|
38
|
+
KW("WBR"), KW("XMP"), SC("HR"), SC("BR"),
|
39
|
+
KW("MAP") };
|
39
40
|
#define SZTAGS (sizeof blocktags / sizeof blocktags[0])
|
40
41
|
#define MAXTAG 11 /* sizeof "BLOCKQUOTE" */
|
41
42
|
|
@@ -127,10 +128,10 @@ skipempty(Line *p)
|
|
127
128
|
|
128
129
|
|
129
130
|
void
|
130
|
-
___mkd_tidy(
|
131
|
+
___mkd_tidy(Cstring *t)
|
131
132
|
{
|
132
|
-
while ( S(t
|
133
|
-
--S(t
|
133
|
+
while ( S(*t) && isspace(T(*t)[S(*t)-1]) )
|
134
|
+
--S(*t);
|
134
135
|
}
|
135
136
|
|
136
137
|
|
@@ -337,7 +338,7 @@ ishdr(Line *t, int *htyp)
|
|
337
338
|
|
338
339
|
/* ANY leading `#`'s make this into an ETX header
|
339
340
|
*/
|
340
|
-
if ( i ) {
|
341
|
+
if ( i && (i < S(t->text) || i > 1) ) {
|
341
342
|
*htyp = ETX;
|
342
343
|
return 1;
|
343
344
|
}
|
@@ -871,7 +872,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
871
872
|
/* HORRIBLE STANDARDS KLUDGE: the first line of every block
|
872
873
|
* has trailing whitespace trimmed off.
|
873
874
|
*/
|
874
|
-
___mkd_tidy(p->text);
|
875
|
+
___mkd_tidy(&p->text->text);
|
875
876
|
}
|
876
877
|
|
877
878
|
ptr = codeblock(p);
|
data/ext/markdown.h
CHANGED
@@ -11,6 +11,7 @@ typedef struct footnote {
|
|
11
11
|
Cstring link; /* what this footnote points to */
|
12
12
|
Cstring title; /* what it's called (TITLE= attribute) */
|
13
13
|
int height, width; /* dimensions (for image link) */
|
14
|
+
int dealloc; /* deallocation needed? */
|
14
15
|
} Footnote;
|
15
16
|
|
16
17
|
/* each input line is read into a Line, which contains the line,
|
@@ -75,6 +76,8 @@ typedef struct mmiot {
|
|
75
76
|
#define CDATA_OUTPUT 0x0080
|
76
77
|
#define TOC 0x1000
|
77
78
|
#define MKD_1_COMPAT 0x2000
|
79
|
+
#define AUTOLINK 0x4000
|
80
|
+
#define SAFELINK 0x8000
|
78
81
|
#define USER_FLAGS 0xF0FF
|
79
82
|
#define EMBEDDED DENY_A|DENY_IMG|NO_PSEUDO_PROTO|CDATA_OUTPUT
|
80
83
|
char *base;
|
@@ -129,6 +132,7 @@ extern Document *mkd_string(char*,int, int);
|
|
129
132
|
extern void ___mkd_freeLine(Line *);
|
130
133
|
extern void ___mkd_freeLines(Line *);
|
131
134
|
extern void ___mkd_freeParagraph(Paragraph *);
|
135
|
+
extern void ___mkd_freefootnote(Footnote *);
|
132
136
|
extern void ___mkd_freefootnotes(MMIOT *);
|
133
137
|
extern void ___mkd_initmmiot(MMIOT *, void *);
|
134
138
|
extern void ___mkd_freemmiot(MMIOT *, void *);
|
@@ -136,6 +140,6 @@ extern void ___mkd_freeLineRange(Line *, Line *);
|
|
136
140
|
extern void ___mkd_xml(char *, int, FILE *);
|
137
141
|
extern void ___mkd_reparse(char *, int, int, MMIOT*);
|
138
142
|
extern void ___mkd_emblock(MMIOT*);
|
139
|
-
extern void ___mkd_tidy(
|
143
|
+
extern void ___mkd_tidy(Cstring *);
|
140
144
|
|
141
145
|
#endif/*_MARKDOWN_D*/
|
data/ext/mkdio.c
CHANGED
data/ext/mkdio.h
CHANGED
@@ -65,6 +65,8 @@ extern char markdown_version[];
|
|
65
65
|
#define MKD_CDATA 0x0080 /* generate code for xml ![CDATA[...]] */
|
66
66
|
#define MKD_TOC 0x1000 /* do table-of-contents processing */
|
67
67
|
#define MKD_1_COMPAT 0x2000 /* compatability with MarkdownTest_1.0 */
|
68
|
+
#define MKD_AUTOLINK 0x4000 /* make http://foo.com link even without <>s */
|
69
|
+
#define MKD_SAFELINK 0x8000 /* paranoid check for link protocol */
|
68
70
|
#define MKD_EMBED MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT
|
69
71
|
|
70
72
|
/* special flags for mkd_in() and mkd_string()
|
data/ext/resource.c
CHANGED
@@ -55,6 +55,17 @@ ___mkd_freeParagraph(Paragraph *p)
|
|
55
55
|
}
|
56
56
|
|
57
57
|
|
58
|
+
/* bye bye footnote.
|
59
|
+
*/
|
60
|
+
void
|
61
|
+
___mkd_freefootnote(Footnote *f)
|
62
|
+
{
|
63
|
+
DELETE(f->tag);
|
64
|
+
DELETE(f->link);
|
65
|
+
DELETE(f->title);
|
66
|
+
}
|
67
|
+
|
68
|
+
|
58
69
|
/* bye bye footnotes.
|
59
70
|
*/
|
60
71
|
void
|
@@ -63,11 +74,8 @@ ___mkd_freefootnotes(MMIOT *f)
|
|
63
74
|
int i;
|
64
75
|
|
65
76
|
if ( f->footnotes ) {
|
66
|
-
for (i=0; i < S(*f->footnotes); i++)
|
67
|
-
|
68
|
-
DELETE(T(*f->footnotes)[i].link);
|
69
|
-
DELETE(T(*f->footnotes)[i].title);
|
70
|
-
}
|
77
|
+
for (i=0; i < S(*f->footnotes); i++)
|
78
|
+
___mkd_freefootnote( &T(*f->footnotes)[i] );
|
71
79
|
DELETE(*f->footnotes);
|
72
80
|
free(f->footnotes);
|
73
81
|
}
|
data/lib/bluecloth.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
#
|
19
19
|
# == Version
|
20
20
|
#
|
21
|
-
# $Id: bluecloth.rb
|
21
|
+
# $Id: bluecloth.rb 123 2009-06-15 13:15:54Z deveiant $
|
22
22
|
#
|
23
23
|
# == License
|
24
24
|
#
|
@@ -29,13 +29,13 @@
|
|
29
29
|
class BlueCloth
|
30
30
|
|
31
31
|
# Release Version
|
32
|
-
VERSION = '2.0.
|
32
|
+
VERSION = '2.0.4'
|
33
33
|
|
34
34
|
# SVN Revision
|
35
|
-
SVNREV = %q$Rev:
|
35
|
+
SVNREV = %q$Rev: 123 $
|
36
36
|
|
37
37
|
# SVN Id tag
|
38
|
-
SVNID = %q$Id: bluecloth.rb
|
38
|
+
SVNID = %q$Id: bluecloth.rb 123 2009-06-15 13:15:54Z deveiant $
|
39
39
|
|
40
40
|
# The defaults for all supported options.
|
41
41
|
DEFAULT_OPTIONS = {
|
@@ -47,6 +47,8 @@ class BlueCloth
|
|
47
47
|
:header_labels => false,
|
48
48
|
:escape_html => false,
|
49
49
|
:strict_mode => true,
|
50
|
+
:auto_links => false,
|
51
|
+
:safe_links => false,
|
50
52
|
}.freeze
|
51
53
|
|
52
54
|
# The number of characters of the original markdown source to include in the
|
@@ -85,6 +87,8 @@ class BlueCloth
|
|
85
87
|
if opthash[:escape_html] then flags |= MKD_NOHTML; end
|
86
88
|
if opthash[:strict_mode] then flags |= MKD_STRICT; end
|
87
89
|
if opthash[:tagtext_mode] then flags |= MKD_TAGTEXT; end
|
90
|
+
if opthash[:auto_links] then flags |= MKD_AUTOLINK; end
|
91
|
+
if opthash[:safe_links] then flags |= MKD_SAFELINK; end
|
88
92
|
|
89
93
|
return flags
|
90
94
|
end
|
@@ -105,6 +109,8 @@ class BlueCloth
|
|
105
109
|
if ( flags & MKD_NOHTML ).nonzero? then opthash[:escape_html] = true; end
|
106
110
|
if ( flags & MKD_STRICT ).nonzero? then opthash[:strict_mode] = true; end
|
107
111
|
if ( flags & MKD_TAGTEXT ).nonzero? then opthash[:tagtext_mode] = true; end
|
112
|
+
if ( flags & MKD_AUTOLINK ).nonzero? then opthash[:auto_links] = true; end
|
113
|
+
if ( flags & MKD_SAFELINK ).nonzero? then opthash[:safe_links] = true; end
|
108
114
|
|
109
115
|
return opthash
|
110
116
|
end
|
data/rake/helpers.rb
CHANGED
@@ -78,7 +78,7 @@ def run( *cmd )
|
|
78
78
|
else
|
79
79
|
trace( cmd )
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
if $dryrun
|
83
83
|
$stderr.puts "(dry run mode)"
|
84
84
|
else
|
@@ -108,7 +108,7 @@ def pipeto( *cmd )
|
|
108
108
|
$stderr.puts "(dry run mode)"
|
109
109
|
else
|
110
110
|
open( '|-', 'w+' ) do |io|
|
111
|
-
|
111
|
+
|
112
112
|
# Parent
|
113
113
|
if io
|
114
114
|
yield( io )
|
@@ -138,19 +138,19 @@ def download( sourceuri, targetfile=nil )
|
|
138
138
|
targetpath.open( File::WRONLY|File::TRUNC|File::CREAT, 0644 ) do |ofh|
|
139
139
|
log "Downloading..."
|
140
140
|
buf = ''
|
141
|
-
|
141
|
+
|
142
142
|
while ifh.read( 16384, buf )
|
143
143
|
until buf.empty?
|
144
144
|
bytes = ofh.write( buf )
|
145
145
|
buf.slice!( 0, bytes )
|
146
146
|
end
|
147
147
|
end
|
148
|
-
|
148
|
+
|
149
149
|
log "Done."
|
150
150
|
end
|
151
|
-
|
151
|
+
|
152
152
|
end
|
153
|
-
|
153
|
+
|
154
154
|
return targetpath
|
155
155
|
ensure
|
156
156
|
$stdout.sync = oldsync
|
@@ -187,13 +187,13 @@ end
|
|
187
187
|
### line-endings, color reset, etc.
|
188
188
|
def colorize( *args )
|
189
189
|
string = ''
|
190
|
-
|
190
|
+
|
191
191
|
if block_given?
|
192
192
|
string = yield
|
193
193
|
else
|
194
194
|
string = args.shift
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
ending = string[/(\s)$/] || ''
|
198
198
|
string = string.rstrip
|
199
199
|
|
@@ -275,7 +275,7 @@ def prompt_for_multiple_values( label, default=nil )
|
|
275
275
|
|
276
276
|
results = []
|
277
277
|
result = nil
|
278
|
-
|
278
|
+
|
279
279
|
begin
|
280
280
|
result = readline( make_prompt_string("> ") )
|
281
281
|
if result.nil? || result.empty?
|
@@ -284,7 +284,7 @@ def prompt_for_multiple_values( label, default=nil )
|
|
284
284
|
results << result
|
285
285
|
end
|
286
286
|
end until result.nil? || result.empty?
|
287
|
-
|
287
|
+
|
288
288
|
return results.flatten
|
289
289
|
end
|
290
290
|
|
@@ -307,7 +307,7 @@ def noecho( masked=false )
|
|
307
307
|
ensure
|
308
308
|
Termios.tcsetattr( $stdin, Termios::TCSANOW, term )
|
309
309
|
end
|
310
|
-
|
310
|
+
|
311
311
|
return rval
|
312
312
|
end
|
313
313
|
|
@@ -350,7 +350,7 @@ alias :prompt_for_confirmation :ask_for_confirmation
|
|
350
350
|
### those will be returned in an Array, else the whole matching line is returned.
|
351
351
|
def find_pattern_in_file( regexp, file )
|
352
352
|
rval = nil
|
353
|
-
|
353
|
+
|
354
354
|
File.open( file, 'r' ).each do |line|
|
355
355
|
if (( match = regexp.match(line) ))
|
356
356
|
rval = match.captures.empty? ? match[0] : match.captures
|
@@ -368,7 +368,7 @@ end
|
|
368
368
|
### is returned.
|
369
369
|
def find_pattern_in_pipe( regexp, *cmd )
|
370
370
|
output = []
|
371
|
-
|
371
|
+
|
372
372
|
log( cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
|
373
373
|
Open3.popen3( *cmd ) do |stdin, stdout, stderr|
|
374
374
|
stdin.close
|
@@ -376,7 +376,7 @@ def find_pattern_in_pipe( regexp, *cmd )
|
|
376
376
|
output << stdout.gets until stdout.eof?
|
377
377
|
output << stderr.gets until stderr.eof?
|
378
378
|
end
|
379
|
-
|
379
|
+
|
380
380
|
result = output.find { |line| regexp.match(line) }
|
381
381
|
return $1 || result
|
382
382
|
end
|
@@ -403,10 +403,10 @@ end
|
|
403
403
|
### Log a subdirectory change, execute a block, and exit the subdirectory
|
404
404
|
def in_subdirectory( subdir )
|
405
405
|
block = Proc.new
|
406
|
-
|
406
|
+
|
407
407
|
log "Entering #{subdir}"
|
408
408
|
Dir.chdir( subdir, &block )
|
409
409
|
log "Leaving #{subdir}"
|
410
410
|
end
|
411
|
-
|
411
|
+
|
412
412
|
|
data/rake/svn.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Subversion Rake Tasks
|
3
|
-
# $Id: svn.rb
|
3
|
+
# $Id: svn.rb 105 2009-06-01 19:20:12Z deveiant $
|
4
4
|
#
|
5
5
|
# Authors:
|
6
6
|
# * Michael Granger <ged@FaerieMUD.org>
|
@@ -392,14 +392,15 @@ namespace :svn do
|
|
392
392
|
desc "Copy the HEAD revision of the current #{SVN_TRUNK_DIR}/ to #{SVN_BRANCHES_DIR} with a " +
|
393
393
|
"user-specified name."
|
394
394
|
task :branch, [:name] do |task, args|
|
395
|
-
|
396
|
-
|
395
|
+
branchname = args.name
|
396
|
+
unless branchname
|
397
|
+
branchname = prompt( "Branch name" ) or abort
|
397
398
|
end
|
398
399
|
|
399
400
|
svninfo = get_svn_info()
|
400
401
|
svntrunk = Pathname.new( svninfo['Repository Root'] ) + SVN_TRUNK_DIR
|
401
402
|
svnbranchdir = Pathname.new( svninfo['Repository Root'] ) + SVN_BRANCHES_DIR
|
402
|
-
svnbranch = svnbranchdir +
|
403
|
+
svnbranch = svnbranchdir + branchname
|
403
404
|
|
404
405
|
desc = "Making a new branch: #{svnbranch}"
|
405
406
|
ask_for_confirmation( desc ) do
|
@@ -4,10 +4,10 @@
|
|
4
4
|
BEGIN {
|
5
5
|
require 'pathname'
|
6
6
|
basedir = Pathname.new( __FILE__ ).dirname.parent.parent
|
7
|
-
|
7
|
+
|
8
8
|
libdir = basedir + 'lib'
|
9
9
|
extdir = basedir + 'ext'
|
10
|
-
|
10
|
+
|
11
11
|
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
12
12
|
$LOAD_PATH.unshift( extdir ) unless $LOAD_PATH.include?( extdir )
|
13
13
|
}
|
@@ -47,7 +47,7 @@ describe BlueCloth, "links" do
|
|
47
47
|
it "supports reference-style links with no title" do
|
48
48
|
the_indented_markdown( <<-"---" ).should be_transformed_into(<<-"---").without_indentation
|
49
49
|
An [example][ex] reference-style link.
|
50
|
-
|
50
|
+
|
51
51
|
[ex]: http://www.bluefi.com/
|
52
52
|
---
|
53
53
|
<p>An <a href="http://www.bluefi.com/">example</a> reference-style link.</p>
|
data/spec/bluecloth_spec.rb
CHANGED
@@ -80,6 +80,40 @@ describe BlueCloth do
|
|
80
80
|
the_markdown( input, :smartypants => true ).should be_transformed_into( expected )
|
81
81
|
end
|
82
82
|
|
83
|
+
it "correctly applies the :auto_links option to the output" do
|
84
|
+
the_indented_markdown( <<-"---", :auto_links => true ).should be_transformed_into(<<-"---").without_indentation
|
85
|
+
I wonder how many people have
|
86
|
+
http://google.com/ as their home page.
|
87
|
+
---
|
88
|
+
<p>I wonder how many people have
|
89
|
+
<a href="http://google.com/">http://google.com/</a> as their home page.</p>
|
90
|
+
---
|
91
|
+
end
|
92
|
+
|
93
|
+
it "doesn't form links for protocols it doesn't know about under :safe_links mode" do
|
94
|
+
the_indented_markdown( <<-"---", :safe_links => true ).should be_transformed_into(<<-"---").without_indentation
|
95
|
+
This is an example
|
96
|
+
[of something](javascript:do_something_bad(\\))
|
97
|
+
you might want to prevent.
|
98
|
+
---
|
99
|
+
<p>This is an example
|
100
|
+
[of something](javascript:do_something_bad())
|
101
|
+
you might want to prevent.</p>
|
102
|
+
---
|
103
|
+
end
|
104
|
+
|
105
|
+
it "forms links for protocols it doesn't know about when not under :safe_links mode" do
|
106
|
+
the_indented_markdown( <<-"---", :safe_links => false ).should be_transformed_into(<<-"---").without_indentation
|
107
|
+
This is an example
|
108
|
+
[of something](javascript:do_something_benign(\\))
|
109
|
+
you might want to allow.
|
110
|
+
---
|
111
|
+
<p>This is an example
|
112
|
+
<a href="javascript:do_something_benign()">of something</a>
|
113
|
+
you might want to allow.</p>
|
114
|
+
---
|
115
|
+
end
|
116
|
+
|
83
117
|
|
84
118
|
describe "Discount extensions" do
|
85
119
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BEGIN {
|
4
|
+
require 'pathname'
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent
|
6
|
+
|
7
|
+
libdir = basedir + 'lib'
|
8
|
+
extdir = basedir + 'ext'
|
9
|
+
|
10
|
+
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
11
|
+
$LOAD_PATH.unshift( extdir ) unless $LOAD_PATH.include?( extdir )
|
12
|
+
}
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
require 'spec'
|
16
|
+
require 'bluecloth'
|
17
|
+
|
18
|
+
require 'spec/lib/helpers'
|
19
|
+
require 'spec/lib/constants'
|
20
|
+
require 'spec/lib/matchers'
|
21
|
+
|
22
|
+
|
23
|
+
#####################################################################
|
24
|
+
### C O N T E X T S
|
25
|
+
#####################################################################
|
26
|
+
|
27
|
+
describe BlueCloth, "implementation of Discount-specific features" do
|
28
|
+
include BlueCloth::TestConstants,
|
29
|
+
BlueCloth::Matchers
|
30
|
+
|
31
|
+
before( :all ) do
|
32
|
+
@basedir = Pathname.new( __FILE__ ).dirname.parent
|
33
|
+
@datadir = @basedir + 'spec/data'
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
describe "pseudo-protocols" do
|
38
|
+
|
39
|
+
it "renders abbr: links as <abbr> phrases" do
|
40
|
+
the_indented_markdown( <<-"---", :pseudoprotocols => true ).should be_transformed_into(<<-"---").without_indentation
|
41
|
+
The [ASPCA](abbr:American Society for the Prevention of Cruelty to Animals).
|
42
|
+
---
|
43
|
+
<p>The <abbr title="American Society for the Prevention of Cruelty to Animals">ASPCA</abbr>.</p>
|
44
|
+
---
|
45
|
+
end
|
46
|
+
|
47
|
+
it "renders id: links as anchors with an ID" do
|
48
|
+
the_markdown( "[foo](id:bar)", :pseudoprotocols => true ).
|
49
|
+
should be_transformed_into( '<p><a id="bar">foo</a></p>' )
|
50
|
+
end
|
51
|
+
|
52
|
+
it "renders class: links as SPANs with a CLASS" do
|
53
|
+
the_markdown( "[foo](class:bar)", :pseudoprotocols => true ).
|
54
|
+
should be_transformed_into( '<p><span class="bar">foo</span></p>' )
|
55
|
+
end
|
56
|
+
|
57
|
+
it "renders raw: links as-is with no syntax expansion" do
|
58
|
+
the_markdown( "[foo](raw:bar)", :pseudoprotocols => true ).
|
59
|
+
should be_transformed_into( '<p>bar</p>' )
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
__END__
|
67
|
+
|