rdiscount 2.1.7 → 2.2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -177,6 +177,7 @@ splitline(Line *t, int cutpoint)
177
177
  }
178
178
 
179
179
  #define UNCHECK(l) ((l)->flags &= ~CHECKED)
180
+
180
181
  #define UNLESS_FENCED(t) if (fenced) { \
181
182
  other = 1; l->count += (c == ' ' ? 0 : -1); \
182
183
  } else { t; }
@@ -186,7 +187,7 @@ splitline(Line *t, int cutpoint)
186
187
  * types.
187
188
  */
188
189
  static void
189
- checkline(Line *l)
190
+ checkline(Line *l, DWORD flags)
190
191
  {
191
192
  int eol, i;
192
193
  int dashes = 0, spaces = 0,
@@ -205,6 +206,7 @@ checkline(Line *l)
205
206
 
206
207
  for (i=l->dle; i<eol; i++) {
207
208
  register int c = T(l->text)[i];
209
+ int is_fence_char = 0;
208
210
 
209
211
  if ( c != ' ' ) l->count++;
210
212
 
@@ -214,14 +216,20 @@ checkline(Line *l)
214
216
  case '=': equals = 1; break;
215
217
  case '_': UNLESS_FENCED(underscores = 1); break;
216
218
  case '*': stars = 1; break;
217
- #if WITH_FENCED_CODE
218
- case '~': if (other) return; fenced = 1; tildes = 1; break;
219
- case '`': if (other) return; fenced = 1; backticks = 1; break;
220
- #endif
221
219
  default:
222
- other = 1;
223
- l->count--;
224
- if (!fenced) return;
220
+ if (flags & MKD_FENCEDCODE) {
221
+ switch (c) {
222
+ case '~': if (other) return; is_fence_char = 1; tildes = 1; break;
223
+ case '`': if (other) return; is_fence_char = 1; backticks = 1; break;
224
+ }
225
+ if (is_fence_char) {
226
+ fenced = 1;
227
+ break;
228
+ }
229
+ }
230
+ other = 1;
231
+ l->count--;
232
+ if (!fenced) return;
225
233
  }
226
234
  }
227
235
 
@@ -237,28 +245,32 @@ checkline(Line *l)
237
245
  if ( stars || underscores ) { l->kind = chk_hr; }
238
246
  else if ( dashes ) { l->kind = chk_dash; }
239
247
  else if ( equals ) { l->kind = chk_equal; }
240
- #if WITH_FENCED_CODE
241
248
  else if ( tildes ) { l->kind = chk_tilde; }
242
249
  else if ( backticks ) { l->kind = chk_backtick; }
243
- #endif
244
250
  }
245
251
 
246
252
 
247
253
 
254
+ /* markdown only does special handling of comments if the comment end
255
+ * is at the end of a line
256
+ */
248
257
  static Line *
249
258
  commentblock(Paragraph *p, int *unclosed)
