bluecloth 2.0.9 → 2.0.10
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.tar.gz.sig +0 -0
- data/ChangeLog +29 -2
- data/Rakefile +18 -15
- data/ext/VERSION +1 -1
- data/ext/bluecloth.c +26 -5
- data/ext/config.h +13 -2
- data/ext/css.c +14 -5
- data/ext/cstring.h +1 -1
- data/ext/docheader.c +13 -7
- data/ext/emmatch.c +1 -1
- data/ext/generate.c +134 -48
- data/ext/markdown.c +207 -94
- data/ext/markdown.h +37 -28
- data/ext/mkdio.c +39 -32
- data/ext/mkdio.h +34 -24
- data/ext/resource.c +3 -1
- data/ext/setup.c +47 -0
- data/ext/tags.c +15 -2
- data/ext/tags.h +1 -0
- data/lib/bluecloth.rb +65 -40
- data/rake/documentation.rb +9 -1
- data/rake/hg.rb +34 -3
- data/rake/packaging.rb +1 -1
- data/rake/publishing.rb +2 -9
- data/rake/testing.rb +53 -88
- data/spec/bluecloth/101_changes_spec.rb +17 -17
- data/spec/bluecloth/autolinks_spec.rb +1 -1
- data/spec/bluecloth/blockquotes_spec.rb +18 -18
- data/spec/bluecloth/code_spans_spec.rb +1 -1
- data/spec/bluecloth/emphasis_spec.rb +1 -1
- data/spec/bluecloth/entities_spec.rb +1 -1
- data/spec/bluecloth/hrules_spec.rb +1 -1
- data/spec/bluecloth/images_spec.rb +1 -1
- data/spec/bluecloth/inline_html_spec.rb +1 -1
- data/spec/bluecloth/links_spec.rb +1 -1
- data/spec/bluecloth/lists_spec.rb +1 -1
- data/spec/bluecloth/paragraphs_spec.rb +1 -1
- data/spec/bluecloth/titles_spec.rb +1 -1
- data/spec/bluecloth_spec.rb +13 -13
- data/spec/bugfix_spec.rb +6 -1
- data/spec/contributions_spec.rb +1 -1
- data/spec/discount_spec.rb +2 -2
- data/spec/lib/helpers.rb +1 -124
- data/spec/lib/matchers.rb +1 -1
- data/spec/markdowntest_spec.rb +1 -1
- metadata +10 -10
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,4 +1,31 @@
|
|
1
|
-
|
1
|
+
147[tip] 6f434470d71c 2011-01-17 09:16 -0800 ged
|
2
|
+
Added tag 2.0.10 for changeset 85dc2533f18e
|
3
|
+
|
4
|
+
146[2.0.10] 85dc2533f18e 2011-01-17 09:16 -0800 ged
|
5
|
+
Added signature for changeset 3dd45baec201
|
6
|
+
|
7
|
+
145 3dd45baec201 2011-01-17 09:14 -0800 ged
|
8
|
+
Bumping version.
|
9
|
+
|
10
|
+
144 a12b01a92197 2011-01-17 09:13 -0800 ged
|
11
|
+
Updated to Discount 2.0.4:
|
12
|
+
|
13
|
+
143 5ef78d71c329 2010-10-15 08:20 -0700 ged
|
14
|
+
Adding an example for the 'Wrong (different) allignment in code block' ticket (refs #71).
|
15
|
+
|
16
|
+
142 0efe9f9e4598 2010-10-15 08:19 -0700 ged
|
17
|
+
Converting to RSpec 2.0.
|
18
|
+
|
19
|
+
141[github/master,master] 8372e8b4c95e 2010-09-23 07:25 -0700 ged
|
20
|
+
Added tag 2.0.9 for changeset 5bbf74a21ecb
|
21
|
+
|
22
|
+
140[2.0.9] 5bbf74a21ecb 2010-09-23 07:25 -0700 ged
|
23
|
+
Added signature for changeset 0a9f01744efb
|
24
|
+
|
25
|
+
139 0a9f01744efb 2010-09-23 07:24 -0700 ged
|
26
|
+
Added tag 2.0.8 for changeset 8ccd2cfe599e
|
27
|
+
|
28
|
+
138 486a5a2a8cd2 2010-09-23 07:15 -0700 ged
|
2
29
|
Bump version, update the Windows build to use 1.9.2 instead of 1.9.1.
|
3
30
|
|
4
31
|
137 1caa0c888dfe 2010-09-17 15:03 -0700 ged
|
@@ -19,7 +46,7 @@
|
|
19
46
|
132 3f36f96bfb8e 2010-08-16 11:50 -0700 ged
|
20
47
|
Install extension in arch-specific subdir [RPS]
|
21
48
|
|
22
|
-
131 8ccd2cfe599e 2010-08-11 09:54 -0600 ged
|
49
|
+
131[2.0.8] 8ccd2cfe599e 2010-08-11 09:54 -0600 ged
|
23
50
|
Bump version to 2.0.8
|
24
51
|
|
25
52
|
130 f2d6de73c6d6 2010-08-11 09:54 -0600 ged
|
data/Rakefile
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
# Based on various other Rakefiles, especially one by Ben Bleything
|
6
6
|
#
|
7
|
-
# Copyright (c) 2007-
|
7
|
+
# Copyright (c) 2007-2011 The FaerieMUD Consortium
|
8
8
|
#
|
9
9
|
# Authors:
|
10
10
|
# * Michael Granger <ged@FaerieMUD.org>
|
@@ -42,6 +42,7 @@ rescue LoadError
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
require 'pathname'
|
45
46
|
require 'rbconfig'
|
46
47
|
require 'rake'
|
47
48
|
require 'rake/testtask'
|
@@ -173,9 +174,9 @@ include RakefileHelpers
|
|
173
174
|
# Set the build ID if the mercurial executable is available
|
174
175
|
if hg = which( 'hg' )
|
175
176
|
id = `#{hg} id -n`.chomp
|
176
|
-
PKG_BUILD =
|
177
|
+
PKG_BUILD = (id.chomp[ /^[[:xdigit:]]+/ ] || '1')
|
177
178
|
else
|
178
|
-
PKG_BUILD = '
|
179
|
+
PKG_BUILD = '0'
|
179
180
|
end
|
180
181
|
SNAPSHOT_PKG_NAME = "#{PKG_FILE_NAME}.#{PKG_BUILD}"
|
181
182
|
SNAPSHOT_GEM_NAME = "#{SNAPSHOT_PKG_NAME}.gem"
|
@@ -192,7 +193,6 @@ RDOC_OPTIONS = [
|
|
192
193
|
]
|
193
194
|
YARD_OPTIONS = [
|
194
195
|
'--use-cache',
|
195
|
-
'--no-private',
|
196
196
|
'--protected',
|
197
197
|
'-r', README_FILE,
|
198
198
|
'--exclude', 'extconf\\.rb',
|
@@ -220,16 +220,15 @@ DEPENDENCIES = {
|
|
220
220
|
|
221
221
|
# Developer Gem dependencies: gemname => version
|
222
222
|
DEVELOPMENT_DEPENDENCIES = {
|
223
|
-
'rake'
|
224
|
-
'rcodetools'
|
225
|
-
'rcov'
|
226
|
-
'
|
227
|
-
'RedCloth'
|
228
|
-
'rspec'
|
229
|
-
'ruby-termios'
|
230
|
-
'text-format'
|
231
|
-
'tmail'
|
232
|
-
'diff-lcs' => '>= 1.1.2',
|
223
|
+
'rake' => '~> 0.8.7',
|
224
|
+
'rcodetools' => '~> 0.7.0.0',
|
225
|
+
'rcov' => '~> 0.8.1.2.0',
|
226
|
+
'yard' => '~> 0.6.1',
|
227
|
+
'RedCloth' => '~> 4.2.3',
|
228
|
+
'rspec' => '~> 2.0.1',
|
229
|
+
'ruby-termios' => '~> 0.9.6',
|
230
|
+
'text-format' => '~> 1.0.0',
|
231
|
+
'tmail' => '~> 1.2.3.1',
|
233
232
|
'tidy-ext' => '>= 0.1.10',
|
234
233
|
'rake-compiler' => '>= 0.7.0',
|
235
234
|
}
|
@@ -251,9 +250,10 @@ GEMSPEC = Gem::Specification.new do |gem|
|
|
251
250
|
"structurally valid XHTML (or HTML).",
|
252
251
|
].join( "\n" )
|
253
252
|
|
254
|
-
gem.authors = "Michael Granger"
|
253
|
+
gem.authors = ["Michael Granger"]
|
255
254
|
gem.email = ["ged@FaerieMUD.org"]
|
256
255
|
gem.homepage = 'http://deveiate.org/projects/BlueCloth/'
|
256
|
+
gem.licenses = ["BSD"]
|
257
257
|
|
258
258
|
gem.has_rdoc = true
|
259
259
|
gem.rdoc_options = RDOC_OPTIONS
|
@@ -275,6 +275,9 @@ GEMSPEC = Gem::Specification.new do |gem|
|
|
275
275
|
gem.signing_key = '/Volumes/Keys/ged-private_gem_key.pem'
|
276
276
|
gem.cert_chain = [File.expand_path('~/.gem/ged-public_gem_cert.pem')]
|
277
277
|
|
278
|
+
|
279
|
+
gem.required_ruby_version = '>= 1.8.7'
|
280
|
+
|
278
281
|
DEPENDENCIES.each do |name, version|
|
279
282
|
version = '>= 0' if version.length.zero?
|
280
283
|
gem.add_runtime_dependency( name, version )
|
data/ext/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.4
|
data/ext/bluecloth.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* BlueCloth -- a Ruby implementation of Markdown
|
3
|
-
* $Id: bluecloth.c,v
|
3
|
+
* $Id: bluecloth.c,v a12b01a92197 2011/01/17 17:13:22 ged $
|
4
4
|
*
|
5
5
|
* = Authors
|
6
6
|
*
|
@@ -185,8 +185,9 @@ static VALUE
|
|
185
185
|
bluecloth_initialize( int argc, VALUE *argv, VALUE self ) {
|
186
186
|
if ( !bluecloth_check_ptr(self) ) {
|
187
187
|
MMIOT *document;
|
188
|
-
VALUE text,
|
188
|
+
VALUE text, optflags, fullhash, opthash = Qnil;
|
189
189
|
int flags = 0;
|
190
|
+
VALUE utf8text = Qnil;
|
190
191
|
|
191
192
|
rb_scan_args( argc, argv, "02", &text, &opthash );
|
192
193
|
|
@@ -254,12 +255,12 @@ bluecloth_to_html( VALUE self ) {
|
|
254
255
|
if ( (length = mkd_document( document, &output )) != EOF ) {
|
255
256
|
#ifdef M17N_SUPPORTED
|
256
257
|
VALUE orig_encoding = rb_obj_encoding( rb_iv_get(self, "@text") );
|
257
|
-
VALUE utf8_result = rb_enc_str_new( output,
|
258
|
+
VALUE utf8_result = rb_enc_str_new( output, strlen(output), rb_utf8_encoding() );
|
258
259
|
result = rb_str_encode( utf8_result, orig_encoding, 0, Qnil );
|
259
260
|
bluecloth_debug( "Bytes after un-utf8ification (if necessary): %s",
|
260
261
|
RSTRING_PTR(rb_funcall(result, rb_intern("dump"), 0, Qnil)) );
|
261
262
|
#else
|
262
|
-
result =
|
263
|
+
result = rb_str_new2( output );
|
263
264
|
#endif /* M17N_SUPPORTED */
|
264
265
|
|
265
266
|
OBJ_INFECT( result, self );
|
@@ -371,6 +372,15 @@ void Init_bluecloth_ext( void ) {
|
|
371
372
|
/* don't allow pseudo-protocols */
|
372
373
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NO_EXT", INT2FIX(MKD_NO_EXT) );
|
373
374
|
|
375
|
+
/* Generate code for xml ![CDATA[...]] */
|
376
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_CDATA", INT2FIX(MKD_CDATA) );
|
377
|
+
|
378
|
+
/* Don't use superscript extension */
|
379
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NOSUPERSCRIPT", INT2FIX(MKD_NOSUPERSCRIPT) );
|
380
|
+
|
381
|
+
/* Relaxed emphasis -- emphasis happens everywhere */
|
382
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NORELAXED", INT2FIX(MKD_NORELAXED) );
|
383
|
+
|
374
384
|
/* disallow tables */
|
375
385
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NOTABLES", INT2FIX(MKD_NOTABLES) );
|
376
386
|
|
@@ -392,10 +402,21 @@ void Init_bluecloth_ext( void ) {
|
|
392
402
|
/* Be paranoid about link protocols */
|
393
403
|
rb_define_const( bluecloth_cBlueCloth, "MKD_SAFELINK", INT2FIX(MKD_SAFELINK) );
|
394
404
|
|
395
|
-
|
396
405
|
/* don't process header blocks */
|
397
406
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NOHEADER", INT2FIX(MKD_NOHEADER) );
|
398
407
|
|
408
|
+
/* Expand tabs to 4 spaces */
|
409
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_TABSTOP", INT2FIX(MKD_TABSTOP) );
|
410
|
+
|
411
|
+
/* Forbid '>%class%' blocks */
|
412
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NODIVQUOTE", INT2FIX(MKD_NODIVQUOTE) );
|
413
|
+
|
414
|
+
/* Forbid alphabetic lists */
|
415
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NOALPHALIST", INT2FIX(MKD_NOALPHALIST) );
|
416
|
+
|
417
|
+
/* Forbid definition lists */
|
418
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NODLIST", INT2FIX(MKD_NODLIST) );
|
419
|
+
|
399
420
|
|
400
421
|
/* Make sure the Ruby side is loaded */
|
401
422
|
rb_require( "bluecloth" );
|
data/ext/config.h
CHANGED
@@ -1,11 +1,22 @@
|
|
1
1
|
/*
|
2
|
-
*
|
3
|
-
* by ged@tenar.home.faeriemud.org
|
2
|
+
* Hacked-up version of the config file generated by discount
|
4
3
|
*/
|
5
4
|
|
6
5
|
#ifndef CONFIG_H_RZLE3ADO
|
7
6
|
#define CONFIG_H_RZLE3ADO
|
8
7
|
|
8
|
+
#include "extconf.h"
|
9
|
+
|
10
|
+
#if SIZEOF_LONG == 8
|
11
|
+
# define DWORD unsigned int
|
12
|
+
# define WORD unsigned short
|
13
|
+
#else
|
14
|
+
# define DWORD unsigned long
|
15
|
+
# define WORD unsigned int
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#define BYTE unsigned char
|
19
|
+
|
9
20
|
#ifdef RUBY_EXTCONF_H
|
10
21
|
# include RUBY_EXTCONF_H
|
11
22
|
#endif
|
data/ext/css.c
CHANGED
@@ -28,9 +28,10 @@ stylesheets(Paragraph *p, Cstring *f)
|
|
28
28
|
|
29
29
|
for ( ; p ; p = p->next ) {
|
30
30
|
if ( p->typ == STYLE ) {
|
31
|
-
for ( q = p->text; q ; q = q->next )
|
31
|
+
for ( q = p->text; q ; q = q->next ) {
|
32
32
|
Cswrite(f, T(q->text), S(q->text));
|
33
33
|
Csputc('\n', f);
|
34
|
+
}
|
34
35
|
}
|
35
36
|
if ( p->down )
|
36
37
|
stylesheets(p->down, f);
|
@@ -44,17 +45,25 @@ int
|
|
44
45
|
mkd_css(Document *d, char **res)
|
45
46
|
{
|
46
47
|
Cstring f;
|
48
|
+
int size;
|
47
49
|
|
48
|
-
if ( res &&
|
50
|
+
if ( res && d && d->compiled ) {
|
51
|
+
*res = 0;
|
49
52
|
CREATE(f);
|
50
53
|
RESERVE(f, 100);
|
51
54
|
stylesheets(d->code, &f);
|
52
55
|
|
56
|
+
if ( (size = S(f)) > 0 ) {
|
57
|
+
EXPAND(f) = 0;
|
53
58
|
/* HACK ALERT! HACK ALERT! HACK ALERT! */
|
54
|
-
|
59
|
+
*res = T(f);/* we know that a T(Cstring) is a character pointer */
|
55
60
|
/* so we can simply pick it up and carry it away, */
|
56
|
-
|
61
|
+
/* leaving the husk of the Ctring on the stack */
|
57
62
|
/* END HACK ALERT */
|
63
|
+
}
|
64
|
+
else
|
65
|
+
DELETE(f);
|
66
|
+
return size;
|
58
67
|
}
|
59
68
|
return EOF;
|
60
69
|
}
|
@@ -69,7 +78,7 @@ mkd_generatecss(Document *d, FILE *f)
|
|
69
78
|
int written = EOF, size = mkd_css(d, &res);
|
70
79
|
|
71
80
|
if ( size > 0 )
|
72
|
-
written = fwrite(res,
|
81
|
+
written = fwrite(res, 1, size, f);
|
73
82
|
if ( res )
|
74
83
|
free(res);
|
75
84
|
return (written == size) ? size : EOF;
|
data/ext/cstring.h
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
*/
|
19
19
|
#define STRING(type) struct { type *text; int size, alloc; }
|
20
20
|
|
21
|
-
#define CREATE(x) T(x) = (void*)(S(x) = (x).alloc = 0)
|
21
|
+
#define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) )
|
22
22
|
#define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \
|
23
23
|
? (T(x)) \
|
24
24
|
: (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \
|
data/ext/docheader.c
CHANGED
@@ -14,13 +14,19 @@
|
|
14
14
|
#include "markdown.h"
|
15
15
|
#include "amalloc.h"
|
16
16
|
|
17
|
-
|
17
|
+
static char *
|
18
|
+
onlyifset(Line *l)
|
19
|
+
{
|
20
|
+
char *ret = T(l->text) + l->dle;
|
21
|
+
|
22
|
+
return ret[0] ? ret : 0;
|
23
|
+
}
|
18
24
|
|
19
25
|
char *
|
20
26
|
mkd_doc_title(Document *doc)
|
21
27
|
{
|
22
|
-
if ( doc && doc->
|
23
|
-
return
|
28
|
+
if ( doc && doc->title )
|
29
|
+
return onlyifset(doc->title);
|
24
30
|
return 0;
|
25
31
|
}
|
26
32
|
|
@@ -28,8 +34,8 @@ mkd_doc_title(Document *doc)
|
|
28
34
|
char *
|
29
35
|
mkd_doc_author(Document *doc)
|
30
36
|
{
|
31
|
-
if ( doc && doc->
|
32
|
-
return
|
37
|
+
if ( doc && doc->author )
|
38
|
+
return onlyifset(doc->author);
|
33
39
|
return 0;
|
34
40
|
}
|
35
41
|
|
@@ -37,7 +43,7 @@ mkd_doc_author(Document *doc)
|
|
37
43
|
char *
|
38
44
|
mkd_doc_date(Document *doc)
|
39
45
|
{
|
40
|
-
if ( doc && doc->
|
41
|
-
return
|
46
|
+
if ( doc && doc->date )
|
47
|
+
return onlyifset(doc->date);
|
42
48
|
return 0;
|
43
49
|
}
|
data/ext/emmatch.c
CHANGED
@@ -163,7 +163,7 @@ emblock(MMIOT *f, int first, int last)
|
|
163
163
|
} /* emblock */
|
164
164
|
|
165
165
|
|
166
|
-
/* ___mkd_emblock() -- emblock a string of blocks, then
|
166
|
+
/* ___mkd_emblock() -- emblock a string of blocks, then concatenate the
|
167
167
|
* resulting text onto f->out.
|
168
168
|
*/
|
169
169
|
void
|
data/ext/generate.c
CHANGED
@@ -351,6 +351,53 @@ linkysize(MMIOT *f, Footnote *ref)
|
|
351
351
|
}
|
352
352
|
|
353
353
|
|
354
|
+
/* extract a <...>-encased url from the input stream.
|
355
|
+
* (markdown 1.0.2b8 compatibility; older versions
|
356
|
+
* of markdown treated the < and > as syntactic
|
357
|
+
* sugar that didn't have to be there. 1.0.2b8
|
358
|
+
* requires a closing >, and then falls into the
|
359
|
+
* title or closing )
|
360
|
+
*/
|
361
|
+
static int
|
362
|
+
linkybroket(MMIOT *f, int image, Footnote *p)
|
363
|
+
{
|
364
|
+
int c;
|
365
|
+
int good = 0;
|
366
|
+
|
367
|
+
T(p->link) = cursor(f);
|
368
|
+
for ( S(p->link)=0; (c = pull(f)) != '>'; ++S(p->link) ) {
|
369
|
+
/* pull in all input until a '>' is found, or die trying.
|
370
|
+
*/
|
371
|
+
if ( c == EOF )
|
372
|
+
return 0;
|
373
|
+
else if ( (c == '\\') && ispunct(peek(f,2)) ) {
|
374
|
+
++S(p->link);
|
375
|
+
pull(f);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
|
379
|
+
c = eatspace(f);
|
380
|
+
|
381
|
+
/* next nonspace needs to be a title, a size, or )
|
382
|
+
*/
|
383
|
+
if ( ( c == '\'' || c == '"' ) && linkytitle(f,c,p) )
|
384
|
+
good=1;
|
385
|
+
else if ( image && (c == '=') && linkysize(f,p) )
|
386
|
+
good=1;
|
387
|
+
else
|
388
|
+
good=( c == ')' );
|
389
|
+
|
390
|
+
if ( good ) {
|
391
|
+
if ( peek(f, 1) == ')' )
|
392
|
+
pull(f);
|
393
|
+
|
394
|
+
___mkd_tidy(&p->link);
|
395
|
+
}
|
396
|
+
|
397
|
+
return good;
|
398
|
+
} /* linkybroket */
|
399
|
+
|
400
|
+
|
354
401
|
/* extract a (-prefixed url from the input stream.
|
355
402
|
* the label is either of the format `<link>`, where I
|
356
403
|
* extract until I find a >, or it is of the format
|
@@ -368,6 +415,8 @@ linkyurl(MMIOT *f, int image, Footnote *p)
|
|
368
415
|
|
369
416
|
if ( c == '<' ) {
|
370
417
|
pull(f);
|
418
|
+
if ( !(f->flags & MKD_1_COMPAT) )
|
419
|
+
return linkybroket(f,image,p);
|
371
420
|
mayneedtotrim=1;
|
372
421
|
}
|
373
422
|
|
@@ -405,10 +454,10 @@ static struct _protocol {
|
|
405
454
|
int nlen;
|
406
455
|
} protocol[] = {
|
407
456
|
#define _aprotocol(x) { x, (sizeof x)-1 }
|
408
|
-
_aprotocol( "https
|
409
|
-
_aprotocol( "http
|
410
|
-
_aprotocol( "news
|
411
|
-
_aprotocol( "ftp
|
457
|
+
_aprotocol( "https:" ),
|
458
|
+
_aprotocol( "http:" ),
|
459
|
+
_aprotocol( "news:" ),
|
460
|
+
_aprotocol( "ftp:" ),
|
412
461
|
#undef _aprotocol
|
413
462
|
};
|
414
463
|
#define NRPROTOCOLS (sizeof protocol / sizeof protocol[0])
|
@@ -445,9 +494,9 @@ typedef struct linkytype {
|
|
445
494
|
} linkytype;
|
446
495
|
|
447
496
|
static linkytype imaget = { 0, 0, "<img src=\"", "\"",
|
448
|
-
1, " alt=\"", "\" />",
|
497
|
+
1, " alt=\"", "\" />", MKD_NOIMAGE|MKD_TAGTEXT, IS_URL };
|
449
498
|
static linkytype linkt = { 0, 0, "<a href=\"", "\"",
|
450
|
-
0, ">", "</a>",
|
499
|
+
0, ">", "</a>", MKD_NOLINKS, IS_URL };
|
451
500
|
|
452
501
|
/*
|
453
502
|
* pseudo-protocols for [][];
|
@@ -457,8 +506,8 @@ static linkytype linkt = { 0, 0, "<a href=\"", "\"",
|
|
457
506
|
* raw: just dump the link without any processing
|
458
507
|
*/
|
459
508
|
static linkytype specials[] = {
|
460
|
-
{ "id:", 3, "<
|
461
|
-
{ "raw:", 4, 0, 0, 0, 0, 0,
|
509
|
+
{ "id:", 3, "<span id=\"", "\"", 0, ">", "</span>", 0, 0 },
|
510
|
+
{ "raw:", 4, 0, 0, 0, 0, 0, MKD_NOHTML, 0 },
|
462
511
|
{ "lang:", 5, "<span lang=\"", "\"", 0, ">", "</span>", 0, 0 },
|
463
512
|
{ "abbr:", 5, "<abbr title=\"", "\"", 0, ">", "</abbr>", 0, 0 },
|
464
513
|
{ "class:", 6, "<span class=\"", "\"", 0, ">", "</span>", 0, 0 },
|
@@ -489,10 +538,13 @@ printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
|
|
489
538
|
{
|
490
539
|
char *edit;
|
491
540
|
|
541
|
+
if ( f->flags & IS_LABEL )
|
542
|
+
return;
|
543
|
+
|
492
544
|
Qstring(tag->link_pfx, f);
|
493
545
|
|
494
546
|
if ( tag->kind & IS_URL ) {
|
495
|
-
if ( f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) {
|
547
|
+
if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) {
|
496
548
|
puturl(edit, strlen(edit), f, 0);
|
497
549
|
if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data);
|
498
550
|
}
|
@@ -500,11 +552,11 @@ printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
|
|
500
552
|
puturl(link + tag->szpat, size - tag->szpat, f, 0);
|
501
553
|
}
|
502
554
|
else
|
503
|
-
___mkd_reparse(link + tag->szpat, size - tag->szpat,
|
555
|
+
___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f);
|
504
556
|
|
505
557
|
Qstring(tag->link_sfx, f);
|
506
558
|
|
507
|
-
if ( f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) {
|
559
|
+
if ( f->cb && f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) {
|
508
560
|
Qchar(' ', f);
|
509
561
|
Qstring(edit, f);
|
510
562
|
if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data);
|
@@ -522,13 +574,13 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
|
|
522
574
|
if ( image )
|
523
575
|
tag = &imaget;
|
524
576
|
else if ( tag = pseudo(ref->link) ) {
|
525
|
-
if ( f->flags & (
|
577
|
+
if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) )
|
526
578
|
return 0;
|
527
579
|
}
|
528
|
-
else if ( (f->flags &
|
529
|
-
|
530
|
-
|
531
|
-
/* if
|
580
|
+
else if ( (f->flags & MKD_SAFELINK) && T(ref->link)
|
581
|
+
&& (T(ref->link)[0] != '/')
|
582
|
+
&& !isautoprefix(T(ref->link), S(ref->link)) )
|
583
|
+
/* if MKD_SAFELINK, only accept links that are local or
|
532
584
|
* a well-known protocol
|
533
585
|
*/
|
534
586
|
return 0;
|
@@ -538,7 +590,9 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
|
|
538
590
|
if ( f->flags & tag->flags )
|
539
591
|
return 0;
|
540
592
|
|
541
|
-
if (
|
593
|
+
if ( f->flags & IS_LABEL )
|
594
|
+
___mkd_reparse(T(text), S(text), tag->flags, f);
|
595
|
+
else if ( tag->link_pfx ) {
|
542
596
|
printlinkyref(f, tag, T(ref->link), S(ref->link));
|
543
597
|
|
544
598
|
if ( tag->WxH ) {
|
@@ -548,7 +602,7 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
|
|
548
602
|
|
549
603
|
if ( S(ref->title) ) {
|
550
604
|
Qstring(" title=\"", f);
|
551
|
-
___mkd_reparse(T(ref->title), S(ref->title),
|
605
|
+
___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f);
|
552
606
|
Qchar('"', f);
|
553
607
|
}
|
554
608
|
|
@@ -587,7 +641,10 @@ linkylinky(int image, MMIOT *f)
|
|
587
641
|
else {
|
588
642
|
int goodlink, implicit_mark = mmiottell(f);
|
589
643
|
|
590
|
-
if (
|
644
|
+
if ( isspace(peek(f,1)) )
|
645
|
+
pull(f);
|
646
|
+
|
647
|
+
if ( peek(f,1) == '[' ) {
|
591
648
|
pull(f); /* consume leading '[' */
|
592
649
|
goodlink = linkylabel(f, &key.tag);
|
593
650
|
}
|
@@ -609,6 +666,8 @@ linkylinky(int image, MMIOT *f)
|
|
609
666
|
if ( ref = bsearch(&key, T(*f->footnotes), S(*f->footnotes),
|
610
667
|
sizeof key, (stfu)__mkd_footsort) )
|
611
668
|
status = linkyformat(f, name, image, ref);
|
669
|
+
else if ( f->flags & IS_LABEL )
|
670
|
+
status = linkyformat(f, name, image, &imaget);
|
612
671
|
}
|
613
672
|
}
|
614
673
|
}
|
@@ -744,19 +803,19 @@ codespan(MMIOT *f, int size)
|
|
744
803
|
|
745
804
|
|
746
805
|
/* before letting a tag through, validate against
|
747
|
-
*
|
806
|
+
* MKD_NOLINKS and MKD_NOIMAGE
|
748
807
|
*/
|
749
808
|
static int
|
750
809
|
forbidden_tag(MMIOT *f)
|
751
810
|
{
|
752
811
|
int c = toupper(peek(f, 1));
|
753
812
|
|
754
|
-
if ( f->flags &
|
813
|
+
if ( f->flags & MKD_NOHTML )
|
755
814
|
return 1;
|
756
815
|
|
757
|
-
if ( c == 'A' && (f->flags &
|
816
|
+
if ( c == 'A' && (f->flags & MKD_NOLINKS) && !isthisalnum(f,2) )
|
758
817
|
return 1;
|
759
|
-
if ( c == 'I' && (f->flags &
|
818
|
+
if ( c == 'I' && (f->flags & MKD_NOIMAGE)
|
760
819
|
&& strncasecmp(cursor(f)+1, "MG", 2) == 0
|
761
820
|
&& !isthisalnum(f,4) )
|
762
821
|
return 1;
|
@@ -803,7 +862,7 @@ process_possible_link(MMIOT *f, int size)
|
|
803
862
|
int mailto = 0;
|
804
863
|
char *text = cursor(f);
|
805
864
|
|
806
|
-
if ( f->flags &
|
865
|
+
if ( f->flags & MKD_NOLINKS ) return 0;
|
807
866
|
|
808
867
|
if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) {
|
809
868
|
/* if it says it's a mailto, it's a mailto -- who am
|
@@ -850,7 +909,7 @@ maybe_tag_or_link(MMIOT *f)
|
|
850
909
|
int c, size;
|
851
910
|
int maybetag = 1;
|
852
911
|
|
853
|
-
if ( f->flags &
|
912
|
+
if ( f->flags & MKD_TAGTEXT )
|
854
913
|
return 0;
|
855
914
|
|
856
915
|
for ( size=0; (c = peek(f, size+1)) != '>'; size++) {
|
@@ -1013,7 +1072,7 @@ smartypants(int c, int *flags, MMIOT *f)
|
|
1013
1072
|
{
|
1014
1073
|
int i;
|
1015
1074
|
|
1016
|
-
if ( f->flags & (
|
1075
|
+
if ( f->flags & (MKD_NOPANTS|MKD_TAGTEXT|IS_LABEL) )
|
1017
1076
|
return 0;
|
1018
1077
|
|
1019
1078
|
for ( i=0; i < NRSMART; i++)
|
@@ -1081,7 +1140,7 @@ tickhandler(MMIOT *f, int tickchar, int minticks, spanhandler spanner)
|
|
1081
1140
|
return 0;
|
1082
1141
|
}
|
1083
1142
|
|
1084
|
-
#define tag_text(f) (f->flags &
|
1143
|
+
#define tag_text(f) (f->flags & MKD_TAGTEXT)
|
1085
1144
|
|
1086
1145
|
|
1087
1146
|
static void
|
@@ -1092,7 +1151,7 @@ text(MMIOT *f)
|
|
1092
1151
|
int smartyflags = 0;
|
1093
1152
|
|
1094
1153
|
while (1) {
|
1095
|
-
if ( (f->flags &
|
1154
|
+
if ( (f->flags & MKD_AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) )
|
1096
1155
|
maybe_autolink(f);
|
1097
1156
|
|
1098
1157
|
c = pull(f);
|
@@ -1131,32 +1190,48 @@ text(MMIOT *f)
|
|
1131
1190
|
case '[': if ( tag_text(f) || !linkylinky(0, f) )
|
1132
1191
|
Qchar(c, f);
|
1133
1192
|
break;
|
1134
|
-
#if SUPERSCRIPT
|
1135
1193
|
/* A^B -> A<sup>B</sup> */
|
1136
|
-
case '^': if ( (f->flags & (
|
1194
|
+
case '^': if ( (f->flags & (MKD_NOSUPERSCRIPT|MKD_STRICT|MKD_TAGTEXT))
|
1195
|
+
|| (isthisnonword(f,-1) && peek(f,-1) != ')')
|
1196
|
+
|| isthisspace(f,1) )
|
1137
1197
|
Qchar(c,f);
|
1138
1198
|
else {
|
1139
1199
|
char *sup = cursor(f);
|
1140
1200
|
int len = 0;
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1201
|
+
|
1202
|
+
if ( peek(f,1) == '(' ) {
|
1203
|
+
int here = mmiottell(f);
|
1204
|
+
pull(f);
|
1205
|
+
|
1206
|
+
if ( (len = parenthetical('(',')',f)) <= 0 ) {
|
1207
|
+
mmiotseek(f,here);
|
1208
|
+
Qchar(c, f);
|
1209
|
+
break;
|
1210
|
+
}
|
1211
|
+
sup++;
|
1212
|
+
}
|
1213
|
+
else {
|
1214
|
+
while ( isthisalnum(f,1+len) )
|
1215
|
+
++len;
|
1216
|
+
if ( !len ) {
|
1217
|
+
Qchar(c,f);
|
1218
|
+
break;
|
1219
|
+
}
|
1220
|
+
shift(f,len);
|
1144
1221
|
}
|
1145
|
-
|
1222
|
+
Qstring("<sup>",f);
|
1146
1223
|
___mkd_reparse(sup, len, 0, f);
|
1147
1224
|
Qstring("</sup>", f);
|
1148
1225
|
}
|
1149
1226
|
break;
|
1150
|
-
#endif
|
1151
1227
|
case '_':
|
1152
|
-
#if RELAXED_EMPHASIS
|
1153
1228
|
/* Underscores don't count if they're in the middle of a word */
|
1154
|
-
if ( !(f->flags &
|
1155
|
-
|
1229
|
+
if ( !(f->flags & (MKD_NORELAXED|MKD_STRICT))
|
1230
|
+
&& isthisalnum(f,-1)
|
1231
|
+
&& isthisalnum(f,1) ) {
|
1156
1232
|
Qchar(c, f);
|
1157
1233
|
break;
|
1158
1234
|
}
|
1159
|
-
#endif
|
1160
1235
|
case '*':
|
1161
1236
|
/* Underscores & stars don't count if they're out in the middle
|
1162
1237
|
* of whitespace */
|
@@ -1174,7 +1249,7 @@ text(MMIOT *f)
|
|
1174
1249
|
}
|
1175
1250
|
break;
|
1176
1251
|
|
1177
|
-
case '~': if ( (f->flags & (
|
1252
|
+
case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || !tickhandler(f,c,2,delspan) )
|
1178
1253
|
Qchar(c, f);
|
1179
1254
|
break;
|
1180
1255
|
|
@@ -1187,6 +1262,14 @@ text(MMIOT *f)
|
|
1187
1262
|
break;
|
1188
1263
|
case '<': Qstring("<", f);
|
1189
1264
|
break;
|
1265
|
+
case '^': if ( f->flags & (MKD_STRICT|MKD_NOSUPERSCRIPT) ) {
|
1266
|
+
Qchar('\\', f);
|
1267
|
+
shift(f,-1);
|
1268
|
+
break;
|
1269
|
+
}
|
1270
|
+
Qchar(c, f);
|
1271
|
+
break;
|
1272
|
+
|
1190
1273
|
case '>': case '#': case '.': case '-':
|
1191
1274
|
case '+': case '{': case '}': case ']':
|
1192
1275
|
case '!': case '[': case '*': case '_':
|
@@ -1230,9 +1313,9 @@ static void
|
|
1230
1313
|
printheader(Paragraph *pp, MMIOT *f)
|
1231
1314
|
{
|
1232
1315
|
Qprintf(f, "<h%d", pp->hnumber);
|
1233
|
-
if ( f->flags &
|
1316
|
+
if ( f->flags & MKD_TOC ) {
|
1234
1317
|
Qprintf(f, " id=\"", pp->hnumber);
|
1235
|
-
mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Qchar, f);
|
1318
|
+
mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Qchar, f, 1);
|
1236
1319
|
Qchar('"', f);
|
1237
1320
|
}
|
1238
1321
|
Qchar('>', f);
|
@@ -1432,7 +1515,6 @@ htmlify(Paragraph *p, char *block, char *arguments, MMIOT *f)
|
|
1432
1515
|
}
|
1433
1516
|
|
1434
1517
|
|
1435
|
-
#if DL_TAG_EXTENSION
|
1436
1518
|
static void
|
1437
1519
|
definitionlist(Paragraph *p, MMIOT *f)
|
1438
1520
|
{
|
@@ -1455,7 +1537,6 @@ definitionlist(Paragraph *p, MMIOT *f)
|
|
1455
1537
|
Qstring("</dl>", f);
|
1456
1538
|
}
|
1457
1539
|
}
|
1458
|
-
#endif
|
1459
1540
|
|
1460
1541
|
|
1461
1542
|
static void
|
@@ -1464,7 +1545,7 @@ listdisplay(int typ, Paragraph *p, MMIOT* f)
|
|
1464
1545
|
if ( p ) {
|
1465
1546
|
Qprintf(f, "<%cl", (typ==UL)?'u':'o');
|
1466
1547
|
if ( typ == AL )
|
1467
|
-
Qprintf(f, " type
|
1548
|
+
Qprintf(f, " type=\"a\"");
|
1468
1549
|
Qprintf(f, ">\n");
|
1469
1550
|
|
1470
1551
|
for ( ; p ; p = p->next ) {
|
@@ -1507,11 +1588,9 @@ display(Paragraph *p, MMIOT *f)
|
|
1507
1588
|
listdisplay(p->typ, p->down, f);
|
1508
1589
|
break;
|
1509
1590
|
|
1510
|
-
#if DL_TAG_EXTENSION
|
1511
1591
|
case DL:
|
1512
1592
|
definitionlist(p->down, f);
|
1513
1593
|
break;
|
1514
|
-
#endif
|
1515
1594
|
|
1516
1595
|
case HR:
|
1517
1596
|
Qstring("<hr />", f);
|
@@ -1543,14 +1622,21 @@ display(Paragraph *p, MMIOT *f)
|
|
1543
1622
|
int
|
1544
1623
|
mkd_document(Document *p, char **res)
|
1545
1624
|
{
|
1625
|
+
int size;
|
1626
|
+
|
1546
1627
|
if ( p && p->compiled ) {
|
1547
1628
|
if ( ! p->html ) {
|
1548
1629
|
htmlify(p->code, 0, 0, p->ctx);
|
1549
1630
|
p->html = 1;
|
1550
1631
|
}
|
1551
1632
|
|
1633
|
+
size = S(p->ctx->out);
|
1634
|
+
|
1635
|
+
if ( (size == 0) || T(p->ctx->out)[size-1] )
|
1636
|
+
EXPAND(p->ctx->out) = 0;
|
1637
|
+
|
1552
1638
|
*res = T(p->ctx->out);
|
1553
|
-
return
|
1639
|
+
return size;
|
1554
1640
|
}
|
1555
1641
|
return EOF;
|
1556
1642
|
}
|