bluecloth 2.0.7-x86-mingw32 → 2.0.11pre158-x86-mingw32

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 (67) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gemtest +0 -0
  3. data/History.md +4 -0
  4. data/LICENSE +1 -1
  5. data/Manifest.txt +103 -0
  6. data/README.md +103 -0
  7. data/Rakefile +95 -301
  8. data/ext/VERSION +1 -1
  9. data/ext/bluecloth.c +69 -23
  10. data/ext/bluecloth.h +13 -2
  11. data/ext/config.h +13 -2
  12. data/ext/css.c +14 -5
  13. data/ext/cstring.h +4 -2
  14. data/ext/docheader.c +13 -7
  15. data/ext/emmatch.c +188 -0
  16. data/ext/extconf.rb +7 -9
  17. data/ext/generate.c +333 -293
  18. data/ext/html5.c +24 -0
  19. data/ext/markdown.c +326 -185
  20. data/ext/markdown.h +52 -29
  21. data/ext/mkdio.c +82 -41
  22. data/ext/mkdio.h +44 -23
  23. data/ext/resource.c +4 -2
  24. data/ext/setup.c +47 -0
  25. data/ext/tags.c +123 -0
  26. data/ext/tags.h +19 -0
  27. data/lib/1.8/bluecloth_ext.so +0 -0
  28. data/lib/1.9/bluecloth_ext.so +0 -0
  29. data/lib/bluecloth.rb +77 -42
  30. data/spec/bluecloth/101_changes_spec.rb +18 -21
  31. data/spec/bluecloth/TEMPLATE +36 -0
  32. data/spec/bluecloth/autolinks_spec.rb +4 -7
  33. data/spec/bluecloth/blockquotes_spec.rb +20 -23
  34. data/spec/bluecloth/code_spans_spec.rb +2 -5
  35. data/spec/bluecloth/emphasis_spec.rb +2 -5
  36. data/spec/bluecloth/entities_spec.rb +2 -5
  37. data/spec/bluecloth/hrules_spec.rb +2 -5
  38. data/spec/bluecloth/images_spec.rb +2 -5
  39. data/spec/bluecloth/inline_html_spec.rb +26 -66
  40. data/spec/bluecloth/links_spec.rb +1 -5
  41. data/spec/bluecloth/lists_spec.rb +2 -5
  42. data/spec/bluecloth/paragraphs_spec.rb +2 -5
  43. data/spec/bluecloth/titles_spec.rb +2 -5
  44. data/spec/bluecloth_spec.rb +36 -22
  45. data/spec/bugfix_spec.rb +90 -10
  46. data/spec/contributions_spec.rb +2 -3
  47. data/spec/discount_spec.rb +50 -10
  48. data/spec/lib/helpers.rb +18 -117
  49. data/spec/lib/matchers.rb +7 -18
  50. data/spec/markdowntest_spec.rb +3 -39
  51. metadata +257 -143
  52. metadata.gz.sig +0 -0
  53. data/ChangeLog +0 -387
  54. data/README +0 -81
  55. data/Rakefile.local +0 -41
  56. data/rake/191_compat.rb +0 -26
  57. data/rake/dependencies.rb +0 -76
  58. data/rake/helpers.rb +0 -435
  59. data/rake/hg.rb +0 -273
  60. data/rake/manual.rb +0 -782
  61. data/rake/packaging.rb +0 -123
  62. data/rake/publishing.rb +0 -274
  63. data/rake/rdoc.rb +0 -30
  64. data/rake/style.rb +0 -62
  65. data/rake/svn.rb +0 -668
  66. data/rake/testing.rb +0 -187
  67. data/rake/verifytask.rb +0 -64
data/ext/extconf.rb CHANGED
@@ -13,19 +13,17 @@ version = versionfile.read.chomp
13
13
  if CONFIG['host_os'].match( 'mswin' )
14
14
  $CFLAGS << ' -I.' << ' -W3' << ' -Zi'
15
15
  else
16
- $CFLAGS << ' -I.' << ' -Wall'
16
+ $CFLAGS << ' -I.'
17
17
  end
18
18
  $CPPFLAGS << %Q{ -DVERSION=\\"#{version}\\"}
19
19
 
20
20
  # Add my own debugging hooks if building for me
21
- if ENV['DEBUGGING_BUILD']
21
+ if ENV['MAINTAINER_MODE']
22
+ $stderr.puts "Maintainer mode enabled."
23
+ $CFLAGS << ' -Wall'
22
24
  $CFLAGS << ' -ggdb' << ' -DDEBUG'
23
25
  end
24
26
 
25
- def fail( *messages )
26
- $stderr.puts( *messages )
27
- exit( 1 )
28
- end
29
27
 
30
28
  # Stuff from configure.sh
31
29
  have_func( "srand" ) || have_func( "srandom" )
@@ -35,13 +33,13 @@ have_func( "random" ) || have_func( "rand" )
35
33
  have_func( "bzero", %w[string.h strings.h] )
36
34
 
37
35
  unless have_func( "strcasecmp" ) || have_func( "stricmp" )
38
- fail( "This extension requires either strcasecmp() or stricmp()" )
36
+ abort "This extension requires either strcasecmp() or stricmp()"
39
37
  end