250
259
  {
251
260
  Line *t, *ret;
252
261
  char *end;
253
262
 
254
- for ( t = p->text; t ; t = t->next) {
255
- if ( end = strstr(T(t->text), "-->") ) {
256
- splitline(t, 3 + (end - T(t->text)) );
257
- ret = t->next;
258
- t->next = 0;
259
- return ret;
260
- }
263
+ for ( t = p->text; t ; t = t->next) {
264
+ if ( end = strstr(T(t->text), "-->") ) {
265
+ if ( nextnonblank(t, 3 + (end - T(t->text))) < S(t->text) )
266
+ continue;
267
+ /*splitline(t, 3 + (end - T(t->text)) );*/
268
+ ret = t->next;
269
+ t->next = 0;
270
+ return ret;
271
+ }
261
272
  }
273
+
262
274
  *unclosed = 1;
263
275
  return t;
264
276
 
@@ -302,8 +314,8 @@ htmlblock(Paragraph *p, struct kw *tag, int *unclosed)
302
314
  else {
303
315
  if ( closing = (c == '/') ) c = flogetc(&f);
304
316
 
305
- for ( i=0; i < tag->size; c=flogetc(&f) ) {
306
- if ( tag->id[i++] != toupper(c) )
317
+ for ( i=0; i < tag->size; i++, c=flogetc(&f) ) {
318
+ if ( tag->id[i] != toupper(c) )
307
319
  break;
308
320
  }
309
321
 
@@ -367,10 +379,10 @@ iscode(Line *t)
367
379
 
368
380
 
369
381
  static inline int
370
- ishr(Line *t)
382
+ ishr(Line *t, DWORD flags)
371
383
  {
372
384
  if ( ! (t->flags & CHECKED) )
373
- checkline(t);
385
+ checkline(t, flags);
374
386
 
375
387
  if ( t->count > 2 )
376
388
  return t->kind == chk_hr || t->kind == chk_dash || t->kind == chk_equal;
@@ -379,7 +391,7 @@ ishr(Line *t)
379
391
 
380
392
 
381
393
  static int
382
- issetext(Line *t, int *htyp)
394
+ issetext(Line *t, int *htyp, DWORD flags)
383
395
  {
384
396
  Line *n;
385
397
 
@@ -389,7 +401,7 @@ issetext(Line *t, int *htyp)
389
401
 
390
402
  if ( (n = t->next) ) {
391
403
  if ( !(n->flags & CHECKED) )
392
- checkline(n);
404
+ checkline(n, flags);
393
405
 
394
406
  if ( n->kind == chk_dash || n->kind == chk_equal ) {
395
407
  *htyp = SETEXT;
@@ -401,7 +413,7 @@ issetext(Line *t, int *htyp)
401
413
 
402
414
 
403
415
  static int
404
- ishdr(Line *t, int *htyp)
416
+ ishdr(Line *t, int *htyp, DWORD flags)
405
417
  {
406
418
  /* ANY leading `#`'s make this into an ETX header
407
419
  */
@@ -412,27 +424,28 @@ ishdr(Line *t, int *htyp)
412
424
 
413
425
  /* And if not, maybe it's a SETEXT header instead
414
426
  */
415
- return issetext(t, htyp);
427
+ return issetext(t, htyp, flags);
416
428
  }
417
429
 
418
430
 
419
431
  static inline int
420
- end_of_block(Line *t)
432
+ end_of_block(Line *t, DWORD flags)
421
433
  {
422
434
  int dummy;
423
435
 
424
436
  if ( !t )
425
437
  return 0;
426
438
 
427
- return ( (S(t->text) <= t->dle) || ishr(t) || ishdr(t, &dummy) );
439
+ return ( (S(t->text) <= t->dle) || ishr(t, flags) || ishdr(t, &dummy, flags) );
428
440
  }
429
441
 
430
442
 
431
443
  static Line*
432
- is_discount_dt(Line *t, int *clip)
444
+ is_discount_dt(Line *t, int *clip, DWORD flags)
433
445
  {
434
- #if USE_DISCOUNT_DL
435
- if ( t && t->next
446
+ if ( !(flags & MKD_NODLDISCOUNT)
447
+ && t
448
+ && t->next
436
449
  && (S(t->text) > 2)
437
450
  && (t->dle == 0)
438
451
  && (T(t->text)[0] == '=')
@@ -442,9 +455,8 @@ is_discount_dt(Line *t, int *clip)
442
455
  return t;
443
456
  }
444
457
  else
445
- return is_discount_dt(t->next, clip);
458
+ return is_discount_dt(t->next, clip, flags);
446
459
  }
447
- #endif
448
460
  return 0;
449
461
  }
450
462
 
@@ -458,15 +470,15 @@ is_extra_dd(Line *t)
458
470
 
459
471
 
460
472
  static Line*
461
- is_extra_dt(Line *t, int *clip)
473
+ is_extra_dt(Line *t, int *clip, DWORD flags)
462
474
  {
463
- #if USE_EXTRA_DL
464
-
465
- if ( t && t->next && S(t->text) && T(t->text)[0] != '='
475
+ if ( flags & MKD_DLEXTRA
476
+ && t
477
+ && t->next && S(t->text) && T(t->text)[0] != '='
466
478
  && T(t->text)[S(t->text)-1] != '=') {
467
479
  Line *x;
468
480
 
469
- if ( iscode(t) || end_of_block(t) )
481
+ if ( iscode(t) || end_of_block(t, flags) )
470
482
  return 0;
471
483
 
472
484
  if ( (x = skipempty(t->next)) && is_extra_dd(x) ) {
@@ -474,25 +486,24 @@ is_extra_dt(Line *t, int *clip)
474
486
  return t;
475
487
  }
476
488
 
477
- if ( x=is_extra_dt(t->next, clip) )
489
+ if ( x=is_extra_dt(t->next, clip, flags) )
478
490
  return x;
479
491
  }
480
- #endif
481
492
  return 0;
482
493
  }
483
494
 
484
495
 
485
496
  static Line*
486
- isdefinition(Line *t, int *clip, int *kind)
497
+ isdefinition(Line *t, int *clip, int *kind, DWORD flags)
487
498
  {
488
499
  Line *ret;
489
500
 
490
501
  *kind = 1;
491
- if ( ret = is_discount_dt(t,clip) )
502
+ if ( ret = is_discount_dt(t,clip,flags) )
492
503
  return ret;
493
504
 
494
505
  *kind=2;
495
- return is_extra_dt(t,clip);
506
+ return is_extra_dt(t,clip,flags);
496
507
  }
497
508
 
498
509
 
@@ -502,10 +513,10 @@ islist(Line *t, int *clip, DWORD flags, int *list_type)
502
513
  int i, j;
503
514
  char *q;
504
515
 
505
- if ( end_of_block(t) )
516
+ if ( end_of_block(t, flags) )
506
517
  return 0;
507
518
 
508
- if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type) )
519
+ if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type,flags) )
509
520
  return DL;
510
521
 
511
522
  if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
@@ -530,8 +541,7 @@ islist(Line *t, int *clip, DWORD flags, int *list_type)
530
541
  strtoul(T(t->text)+t->dle, &q, 10);
531
542
  if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) {
532
543
  j = nextnonblank(t,j);
533
- /* *clip = j; */
534
- *clip = (j > 4) ? 4 : j;
544
+ *clip = j;
535
545
  *list_type = OL;
536
546
  return AL;
537
547
  }
@@ -611,12 +621,14 @@ codeblock(Paragraph *p)
611
621
  }
612
622
 
613
623
 
614
- #ifdef WITH_FENCED_CODE
615
624
  static int
616
- iscodefence(Line *r, int size, line_type kind)
625
+ iscodefence(Line *r, int size, line_type kind, DWORD flags)
617
626
  {
627
+ if ( !(flags & MKD_FENCEDCODE) )
628
+ return 0;
629
+
618
630
  if ( !(r->flags & CHECKED) )
619
- checkline(r);
631
+ checkline(r, flags);
620
632
 
621
633
  if ( kind )
622
634
  return (r->kind == kind) && (r->count >= size);
@@ -625,7 +637,7 @@ iscodefence(Line *r, int size, line_type kind)
625
637
  }
626
638
 
627
639
  static Paragraph *
628
- fencedcodeblock(ParagraphRoot *d, Line **ptr)
640
+ fencedcodeblock(ParagraphRoot *d, Line **ptr, DWORD flags)
629
641
  {
630
642
  Line *first, *r;
631
643
  Paragraph *ret;
@@ -634,14 +646,14 @@ fencedcodeblock(ParagraphRoot *d, Line **ptr)
634
646
 
635
647
  /* don't allow zero-length code fences
636
648
  */
637
- if ( (first->next == 0) || iscodefence(first->next, first->count, 0) )
649
+ if ( (first->next == 0) || iscodefence(first->next, first->count, 0, flags) )
638
650
  return 0;
639
651
 
640
652
  /* find the closing fence, discard the fences,
641
653
  * return a Paragraph with the contents
642
654
  */
643
655
  for ( r = first; r && r->next; r = r->next )
644
- if ( iscodefence(r->next, first->count, first->kind) ) {
656
+ if ( iscodefence(r->next, first->count, first->kind, flags) ) {
645
657
  (*ptr) = r->next->next;
646
658
  ret = Pp(d, first->next, CODE);
647
659
  if (S(first->text) - first->count > 0) {
@@ -659,7 +671,6 @@ fencedcodeblock(ParagraphRoot *d, Line **ptr)
659
671
  }
660
672
  return 0;
661
673
  }
662
- #endif
663
674
 
664
675
 
665
676
  static int
@@ -685,7 +696,7 @@ endoftextblock(Line *t, int toplevelblock, DWORD flags)
685
696
  {
686
697
  int z;
687
698
 
688
- if ( end_of_block(t) || isquote(t) )
699
+ if ( end_of_block(t, flags) || isquote(t) )
689
700
  return 1;
690
701
 
691
702
  /* HORRIBLE STANDARDS KLUDGES:
@@ -847,6 +858,12 @@ listitem(Paragraph *p, int indent, DWORD flags, linefn check)
847
858
  UNCHECK(t);
848
859
  t->dle = mkd_firstnonblank(t);
849
860
 
861
+ /* even though we had to trim a long leader off this item,
862
+ * the indent for trailing paragraphs is still 4...
863
+ */
864
+ if (indent > 4) {
865
+ indent = 4;
866
+ }
850
867
  if ( (q = skipempty(t->next)) == 0 ) {
851
868
  ___mkd_freeLineRange(t,q);
852
869
  return 0;
@@ -868,9 +885,9 @@ listitem(Paragraph *p, int indent, DWORD flags, linefn check)
868
885
  indent = clip ? clip : 2;
869
886
  }
870
887
 
871
- if ( (q->dle < indent) && (ishr(q) || islist(q,&z,flags,&z)
888
+ if ( (q->dle < indent) && (ishr(q,flags) || islist(q,&z,flags,&z)
872
889
  || (check && (*check)(q)))
873
- && !issetext(q,&z) ) {
890
+ && !issetext(q,&z,flags) ) {
874
891
  q = t->next;
875
892
  t->next = 0;
876
893
  return q;
@@ -892,7 +909,7 @@ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
892
909
 
893
910
  while (( labels = q )) {
894
911
 
895
- if ( (q = isdefinition(labels, &z, &kind)) == 0 )
912
+ if ( (q = isdefinition(labels, &z, &kind, f->flags)) == 0 )
896
913
  break;
897
914
 
898
915
  if ( (text = skipempty(q->next)) == 0 )
@@ -998,7 +1015,7 @@ addfootnote(Line *p, MMIOT* f)
998
1015
  int c;
999
1016
  Line *np = p->next;
1000
1017
 
1001
- Footnote *foot = &EXPAND(*f->footnotes);
1018
+ Footnote *foot = &EXPAND(f->footnotes->note);
1002
1019
 
1003
1020
  CREATE(foot->tag);
1004
1021
  CREATE(foot->link);
@@ -1013,6 +1030,7 @@ addfootnote(Line *p, MMIOT* f)
1013
1030
  j = nextnonblank(p, j+2);
1014
1031
 
1015
1032
  if ( (f->flags & MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) {
1033
+ /* need to consume all lines until non-indented block? */
1016
1034
  while ( j < S(p->text) )
1017
1035
  EXPAND(foot->title) = T(p->text)[j++];
1018
1036
  goto skip_to_end;
@@ -1243,11 +1261,9 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1243
1261
 
1244
1262
  ptr = codeblock(p);
1245
1263
  }
1246
- #if WITH_FENCED_CODE
1247
- else if ( iscodefence(ptr,3,0) && (p=fencedcodeblock(&d, &ptr)) )
1264
+ else if ( iscodefence(ptr,3,0,f->flags) && (p=fencedcodeblock(&d, &ptr, f->flags)) )
1248
1265
  /* yay, it's already done */ ;
1249
- #endif
1250
- else if ( ishr(ptr) ) {
1266
+ else if ( ishr(ptr, f->flags) ) {
1251
1267
  p = Pp(&d, 0, HR);
1252
1268
  r = ptr;
1253
1269
  ptr = ptr->next;
@@ -1269,7 +1285,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1269
1285
  p->down = compile(p->text, 1, f);
1270
1286
  p->text = 0;
1271
1287
  }
1272
- else if ( ishdr(ptr, &hdr_type) ) {
1288
+ else if ( ishdr(ptr, &hdr_type, f->flags) ) {
1273
1289
  p = Pp(&d, ptr, HDR);
1274
1290
  ptr = headerblock(p, hdr_type);
1275
1291
  }
@@ -1310,23 +1326,34 @@ mkd_compile(Document *doc, DWORD flags)
1310
1326
  if ( !doc )
1311
1327
  return 0;
1312
1328
 
1313
- if ( doc->compiled )
1314
- return 1;
1329
+ flags &= USER_FLAGS;
1330
+
1331
+ if ( doc->compiled ) {
1332
+ if ( doc->ctx->flags == flags )
1333
+ return 1;
1334
+ else {
1335
+ if ( doc->code)
1336
+ ___mkd_freeParagraph(doc->code);
1337
+ if ( doc->ctx->footnotes )
1338
+ ___mkd_freefootnotes(doc->ctx);
1339
+ }
1340
+ }
1315
1341
 
1316
1342
  doc->compiled = 1;
1317
1343
  memset(doc->ctx, 0, sizeof(MMIOT) );
1318
1344
  doc->ctx->ref_prefix= doc->ref_prefix;
1319
1345
  doc->ctx->cb = &(doc->cb);
1320
- doc->ctx->flags = flags & USER_FLAGS;
1346
+ doc->ctx->flags = flags;
1321
1347
  CREATE(doc->ctx->in);
1322
1348
  doc->ctx->footnotes = malloc(sizeof doc->ctx->footnotes[0]);
1323
- CREATE(*doc->ctx->footnotes);
1349
+ doc->ctx->footnotes->reference = 0;
1350
+ CREATE(doc->ctx->footnotes->note);
1324
1351
 
1325
1352
  mkd_initialize();
1326
1353
 
1327
1354
  doc->code = compile_document(T(doc->content), doc->ctx);
1328
- qsort(T(*doc->ctx->footnotes), S(*doc->ctx->footnotes),
1329
- sizeof T(*doc->ctx->footnotes)[0],
1355
+ qsort(T(doc->ctx->footnotes->note), S(doc->ctx->footnotes->note),
1356
+ sizeof T(doc->ctx->footnotes->note)[0],
1330
1357
  (stfu)__mkd_footsort);
1331
1358
  memset(&doc->content, 0, sizeof doc->content);
1332
1359
  return 1;
@@ -88,6 +88,12 @@ struct escaped {
88
88
  } ;
89
89
 
90
90
 
91
+ struct footnote_list {
92
+ int reference;
93
+ STRING(Footnote) note;
94
+ } ;
95
+
96
+
91
97
  /* a magic markdown io thing holds all the data structures needed to
92
98
  * do the backend processing of a markdown document
93
99
  */
@@ -96,10 +102,9 @@ typedef struct mmiot {
96
102
  Cstring in;
97
103
  Qblock Q;
98
104
  int isp;
99
- int reference;
100
105
  struct escaped *esc;
101
106
  char *ref_prefix;
102
- STRING(Footnote) *footnotes;
107
+ struct footnote_list *footnotes;
103
108
  DWORD flags;
104
109
  #define MKD_NOLINKS 0x00000001
105
110
  #define MKD_NOIMAGE 0x00000002
@@ -124,14 +129,23 @@ typedef struct mmiot {
124
129
  #define MKD_NODLIST 0x00100000
125
130
  #define MKD_EXTRA_FOOTNOTE 0x00200000
126
131
  #define MKD_NOSTYLE 0x00400000
127
- #define IS_LABEL 0x08000000
128
- #define USER_FLAGS 0x0FFFFFFF
132
+ #define MKD_NODLDISCOUNT 0x00800000
133
+ #define MKD_DLEXTRA 0x01000000
134
+ #define MKD_FENCEDCODE 0x02000000
135
+ #define MKD_IDANCHOR 0x04000000
136
+ #define MKD_GITHUBTAGS 0x08000000
137
+ #define MKD_URLENCODEDANCHOR 0x10000000
138
+ #define IS_LABEL 0x20000000
139
+ #define USER_FLAGS 0x3FFFFFFF
129
140
  #define INPUT_MASK (MKD_NOHEADER|MKD_TABSTOP)
130
141
 
131
142
  Callback_data *cb;
132
143
  } MMIOT;
133
144
 
134
145
 
146
+ #define MKD_EOLN 3
147
+
148
+
135
149
  /*
136
150
  * the mkdio text input functions return a document structure,
137
151
  * which contains a header (retrieved from the document if
@@ -182,7 +196,7 @@ extern int mkd_generateline(char *, int, FILE*, DWORD);
182
196
  extern void mkd_basename(Document*, char *);
183
197
 
184
198
  typedef int (*mkd_sta_function_t)(const int,const void*);
185
- extern void mkd_string_to_anchor(char*,int, mkd_sta_function_t, void*, int);
199
+ extern void mkd_string_to_anchor(char*,int, mkd_sta_function_t, void*, int, DWORD);
186
200
 
187
201
  extern Document *mkd_in(FILE *, DWORD);
188
202
  extern Document *mkd_string(const char*,int, DWORD);
@@ -216,4 +230,9 @@ extern void __mkd_header_dle(Line *);
216
230
 
217
231
  extern int __mkd_io_strget(struct string_stream *);
218
232
 
233
+ /* utility function to do some operation and exit the current function
234
+ * if it fails
235
+ */
236
+ #define DO_OR_DIE(op) if ( (op) == EOF ) return EOF; else 1
237
+
219
238
  #endif/*_MARKDOWN_D*/