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.
Files changed (47) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +29 -2
  3. data/Rakefile +18 -15
  4. data/ext/VERSION +1 -1
  5. data/ext/bluecloth.c +26 -5
  6. data/ext/config.h +13 -2
  7. data/ext/css.c +14 -5
  8. data/ext/cstring.h +1 -1
  9. data/ext/docheader.c +13 -7
  10. data/ext/emmatch.c +1 -1
  11. data/ext/generate.c +134 -48
  12. data/ext/markdown.c +207 -94
  13. data/ext/markdown.h +37 -28
  14. data/ext/mkdio.c +39 -32
  15. data/ext/mkdio.h +34 -24
  16. data/ext/resource.c +3 -1
  17. data/ext/setup.c +47 -0
  18. data/ext/tags.c +15 -2
  19. data/ext/tags.h +1 -0
  20. data/lib/bluecloth.rb +65 -40
  21. data/rake/documentation.rb +9 -1
  22. data/rake/hg.rb +34 -3
  23. data/rake/packaging.rb +1 -1
  24. data/rake/publishing.rb +2 -9
  25. data/rake/testing.rb +53 -88
  26. data/spec/bluecloth/101_changes_spec.rb +17 -17
  27. data/spec/bluecloth/autolinks_spec.rb +1 -1
  28. data/spec/bluecloth/blockquotes_spec.rb +18 -18
  29. data/spec/bluecloth/code_spans_spec.rb +1 -1
  30. data/spec/bluecloth/emphasis_spec.rb +1 -1
  31. data/spec/bluecloth/entities_spec.rb +1 -1
  32. data/spec/bluecloth/hrules_spec.rb +1 -1
  33. data/spec/bluecloth/images_spec.rb +1 -1
  34. data/spec/bluecloth/inline_html_spec.rb +1 -1
  35. data/spec/bluecloth/links_spec.rb +1 -1
  36. data/spec/bluecloth/lists_spec.rb +1 -1
  37. data/spec/bluecloth/paragraphs_spec.rb +1 -1
  38. data/spec/bluecloth/titles_spec.rb +1 -1
  39. data/spec/bluecloth_spec.rb +13 -13
  40. data/spec/bugfix_spec.rb +6 -1
  41. data/spec/contributions_spec.rb +1 -1
  42. data/spec/discount_spec.rb +2 -2
  43. data/spec/lib/helpers.rb +1 -124
  44. data/spec/lib/matchers.rb +1 -1
  45. data/spec/markdowntest_spec.rb +1 -1
  46. metadata +10 -10
  47. metadata.gz.sig +0 -0
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,4 +1,31 @@
1
- 138[tip] 486a5a2a8cd2 2010-09-23 07:15 -0700 ged
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-2010 The FaerieMUD Consortium
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 = "pre%03d" % [(id.chomp[ /^[[:xdigit:]]+/ ] || '1')]
177
+ PKG_BUILD = (id.chomp[ /^[[:xdigit:]]+/ ] || '1')
177
178
  else
178
- PKG_BUILD = 'pre000'
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' => '>= 0.8.7',
224
- 'rcodetools' => '>= 0.7.0.0',
225
- 'rcov' => '>= 0.8.1.2.0',
226
- 'rdoc' => '>= 2.4.3',
227
- 'RedCloth' => '>= 4.0.3',
228
- 'rspec' => '>= 1.2.6',
229
- 'ruby-termios' => '>= 0.9.6',
230
- 'text-format' => '>= 1.0.0',
231
- 'tmail' => '>= 1.2.3.1',
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 )
@@ -1 +1 @@
1
- 1.6.8
1
+ 2.0.4
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * BlueCloth -- a Ruby implementation of Markdown
3
- * $Id: bluecloth.c,v 1caa0c888dfe 2010/09/17 22:03:06 ged $
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, utf8text, optflags, fullhash, opthash = Qnil;
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, length, rb_utf8_encoding() );
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 = rb_str_new( output, length );
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" );
@@ -1,11 +1,22 @@
1
1
  /*
2
- * configuration for markdown, generated Tue Dec 23 06:19:25 PST 2008
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 && *res && d && d->compiled ) {
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
- *res = T(f); /* we know that a T(Cstring) is a character pointer */
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
- return S(f); /* leaving the husk of the Ctring on the stack */
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, size, 1, f);
81
+ written = fwrite(res, 1, size, f);
73
82
  if ( res )