40
38
  unless have_func( "strncasecmp" ) || have_func( "strnicmp" )
41
- fail( "This extensions requires either strncasecmp() or strnicmp()" )
39
+ abort "This extensions requires either strncasecmp() or strnicmp()"
42
40
  end
43
41
 
44
- have_header( 'mkdio.h' ) or fail( "missing mkdio.h" )
42
+ have_header( 'mkdio.h' ) or abort "missing mkdio.h"
45
43
 
46
44
  # Check for 1.9.xish encoding header
47
45
  have_header( 'ruby/encoding.h' )
data/ext/generate.c CHANGED
@@ -18,11 +18,9 @@
18
18
  #include "amalloc.h"
19
19
 
20
20
  typedef int (*stfu)(const void*,const void*);
21
-
21
+ typedef void (*spanhandler)(MMIOT*,int);
22
22
 
23
23
  /* forward declarations */
24
- static int iscodeblock(MMIOT*);
25
- static void code(int, MMIOT*);
26
24
  static void text(MMIOT *f);
27
25
  static Paragraph *display(Paragraph*, MMIOT*);
28
26
 
@@ -182,118 +180,6 @@ Qem(MMIOT *f, char c, int count)
182
180
  }
183
181
 
184
182
 
185
- /* empair()
186
- */
187
- static int
188
- empair(MMIOT *f, int go, int level)
189
- {
190
-
191
- int i;
192
- block *begin, *p;
193
-
194
- begin = &T(f->Q)[go];
195
- for (i=go+1; i < S(f->Q); i++) {
196
- p = &T(f->Q)[i];
197
-
198
- if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
199
- break;
200
-
201
- if ( p->b_type == begin->b_type ) {
202
- if ( p->b_count == level ) /* exact match */
203
- return i-go;
204
-
205
- if ( p->b_count > 2 ) /* fuzzy match */
206
- return i-go;
207
- }
208
- }
209
- return EOF;
210
- }
211
-
212
-
213
-
214
- static struct emtags {
215
- char open[10];
216
- char close[10];
217
- int size;
218
- } emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } };
219
-
220
-
221
- static void
222
- emclose(Cstring *s, int level)
223
- {
224
- PREFIX(*s, emtags[level-1].close, emtags[level-1].size);
225
- }
226
-
227
-
228
- static void
229
- emopen(Cstring *s, int level)
230
- {
231
- SUFFIX(*s, emtags[level-1].open, emtags[level-1].size-1);
232
- }
233
-
234
-
235
- /* emmatch()
236
- */
237
- static void
238
- emmatch(MMIOT *f, int go)
239
- {
240
- block *start = &T(f->Q)[go], *end;
241
- int e, e2, i, match;
242
-
243
- while ( start->b_count ) {
244
- switch (start->b_count) {
245
- case 2: e = empair(f,go,match=2);
246
- if ( e != EOF ) break;
247
- case 1: e = empair(f,go,match=1); break;
248
- default:
249
- e = empair(f,go,1);
250
- e2= empair(f,go,2);
251
-
252
- if ( e == EOF || ((e2 != EOF) && (e2 >= e)) ) {
253
- e = e2;
254
- match = 2;
255
- }
256
- else
257
- match = 1;
258
- }
259
- if ( e != EOF ) {
260
- end = &T(f->Q)[go+e];
261
- emclose(&end->b_post, match);
262
- emopen(&start->b_text, match);
263
- end->b_count -= match;
264
- }
265
- else {
266
- for (i=0; i < match; i++)
267
- EXPAND(start->b_text) = start->b_char;
268
- }
269
-
270
- start->b_count -= match;
271
- }
272
- }
273
-
274
-
275
- /* ___mkd_emblock()
276
- */
277
- void
278
- ___mkd_emblock(MMIOT *f)
279
- {
280
- int i;
281
- block *p;
282
-
283
- for (i=0; i < S(f->Q); i++) {
284
- p = &T(f->Q)[i];
285
-
286
- if ( p->b_type != bTEXT ) emmatch(f, i);
287
-
288
- if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post));
289
- DELETE(p->b_post); }
290
- if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text));
291
- DELETE(p->b_text); }
292
- }
293
- S(f->Q) = 0;
294
- }
295
-
296
-
297
183
  /* generate html from a markup fragment
298
184
  */
299
185
  void
@@ -304,7 +190,7 @@ ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f)
304
190
  ___mkd_initmmiot(&sub, f->footnotes);
305
191
 
306
192
  sub.flags = f->flags | flags;
307
- sub.base = f->base;
193
+ sub.cb = f->cb;
308
194
 
309
195
  push(bfr, size, &sub);
310
196
  EXPAND(sub.in) = 0;
@@ -345,6 +231,8 @@ puturl(char *s, int size, MMIOT *f, int display)
345
231
  Qstring("%22", f);
346
232
  else if ( isalnum(c) || ispunct(c) || (display && isspace(c)) )
347
233
  Qchar(c, f);
234
+ else if ( c == 003 ) /* untokenize ^C */
235
+ Qstring(" ", f);
348
236
  else
349
237
  Qprintf(f, "%%%02X", c);
