rdiscount 2.1.7 → 2.2.0.2

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.
@@ -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*/