74
83
  free(res);
75
84
  return (written == size) ? size : EOF;
@@ -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)) \
@@ -14,13 +14,19 @@
14
14
  #include "markdown.h"
15
15
  #include "amalloc.h"
16
16
 
17
- #define afterdle(t) (T((t)->text) + (t)->dle)
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->headers )
23
- return afterdle(doc->headers);
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->headers && doc->headers->next )
32
- return afterdle(doc->headers->next);
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->headers && doc->headers->next && doc->headers->next->next )
41
- return afterdle(doc->headers->next->next);
46
+ if ( doc && doc->date )
47
+ return onlyifset(doc->date);
42
48
  return 0;
43
49
  }
@@ -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 concatinate the
166
+ /* ___mkd_emblock() -- emblock a string of blocks, then concatenate the
167
167
  * resulting text onto f->out.
168
168
  */
169
169
  void
@@ -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=\"", "\" />", DENY_IMG|INSIDE_TAG, IS_URL };
497
+ 1, " alt=\"", "\" />", MKD_NOIMAGE|MKD_TAGTEXT, IS_URL };
449
498
  static linkytype linkt = { 0, 0, "<a href=\"", "\"",
450
- 0, ">", "</a>", DENY_A, IS_URL };
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, "<a id=\"", "\"", 0, ">", "</a>", 0, IS_URL },
461
- { "raw:", 4, 0, 0, 0, 0, 0, DENY_HTML, 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, INSIDE_TAG, f);
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 & (NO_PSEUDO_PROTO|SAFELINK) )
577
+ if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) )
526
578
  return 0;
527
579
  }
528
- else if ( (f->flags & SAFELINK) && T(ref->link)
529
- && (T(ref->link)[0] != '/')
530
- && !isautoprefix(T(ref->link), S(ref->link)) )
531
- /* if SAFELINK, only accept links that are local or
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 ( tag->link_pfx ) {
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), INSIDE_TAG, f);
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 ( eatspace(f) == '[' ) {
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
- * DENY_A and DENY_IMG
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 & DENY_HTML )
813
+ if ( f->flags & MKD_NOHTML )
755
814
  return 1;
756
815
 
757
- if ( c == 'A' && (f->flags & DENY_A) && !isthisalnum(f,2) )
816
+ if ( c == 'A' && (f->flags & MKD_NOLINKS) && !isthisalnum(f,2) )
758
817
  return 1;
759
- if ( c == 'I' && (f->flags & DENY_IMG)
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 & DENY_A ) return 0;
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 & INSIDE_TAG )
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 & (DENY_SMARTY|INSIDE_TAG) )
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 & INSIDE_TAG)
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 & AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) )
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 & (STRICT|INSIDE_TAG)) || isthisspace(f,-1) || isthisspace(f,1) )
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
- Qstring("<sup>",f);
1142
- while ( !isthisspace(f,1+len) ) {
1143
- ++len;
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
- shift(f,len);
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 & STRICT) && isthisalnum(f,-1)
1155
- && isthisalnum(f,1) ) {
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 & (NOSTRIKETHROUGH|INSIDE_TAG|STRICT)) || !tickhandler(f,c,2,delspan) )
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("&lt;", 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 & TOC ) {
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=a");
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 S(p->ctx->out);
1639
+ return size;
1554
1640
  }
1555
1641
  return EOF;
1556
1642
  }