350
238
  }
@@ -374,12 +262,12 @@ parenthetical(int in, int out, MMIOT *f)
374
262
  for ( indent=1,size=0; indent; size++ ) {
375
263
  if ( (c = pull(f)) == EOF )
376
264
  return EOF;
377
- else if ( c == in )
378
- ++indent;
379
- else if ( (c == '\\') && (peek(f,1) == out) ) {
265
+ else if ( (c == '\\') && (peek(f,1) == out || peek(f,1) == in) ) {
380
266
  ++size;
381
267
  pull(f);
382
268
  }
269
+ else if ( c == in )
270
+ ++indent;
383
271
  else if ( c == out )
384
272
  --indent;
385
273
  }
@@ -463,6 +351,53 @@ linkysize(MMIOT *f, Footnote *ref)
463
351
  }
464
352
 
465
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
+
466
401
  /* extract a (-prefixed url from the input stream.
467
402
  * the label is either of the format `<link>`, where I
468
403
  * extract until I find a >, or it is of the format
@@ -480,6 +415,8 @@ linkyurl(MMIOT *f, int image, Footnote *p)
480
415
 
481
416
  if ( c == '<' ) {
482
417
  pull(f);
418
+ if ( !(f->flags & MKD_1_COMPAT) )
419
+ return linkybroket(f,image,p);
483
420
  mayneedtotrim=1;
484
421
  }
485
422
 
@@ -512,27 +449,28 @@ linkyurl(MMIOT *f, int image, Footnote *p)
512
449
 
513
450
  /* prefixes for <automatic links>
514
451
  */
515
- static struct {
452
+ static struct _protocol {
516
453
  char *name;
517
454
  int nlen;
518
455
  } protocol[] = {
519
456
  #define _aprotocol(x) { x, (sizeof x)-1 }
520
- _aprotocol( "http://" ),
521
- _aprotocol( "https://" ),
522
- _aprotocol( "ftp://" ),
523
- _aprotocol( "news://" ),
457
+ _aprotocol( "https:" ),
458
+ _aprotocol( "http:" ),
459
+ _aprotocol( "news:" ),
460
+ _aprotocol( "ftp:" ),
524
461
  #undef _aprotocol
525
462
  };
526
463
  #define NRPROTOCOLS (sizeof protocol / sizeof protocol[0])
527
464
 
528
465
 
529
466
  static int
530
- isautoprefix(char *text)
467
+ isautoprefix(char *text, int size)
531
468
  {
532
469
  int i;
470
+ struct _protocol *p;
533
471
 
534
- for (i=0; i < NRPROTOCOLS; i++)
535
- if ( strncasecmp(text, protocol[i].name, protocol[i].nlen) == 0 )
472
+ for (i=0, p=protocol; i < NRPROTOCOLS; i++, p++)
473
+ if ( (size >= p->nlen) && strncasecmp(text, p->name, p->nlen) == 0 )
536
474
  return 1;
537
475
  return 0;
538
476
  }
@@ -556,9 +494,9 @@ typedef struct linkytype {
556
494
  } linkytype;
557
495
 
558
496
  static linkytype imaget = { 0, 0, "<img src=\"", "\"",
559
- 1, " alt=\"", "\" />", DENY_IMG|INSIDE_TAG, IS_URL };
497
+ 1, " alt=\"", "\" />", MKD_NOIMAGE|MKD_TAGTEXT, IS_URL };
560
498
  static linkytype linkt = { 0, 0, "<a href=\"", "\"",
561
- 0, ">", "</a>", DENY_A, IS_URL };
499
+ 0, ">", "</a>", MKD_NOLINKS, IS_URL };
562
500
 
563
501
  /*
564
502
  * pseudo-protocols for [][];
@@ -568,10 +506,11 @@ static linkytype linkt = { 0, 0, "<a href=\"", "\"",
568
506
  * raw: just dump the link without any processing
569
507
  */
570
508
  static linkytype specials[] = {
571
- { "id:", 3, "<a id=\"", "\"", 0, ">", "</a>", 0, IS_URL },
572
- { "class:", 6, "<span class=\"", "\"", 0, ">", "</span>", 0, 0 },
573
- { "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 },
511
+ { "lang:", 5, "<span lang=\"", "\"", 0, ">", "</span>", 0, 0 },
574
512
  { "abbr:", 5, "<abbr title=\"", "\"", 0, ">", "</abbr>", 0, 0 },
513
+ { "class:", 6, "<span class=\"", "\"", 0, ">", "</span>", 0, 0 },
575
514
  } ;
576
515
 
577
516
  #define NR(x) (sizeof x / sizeof x[0])
@@ -584,8 +523,7 @@ pseudo(Cstring t)
584
523
  int i;
585
524
  linkytype *r;
586
525
 
587
- for ( i=0; i < NR(specials); i++ ) {
588
- r = &specials[i];
526
+ for ( i=0, r=specials; i < NR(specials); i++,r++ ) {
589
527
  if ( (S(t) > r->szpat) && (strncasecmp(T(t), r->pat, r->szpat) == 0) )
590
528
  return r;
591
529
  }
@@ -593,6 +531,39 @@ pseudo(Cstring t)
593
531
  }
594
532
 
595
533
 
534
+ /* print out the start of an `img' or `a' tag, applying callbacks as needed.
535
+ */
536
+ static void
537
+ printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
538
+ {
539
+ char *edit;
540
+
541
+ if ( f->flags & IS_LABEL )
542
+ return;
543
+
544
+ Qstring(tag->link_pfx, f);
545
+
546
+ if ( tag->kind & IS_URL ) {
547
+ if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) {
548
+ puturl(edit, strlen(edit), f, 0);
549
+ if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data);
550
+ }
551
+ else
552
+ puturl(link + tag->szpat, size - tag->szpat, f, 0);
553
+ }
554
+ else
555
+ ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f);
556
+
557
+ Qstring(tag->link_sfx, f);
558
+
559
+ if ( f->cb && f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) {
560
+ Qchar(' ', f);
561
+ Qstring(edit, f);
562
+ if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data);
563
+ }
564
+ } /* printlinkyref */
565
+
566
+
596
567
  /* print out a linky (or fail if it's Not Allowed)
597
568
  */
