bluecloth 2.0.3 → 2.0.4
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/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
|
+
|