598
569
  static int
@@ -600,46 +571,38 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
600
571
  {
601
572
  linkytype *tag;
602
573
 
603
- if ( image )
574
+ if ( image || (ref == 0) )
604
575
  tag = &imaget;
605
576
  else if ( tag = pseudo(ref->link) ) {
606
- if ( f->flags & (NO_PSEUDO_PROTO|SAFELINK) )
577
+ if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) )
607
578
  return 0;
608
579
  }
609
- else if ( (f->flags & SAFELINK) && T(ref->link)
610
- && (T(ref->link)[0] != '/')
611
- && !isautoprefix(T(ref->link)) )
612
- /* 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
613
584
  * a well-known protocol
614
585
  */
615
- return 0;
586
+ return 0;
616
587
  else
617
588
  tag = &linkt;
618
589
 
619
590
  if ( f->flags & tag->flags )
620
591
  return 0;
621
592
 
622
- if ( tag->link_pfx ) {
623
- Qstring(tag->link_pfx, f);
624
-
625
- if ( tag->kind & IS_URL ) {
626
- if ( f->base && T(ref->link) && (T(ref->link)[tag->szpat] == '/') )
627
- puturl(f->base, strlen(f->base), f, 0);
628
- puturl(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f, 0);
629
- }
630
- else
631
- ___mkd_reparse(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, INSIDE_TAG, f);
632
-
633
- Qstring(tag->link_sfx, f);
593
+ if ( f->flags & IS_LABEL )
594
+ ___mkd_reparse(T(text), S(text), tag->flags, f);
595
+ else if ( tag->link_pfx ) {
596
+ printlinkyref(f, tag, T(ref->link), S(ref->link));
634
597
 
635
- if ( tag->WxH) {
636
- if ( ref->height) Qprintf(f," height=\"%d\"", ref->height);
637
- if ( ref->width) Qprintf(f, " width=\"%d\"", ref->width);
598
+ if ( tag->WxH ) {
599
+ if ( ref->height ) Qprintf(f," height=\"%d\"", ref->height);
600
+ if ( ref->width ) Qprintf(f, " width=\"%d\"", ref->width);
638
601
  }
639
602
 
640
603
  if ( S(ref->title) ) {
641
604
  Qstring(" title=\"", f);
642
- ___mkd_reparse(T(ref->title), S(ref->title), INSIDE_TAG, f);
605
+ ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f);
643
606
  Qchar('"', f);
644
607
  }
645
608
 
@@ -677,8 +640,11 @@ linkylinky(int image, MMIOT *f)
677
640
  }
678
641
  else {
679
642
  int goodlink, implicit_mark = mmiottell(f);
680
-
681
- if ( eatspace(f) == '[' ) {
643
+
644
+ if ( isspace(peek(f,1)) )
645
+ pull(f);
646
+
647
+ if ( peek(f,1) == '[' ) {
682
648
  pull(f); /* consume leading '[' */
683
649
  goodlink = linkylabel(f, &key.tag);
684
650
  }
@@ -700,6 +666,8 @@ linkylinky(int image, MMIOT *f)
700
666
  if ( ref = bsearch(&key, T(*f->footnotes), S(*f->footnotes),
701
667
  sizeof key, (stfu)__mkd_footsort) )
702
668
  status = linkyformat(f, name, image, ref);
669
+ else if ( f->flags & IS_LABEL )
670
+ status = linkyformat(f, name, image, 0);
703
671
  }
704
672
  }
705
673
  }
@@ -742,20 +710,112 @@ mangle(char *s, int len, MMIOT *f)
742
710
  }
743
711
 
744
712
 
713
+ /* nrticks() -- count up a row of tick marks
714
+ */
715
+ static int
716
+ nrticks(int offset, int tickchar, MMIOT *f)
717
+ {
718
+ int tick = 0;
719
+
720
+ while ( peek(f, offset+tick) == tickchar ) tick++;
721
+
722
+ return tick;
723
+ } /* nrticks */
724
+
725
+
726
+ /* matchticks() -- match a certain # of ticks, and if that fails
727
+ * match the largest subset of those ticks.
728
+ *
729
+ * if a subset was matched, return the # of ticks
730
+ * that were matched.
731
+ */
732
+ static int
733
+ matchticks(MMIOT *f, int tickchar, int ticks, int *endticks)
734
+ {
735
+ int size, count, c;
736
+ int subsize=0, subtick=0;
737
+
738
+ *endticks = ticks;
739
+ for (size = 0; (c=peek(f,size+ticks)) != EOF; size ++) {
740
+ if ( (c == tickchar) && ( count = nrticks(size+ticks,tickchar,f)) ) {
741
+ if ( count == ticks )
742
+ return size;
743
+ else if ( count ) {
744
+ if ( (count > subtick) && (count < ticks) ) {
745
+ subsize = size;
746
+ subtick = count;
747
+ }
748
+ size += count;
749
+ }
750
+ }
751
+ }
752
+ if ( subsize ) {
753
+ *endticks = subtick;
754
+ return subsize;
755
+ }
756
+ return 0;
757
+ } /* matchticks */
758
+
759
+
760
+ /* code() -- write a string out as code. The only characters that have
761
+ * special meaning in a code block are * `<' and `&' , which
762
+ * are /always/ expanded to &lt; and &amp;
763
+ */
764
+ static void
765
+ code(MMIOT *f, char *s, int length)
766
+ {
767
+ int i,c;
768
+
769
+ for ( i=0; i < length; i++ )
770
+ if ( (c = s[i]) == 003) /* ^C: expand back to 2 spaces */
771
+ Qstring(" ", f);
772
+ else
773
+ cputc(c, f);
774
+ } /* code */
775
+
776
+
777
+ /* delspan() -- write out a chunk of text, blocking with <del>...</del>
778
+ */
779
+ static void
780
+ delspan(MMIOT *f, int size)
781
+ {
782
+ Qstring("<del>", f);
783
+ ___mkd_reparse(cursor(f)-1, size, 0, f);
784
+ Qstring("</del>", f);
785
+ }
786
+
787
+
788
+ /* codespan() -- write out a chunk of text as code, trimming one
789
+ * space off the front and/or back as appropriate.
790
+ */
791
+ static void
792
+ codespan(MMIOT *f, int size)
793
+ {
794
+ int i=0;
795
+
796
+ if ( size > 1 && peek(f, size-1) == ' ' ) --size;
797
+ if ( peek(f,i) == ' ' ) ++i, --size;
798
+
799
+ Qstring("<code>", f);
800
+ code(f, cursor(f)+(i-1), size);
801
+ Qstring("</code>", f);
802
+ } /* codespan */
803
+
804
+
745
805
  /* before letting a tag through, validate against
746
- * DENY_A and DENY_IMG
806
+ * MKD_NOLINKS and MKD_NOIMAGE
747
807
  */
748
808
  static int
749
809
  forbidden_tag(MMIOT *f)
750
810
  {
751
811
  int c = toupper(peek(f, 1));
752
812
 
753
- if ( f->flags & DENY_HTML )
813
+ if ( f->flags & MKD_NOHTML )
754
814
  return 1;
755
815
 
756
- if ( c == 'A' && (f->flags & DENY_A) && !isthisalnum(f,2) )
816
+ if ( c == 'A' && (f->flags & MKD_NOLINKS) && !isthisalnum(f,2) )
757
817
  return 1;
758
- if ( c == 'I' && (f->flags & DENY_IMG)
818
+ if ( c == 'I' && (f->flags & MKD_NOIMAGE)
759
819
  && strncasecmp(cursor(f)+1, "MG", 2) == 0
760
820
  && !isthisalnum(f,4) )
761
821
  return 1;
@@ -802,7 +862,7 @@ process_possible_link(MMIOT *f, int size)
802
862
  int mailto = 0;
803
863
  char *text = cursor(f);
804
864
 
805
- if ( f->flags & DENY_A ) return 0;
865
+ if ( f->flags & MKD_NOLINKS ) return 0;
806
866
 
807
867
  if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) {
808
868
  /* if it says it's a mailto, it's a mailto -- who am
@@ -826,10 +886,9 @@ process_possible_link(MMIOT *f, int size)
826
886
  Qstring("</a>", f);
827
887
  return 1;
828
888
  }
829
- else if ( isautoprefix(text) ) {
830
- Qstring("<a href=\"", f);
831
- puturl(text,size,f, 0);
832
- Qstring("\">", f);
889
+ else if ( isautoprefix(text, size) ) {
890
+ printlinkyref(f, &linkt, text, size);
891
+ Qchar('>', f);
833
892
  puturl(text,size,f, 1);
834
893
  Qstring("</a>", f);
835
894
  return 1;
@@ -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++) {
@@ -879,7 +938,10 @@ maybe_tag_or_link(MMIOT *f)
879
938
  else
880
939
  size++;
881
940
 
882
- Qstring(forbidden_tag(f) ? "&lt;" : "<", f);
941
+ if ( forbidden_tag(f) )
942
+ return 0;
943
+
944
+ Qchar('<', f);
883
945
  while ( ((c = peek(f, 1)) != EOF) && (c != '>') )
884
946
  Qchar(pull(f), f);
885
947
  return 1;
@@ -981,6 +1043,11 @@ static struct smarties {
981
1043
  } smarties[] = {
982
1044
  { '\'', "'s>", "rsquo", 0 },
983
1045
  { '\'', "'t>", "rsquo", 0 },
1046
+ { '\'', "'re>", "rsquo", 0 },
1047
+ { '\'', "'ll>", "rsquo", 0 },
1048
+ { '\'', "'ve>", "rsquo", 0 },
1049
+ { '\'', "'m>", "rsquo", 0 },
1050
+ { '\'', "'d>", "rsquo", 0 },
984
1051
  { '-', "--", "mdash", 1 },
985
1052
  { '-', "<->", "ndash", 0 },
986
1053
  { '.', "...", "hellip", 2 },
@@ -1005,7 +1072,7 @@ smartypants(int c, int *flags, MMIOT *f)
1005
1072
  {
1006
1073
  int i;
1007
1074
 
1008
- if ( f->flags & (DENY_SMARTY|INSIDE_TAG) )
1075
+ if ( f->flags & (MKD_NOPANTS|MKD_TAGTEXT|IS_LABEL) )
1009
1076
  return 0;
1010
1077
 
1011
1078
  for ( i=0; i < NRSMART; i++)
@@ -1049,7 +1116,31 @@ smartypants(int c, int *flags, MMIOT *f)
1049
1116
  } /* smartypants */
1050
1117
 
1051
1118
 
1052
- #define tag_text(f) (f->flags & INSIDE_TAG)
1119
+ /* process a body of text encased in some sort of tick marks. If it
1120
+ * works, generate the output and return 1, otherwise just return 0 and
1121
+ * let the caller figure it out.
1122
+ */
1123
+ static int
1124
+ tickhandler(MMIOT *f, int tickchar, int minticks, spanhandler spanner)
1125
+ {
1126
+ int endticks, size;
1127
+ int tick = nrticks(0, tickchar, f);
1128
+
1129
+ if ( (tick >= minticks) && (size = matchticks(f,tickchar,tick,&endticks)) ) {
1130
+ if ( endticks < tick ) {
1131
+ size += (tick - endticks);
1132
+ tick = endticks;
1133
+ }
1134
+
1135
+ shift(f, tick);
1136
+ (*spanner)(f,size);
1137
+ shift(f, size+tick-1);
1138
+ return 1;
1139
+ }
1140
+ return 0;
1141
+ }
1142
+
1143
+ #define tag_text(f) (f->flags & MKD_TAGTEXT)
1053
1144
 
1054
1145
 
1055
1146
  static void
@@ -1060,7 +1151,7 @@ text(MMIOT *f)
1060
1151
  int smartyflags = 0;
1061
1152
 
1062
1153
  while (1) {
1063
- if ( (f->flags & AUTOLINK) && isalpha(peek(f,1)) )
1154
+ if ( (f->flags & MKD_AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) )
1064
1155
  maybe_autolink(f);
1065
1156
 
1066
1157
  c = pull(f);
@@ -1073,7 +1164,7 @@ text(MMIOT *f)
1073
1164
  switch (c) {
1074
1165
  case 0: break;
1075
1166
 
1076
- case 3: Qstring("<br/>", f);
1167
+ case 3: Qstring(tag_text(f) ? " " : "<br/>", f);
1077
1168
  break;
1078
1169
 
1079
1170
  case '>': if ( tag_text(f) )
@@ -1099,43 +1190,56 @@ text(MMIOT *f)
1099
1190
  case '[': if ( tag_text(f) || !linkylinky(0, f) )
1100
1191
  Qchar(c, f);
1101
1192
  break;
1102
- #if SUPERSCRIPT
1103
1193
  /* A^B -> A<sup>B</sup> */
1104
- 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) )
1105
1197
  Qchar(c,f);
1106
1198
  else {
1107
1199
  char *sup = cursor(f);
1108
1200
  int len = 0;
1109
- Qstring("<sup>",f);
1110
- while ( !isthisspace(f,1+len) ) {
1111
- ++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++;
1112
1212
  }
1113
- shift(f,len);
1213
+ else {
1214
+ while ( isthisalnum(f,1+len) )
1215
+ ++len;
1216
+ if ( !len ) {
1217
+ Qchar(c,f);
1218
+ break;
1219
+ }
1220
+ shift(f,len);
1221
+ }
1222
+ Qstring("<sup>",f);
1114
1223
  ___mkd_reparse(sup, len, 0, f);
1115
1224
  Qstring("</sup>", f);
1116
1225
  }
1117
1226
  break;
1118
- #endif
1119
1227
  case '_':
1120
- #if RELAXED_EMPHASIS
1121
1228
  /* Underscores don't count if they're in the middle of a word */
1122
- if ( !(f->flags & STRICT) && isthisalnum(f,-1)
1123
- && isthisalnum(f,1) ) {
1229
+ if ( !(f->flags & (MKD_NORELAXED|MKD_STRICT))
1230
+ && isthisalnum(f,-1)
1231
+ && isthisalnum(f,1) ) {
1124
1232
  Qchar(c, f);
1125
1233
  break;
1126
1234
  }
1127
- #endif
1128
1235
  case '*':
1129
- #if RELAXED_EMPHASIS
1130
1236
  /* Underscores & stars don't count if they're out in the middle
1131
1237
  * of whitespace */
1132
- if ( !(f->flags & STRICT) && isthisspace(f,-1)
1133
- && isthisspace(f,1) ) {
1238
+ if ( isthisspace(f,-1) && isthisspace(f,1) ) {
1134
1239
  Qchar(c, f);
1135
1240
  break;
1136
1241
  }
1137
1242
  /* else fall into the regular old emphasis case */
1138
- #endif
1139
1243
  if ( tag_text(f) )
1140
1244
  Qchar(c, f);
1141
1245
  else {
@@ -1145,18 +1249,12 @@ text(MMIOT *f)
1145
1249
  }
1146
1250
  break;
1147
1251
 
1148
- case '`': if ( tag_text(f) || !iscodeblock(f) )
1252
+ case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || !tickhandler(f,c,2,delspan) )
1253
+ Qchar(c, f);
1254
+ break;
1255
+
1256
+ case '`': if ( tag_text(f) || !tickhandler(f,c,1,codespan) )
1149
1257
  Qchar(c, f);
1150
- else {
1151
- Qstring("<code>", f);
1152
- if ( peek(f, 1) == '`' ) {
1153
- pull(f);
1154
- code(2, f);
1155
- }
1156
- else
1157
- code(1, f);
1158
- Qstring("</code>", f);
1159
- }
1160
1258
  break;
1161
1259
 
1162
1260
  case '\\': switch ( c = pull(f) ) {
@@ -1164,11 +1262,18 @@ text(MMIOT *f)
1164
1262
  break;
1165
1263
  case '<': Qstring("&lt;", f);
1166
1264
  break;
1167
- case '\\':
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
+
1168
1273
  case '>': case '#': case '.': case '-':
1169
1274
  case '+': case '{': case '}': case ']':
1170
- case '(': case ')': case '"': case '\'':
1171
1275
  case '!': case '[': case '*': case '_':
1276
+ case '\\':case '(': case ')':
1172
1277
  case '`': Qchar(c, f);
1173
1278
  break;
1174
1279
  default:
@@ -1202,86 +1307,17 @@ text(MMIOT *f)
1202
1307
  } /* text */
1203
1308
 
1204
1309
 
1205
- static int
1206
- iscodeblock(MMIOT *f)
1207
- {
1208
- int i=1, single = 1, c;
1209
-
1210
- if ( peek(f,i) == '`' ) {
1211
- single=0;
1212
- i++;
1213
- }
1214
- while ( (c=peek(f,i)) != EOF ) {
1215
- if ( (c == '`') && (single || peek(f,i+1) == '`') )
1216
- return 1;
1217
- else if ( c == '\\' )
1218
- i++;
1219
- i++;
1220
- }
1221
- return 0;
1222
-
1223
- }
1224
-
1225
- static int
1226
- endofcode(int escape, int offset, MMIOT *f)
1227
- {
1228
- switch (escape) {
1229
- case 2: if ( peek(f, offset+1) == '`' ) {
1230
- shift(f,1);
1231
- case 1: shift(f,offset);
1232
- return 1;
1233
- }
1234
- default:return 0;
1235
- }
1236
- }
1237
-
1238
-
1239
- /* the only characters that have special meaning in a code block are
1240
- * `<' and `&' , which are /always/ expanded to &lt; and &amp;
1241
- */
1242
- static void
1243
- code(int escape, MMIOT *f)
1244
- {
1245
- int c;
1246
-
1247
- if ( escape && (peek(f,1) == ' ') )
1248
- shift(f,1);
1249
-
1250
- while ( (c = pull(f)) != EOF ) {
1251
- switch (c) {
1252
- case ' ': if ( peek(f,1) == '`' && endofcode(escape, 1, f) )
1253
- return;
1254
- Qchar(c, f);
1255
- break;
1256
-
1257
- case '`': if ( endofcode(escape, 0, f) )
1258
- return;
1259
- Qchar(c, f);
1260
- break;
1261
-
1262
- case '\\': cputc(c, f);
1263
- if ( peek(f,1) == '>' || (c = pull(f)) == EOF )
1264
- break;
1265
-
1266
- default: cputc(c, f);
1267
- break;
1268
- }
1269
- }
1270
- } /* code */
1271
-
1272
-
1273
1310
  /* print a header block
1274
1311
  */
1275
1312
  static void
1276
1313
  printheader(Paragraph *pp, MMIOT *f)
1277
1314
  {
1278
- Qprintf(f, "<h%d", pp->hnumber);
1279
- if ( f->flags & TOC ) {
1280
- Qprintf(f, " id=\"", pp->hnumber);
1281
- mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Qchar, f);
1282
- Qchar('"', f);
1315
+ if ( f->flags & MKD_TOC ) {
1316
+ Qstring("<a name=\"", f);
1317
+ mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Qchar, f, 1);
1318
+ Qstring("\"></a>\n", f);
1283
1319
  }
1284
- Qchar('>', f);
1320
+ Qprintf(f, "<h%d>", pp->hnumber);
1285
1321
  push(T(pp->text->text), S(pp->text->text), f);
1286
1322
  text(f);
1287
1323
  Qprintf(f, "</h%d>", pp->hnumber);
@@ -1328,6 +1364,7 @@ splat(Line *p, char *block, Istring align, int force, MMIOT *f)
1328
1364
  return colno;
1329
1365
  }
1330
1366
 
1367
+
1331
1368
  static int
1332
1369
  printtable(Paragraph *pp, MMIOT *f)
1333
1370
  {
@@ -1392,13 +1429,14 @@ static int
1392
1429
  printblock(Paragraph *pp, MMIOT *f)
1393
1430
  {
1394
1431
  Line *t = pp->text;
1395
- static char *Begin[] = { "", "<p>", "<center>" };
1396
- static char *End[] = { "", "</p>","</center>" };
1432
+ static char *Begin[] = { "", "<p>", "<p style=\"text-align:center;\">" };
1433
+ static char *End[] = { "", "</p>","</p>" };
1397
1434
 
1398
1435
  while (t) {
1399
1436
  if ( S(t->text) ) {
1400
- if ( S(t->text) > 2 && T(t->text)[S(t->text)-2] == ' '
1401
- && T(t->text)[S(t->text)-1] == ' ') {
1437
+ if ( t->next && S(t->text) > 2
1438
+ && T(t->text)[S(t->text)-2] == ' '
1439
+ && T(t->text)[S(t->text)-1] == ' ' ) {
1402
1440
  push(T(t->text), S(t->text)-2, f);
1403
1441
  push("\003\n", 2, f);
1404
1442
  }
@@ -1423,19 +1461,18 @@ printcode(Line *t, MMIOT *f)
1423
1461
  {
1424
1462
  int blanks;
1425
1463
 
1426
- for ( blanks = 0; t ; t = t->next )
1464
+ Qstring("<pre><code>", f);
1465
+ for ( blanks = 0; t ; t = t->next ) {
1427
1466
  if ( S(t->text) > t->dle ) {
1428
1467
  while ( blanks ) {
1429
- push("\n", 1, f);
1468
+ Qchar('\n', f);
1430
1469
  --blanks;
1431
1470
  }
1432
- push(T(t->text), S(t->text), f);
1433
- push("\n", 1, f);
1471
+ code(f, T(t->text), S(t->text));
1472
+ Qchar('\n', f);
1434
1473
  }
1435
1474
  else blanks++;
1436
-
1437
- Qstring("<pre><code>", f);
1438
- code(0, f);
1475
+ }
1439
1476
  Qstring("</code></pre>", f);
1440
1477
  }
1441
1478
 
@@ -1477,7 +1514,6 @@ htmlify(Paragraph *p, char *block, char *arguments, MMIOT *f)
1477
1514
  }
1478
1515
 
1479
1516
 
1480
- #if DL_TAG_EXTENSION
1481
1517
  static void
1482
1518
  definitionlist(Paragraph *p, MMIOT *f)
1483
1519
  {
@@ -1500,7 +1536,6 @@ definitionlist(Paragraph *p, MMIOT *f)
1500
1536
  Qstring("</dl>", f);
1501
1537
  }
1502
1538
  }
1503
- #endif
1504
1539
 
1505
1540
 
1506
1541
  static void
@@ -1509,7 +1544,7 @@ listdisplay(int typ, Paragraph *p, MMIOT* f)
1509
1544
  if ( p ) {
1510
1545
  Qprintf(f, "<%cl", (typ==UL)?'u':'o');
1511
1546
  if ( typ == AL )
1512
- Qprintf(f, " type=a");
1547
+ Qprintf(f, " type=\"a\"");
1513
1548
  Qprintf(f, ">\n");
1514
1549
 
1515
1550
  for ( ; p ; p = p->next ) {
@@ -1552,11 +1587,9 @@ display(Paragraph *p, MMIOT *f)
1552
1587
  listdisplay(p->typ, p->down, f);
1553
1588
  break;
1554
1589
 
1555
- #if DL_TAG_EXTENSION
1556
1590
  case DL:
1557
1591
  definitionlist(p->down, f);
1558
1592
  break;
1559
- #endif
1560
1593
 
1561
1594
  case HR:
1562
1595
  Qstring("<hr />", f);
@@ -1588,14 +1621,21 @@ display(Paragraph *p, MMIOT *f)
1588
1621
  int
1589
1622
  mkd_document(Document *p, char **res)
1590
1623
  {
1624
+ int size;
1625
+
1591
1626
  if ( p && p->compiled ) {
1592
1627
  if ( ! p->html ) {
1593
1628
  htmlify(p->code, 0, 0, p->ctx);
1594
1629
  p->html = 1;
1595
1630
  }
1596
1631
 
1632
+ size = S(p->ctx->out);
1633
+
1634
+ if ( (size == 0) || T(p->ctx->out)[size-1] )
1635
+ EXPAND(p->ctx->out) = 0;
1636
+
1597
1637
  *res = T(p->ctx->out);
1598
- return S(p->ctx->out);
1638
+ return size;
1599
1639
  }
1600
1640
  return EOF;
1601
1641
  }