Fossil

Check-in [33a681eb]
Login

Check-in [33a681eb]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Minor refactoring. Move the definition of BLOB_APPEND_BLOB() macro from markdown_html.c to blob.c so that it could be used outside of markdown_html.c. Also rename it to blob_appendb() for consistency with blob_appendf() and other API. Within markdown.c use that newly available macro where appropriate. Within markdown_html.c use it for footnotes-relevant code. Other invocations of BLOB_APPEND_BLOB() within markdown_html.c are left intact (they use an alias) in order to simplify the potential merge with the trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | markdown-footnotes
Files: files | file ages | folders
SHA3-256: 33a681ebee054f3d0346fbf992f19823120ce23f64ba5fb4b58e12e262803144
User & Date: george 2022-02-23 08:21:38
Original Comment: Minor refactoring. Move the definition of BLOB_APPEND_BLOB() macro from markdown_html.c to blob.c so that it could be used outside of markdown_html.c. Also rename it to blob_appendb for consistency with blob_appendf() and other API. Within markdown.c use that newly available macro where appropriate. Within markdown_html.c use it for footnotes-relevant code. Other invocations of BLOB_APPEND_BLOB()markdown_html.c</code are left intact (they use an alias) in order to simplify the potential merge with the trunk.
Context
2022-02-23
09:45
Minor refactoring. Move the definition of BLOB_APPEND_LITERAL() macro from markdown_html.c to blob.c so that it could be used outside of markdown_html.c. Also rename it to lowercase for consistency with other API. Within markdown.c use that newly available macro instead of blob_append_string(). Within markdown_html.c use it for footnotes-relevant code. Other invocations of BLOB_APPEND_LITERAL() within markdown_html.c are left intact (they use an alias) in order to simplify the potential merge with the trunk. ... (check-in: c8a8d0c9 user: george tags: markdown-footnotes)
08:21
Minor refactoring. Move the definition of BLOB_APPEND_BLOB() macro from markdown_html.c to blob.c so that it could be used outside of markdown_html.c. Also rename it to blob_appendb() for consistency with blob_appendf() and other API. Within markdown.c use that newly available macro where appropriate. Within markdown_html.c use it for footnotes-relevant code. Other invocations of BLOB_APPEND_BLOB() within markdown_html.c are left intact (they use an alias) in order to simplify the potential merge with the trunk. ... (check-in: 33a681eb user: george tags: markdown-footnotes)
07:36
Fix handling of user-provided classes for unreferenced, joined and overnested footnotes. In all these cases the tokens of user-provided classes are rendered as plain-text and no special classes are added anywhere. ... (check-in: 875472a8 user: george tags: markdown-footnotes)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/blob.c.

51
52
53
54
55
56
57






58
59
60
61
62
63
64
#define blob_size(X)  ((X)->nUsed)

/*
** The buffer holding the blob data
*/
#define blob_buffer(X)  ((X)->aData)







/*
** Seek whence parameter values
*/
#define BLOB_SEEK_SET 1
#define BLOB_SEEK_CUR 2

#endif /* INTERFACE */







>
>
>
>
>
>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#define blob_size(X)  ((X)->nUsed)

/*
** The buffer holding the blob data
*/
#define blob_buffer(X)  ((X)->aData)

/*
** Append blob contents to another
*/
#define blob_appendb(dest, src) \
  blob_append((dest), blob_buffer(src), blob_size(src))

/*
** Seek whence parameter values
*/
#define BLOB_SEEK_SET 1
#define BLOB_SEEK_CUR 2

#endif /* INTERFACE */

Changes to src/markdown.c.

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
               sizeof (struct link_ref),
               cmp_link_ref);
  if( !lr ) return -1;

  /* fill the output buffers */
  blob_reset(link);
  blob_reset(title);
  blob_append(link, blob_buffer(&lr->link), blob_size(&lr->link));
  blob_append(title, blob_buffer(&lr->title), blob_size(&lr->title));
  return 0;
}

/* get_footnote() -- find a footnote by label, invoked during the 2nd pass.
 * On success returns a footnote (after incrementing its nUsed field),
 * otherwise returns NULL */
static const struct footnote* get_footnote(







|
|







1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
               sizeof (struct link_ref),
               cmp_link_ref);
  if( !lr ) return -1;

  /* fill the output buffers */
  blob_reset(link);
  blob_reset(title);
  blob_appendb(link, &lr->link);
  blob_appendb(title, &lr->title);
  return 0;
}

/* get_footnote() -- find a footnote by label, invoked during the 2nd pass.
 * On success returns a footnote (after incrementing its nUsed field),
 * otherwise returns NULL */
static const struct footnote* get_footnote(
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
        blob_reserve(&list, k);
        /* must match _joined_footnote_indicator in html_footnote_item() */
        blob_append_string(&list, "<ul class='fn-joined'>\n");
        for(k=i; k<j; k++){
          struct footnote *y = fn + k;
          blob_append_string(&list, "<li>");
          if( blob_size(&y->upc) ){
            blob_append(&list, blob_buffer(&y->upc), blob_size(&y->upc));
            blob_reset(&y->upc);
          }
          blob_append(&list, blob_buffer(&y->text), blob_size(&y->text));
          blob_append_string(&list, "</li>\n");

          /* free memory buffer */
          blob_reset(&y->text);
          if( k!=i ) blob_reset(&y->id);
        }
        blob_append_string(&list, "</ul>\n");







|


|







2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
        blob_reserve(&list, k);
        /* must match _joined_footnote_indicator in html_footnote_item() */
        blob_append_string(&list, "<ul class='fn-joined'>\n");
        for(k=i; k<j; k++){
          struct footnote *y = fn + k;
          blob_append_string(&list, "<li>");
          if( blob_size(&y->upc) ){
            blob_appendb(&list, &y->upc);
            blob_reset(&y->upc);
          }
          blob_appendb(&list, &y->text);
          blob_append_string(&list, "</li>\n");

          /* free memory buffer */
          blob_reset(&y->text);
          if( k!=i ) blob_reset(&y->id);
        }
        blob_append_string(&list, "</ul>\n");
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
    /* inline notes may get appended to rndr.notes.all while rendering */
    while(1){
      struct footnote *aNotes;
      const int N = COUNT_FOOTNOTES( allNotes );

      /* make a shallow copy of `origin` */
      blob_truncate(notes,0);
      blob_append(notes, blob_buffer(allNotes), blob_size(allNotes));
      aNotes = CAST_AS_FOOTNOTES(notes);
      qsort(aNotes, N, sizeof(struct footnote), cmp_footnote_sort);

      if( --maxDepth < 0 || nMarks == rndr.notes.nMarks ) break;
      nMarks = rndr.notes.nMarks;

      for(i=0; i<N; i++){
        const int j = aNotes[i].index;
        struct footnote *x = CAST_AS_FOOTNOTES(allNotes) + j;
        assert( 0<=j && j<N );
        if( x->bRndred || !x->nUsed ) continue;
        assert( x->iMark > 0 );
        assert( blob_size(&x->text) );
        blob_truncate(tmp,0);

        /* `origin` may be altered and extended through this call */
        parse_inline(tmp, &rndr, blob_buffer(&x->text), blob_size(&x->text));

        blob_truncate(&x->text,0);
        blob_append(&x->text, blob_buffer(tmp), blob_size(tmp));
        x->bRndred = 1;
      }
    }
    release_work_buffer(&rndr,tmp);

    /* footnotes rendering */
    if( rndr.make.footnote_item && rndr.make.footnotes ){







|



















|







2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
    /* inline notes may get appended to rndr.notes.all while rendering */
    while(1){
      struct footnote *aNotes;
      const int N = COUNT_FOOTNOTES( allNotes );

      /* make a shallow copy of `origin` */
      blob_truncate(notes,0);
      blob_appendb(notes, allNotes);
      aNotes = CAST_AS_FOOTNOTES(notes);
      qsort(aNotes, N, sizeof(struct footnote), cmp_footnote_sort);

      if( --maxDepth < 0 || nMarks == rndr.notes.nMarks ) break;
      nMarks = rndr.notes.nMarks;

      for(i=0; i<N; i++){
        const int j = aNotes[i].index;
        struct footnote *x = CAST_AS_FOOTNOTES(allNotes) + j;
        assert( 0<=j && j<N );
        if( x->bRndred || !x->nUsed ) continue;
        assert( x->iMark > 0 );
        assert( blob_size(&x->text) );
        blob_truncate(tmp,0);

        /* `origin` may be altered and extended through this call */
        parse_inline(tmp, &rndr, blob_buffer(&x->text), blob_size(&x->text));

        blob_truncate(&x->text,0);
        blob_appendb(&x->text, tmp);
        x->bRndred = 1;
      }
    }
    release_work_buffer(&rndr,tmp);

    /* footnotes rendering */
    if( rndr.make.footnote_item && rndr.make.footnotes ){

Changes to src/markdown_html.c.

57
58
59
60
61
62
63
64


65
66
67
68
69
70
71
72
73
74
75
76
  blob_append((blob), "" literal, (sizeof literal)-1)
  /*
   * The empty string in the second argument leads to a syntax error
   * when the macro is not used with a string literal. Unfortunately
   * the error is not overly explicit.
   */

/* BLOB_APPEND_BLOB -- append blob contents to another */


#define BLOB_APPEND_BLOB(dest, src) \
  blob_append((dest), blob_buffer(src), blob_size(src))

#ifndef FOOTNOTES_WITHOUT_URI
  #define BLOB_APPEND_URI(dest,ctx) BLOB_APPEND_BLOB(dest,&((ctx)->reqURI))
#else
  #define BLOB_APPEND_URI(dest,ctx)
#endif

/* Converts an integer to a null-terminated base26 representation
 * Return empty string if that integer is negative.   */
static bitfield64_t to_base26(int i, int uppercase){







|
>
>
|
<


|







57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
  blob_append((blob), "" literal, (sizeof literal)-1)
  /*
   * The empty string in the second argument leads to a syntax error
   * when the macro is not used with a string literal. Unfortunately
   * the error is not overly explicit.
   */

/* BLOB_APPEND_BLOB -- append blob contents to another
** TODO: Refactor all invocations to use globall macro blob_appendb()
*/
#define BLOB_APPEND_BLOB(dest, src) blob_appendb((dest), (src))


#ifndef FOOTNOTES_WITHOUT_URI
  #define BLOB_APPEND_URI(dest,ctx) blob_appendb(dest,&((ctx)->reqURI))
#else
  #define BLOB_APPEND_URI(dest,ctx)
#endif

/* Converts an integer to a null-terminated base26 representation
 * Return empty string if that integer is negative.   */
static bitfield64_t to_base26(int i, int uppercase){
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436

    sprintf(pos, "%s-%i-%s", ctx->unique.c, iMark, l.c);
    if(span && blob_size(span)) {
      BLOB_APPEND_LITERAL(ob,"<span class='");
      append_footnote_upc(ob, upc, 0);
      BLOB_APPEND_LITERAL(ob,"notescope' id='noteref");
      blob_appendf(ob,"%s'>",pos);
      BLOB_APPEND_BLOB(ob, span);
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='");
      BLOB_APPEND_URI(ob, ctx);
      blob_appendf(ob,"#footnote%s'>%i</a></sup></span>", pos, iMark);
    }else{
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob,"<sup class='");
      append_footnote_upc(ob, upc, 0);
      BLOB_APPEND_LITERAL(ob,"noteref'><a href='");
      BLOB_APPEND_URI(ob, ctx);
      blob_appendf(ob,"#footnote%s' id='noteref%s'>%i</a></sup>",
                      pos,           pos,  iMark);
    }
  }else{              /* misreference */
    assert( iMark == -1 );

    sprintf(pos, "%s-%s", ctx->unique.c, l.c);
    if(span && blob_size(span)) {
      blob_appendf(ob, "<span class='notescope' id='misref%s'>", pos);
      BLOB_APPEND_BLOB(ob, span);
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
      BLOB_APPEND_URI(ob, ctx);
      blob_appendf(ob, "#misreference%s'>misref</a></sup></span>", pos);
    }else{
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");







|



















|







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

    sprintf(pos, "%s-%i-%s", ctx->unique.c, iMark, l.c);
    if(span && blob_size(span)) {
      BLOB_APPEND_LITERAL(ob,"<span class='");
      append_footnote_upc(ob, upc, 0);
      BLOB_APPEND_LITERAL(ob,"notescope' id='noteref");
      blob_appendf(ob,"%s'>",pos);
      blob_appendb(ob, span);
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='");
      BLOB_APPEND_URI(ob, ctx);
      blob_appendf(ob,"#footnote%s'>%i</a></sup></span>", pos, iMark);
    }else{
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob,"<sup class='");
      append_footnote_upc(ob, upc, 0);
      BLOB_APPEND_LITERAL(ob,"noteref'><a href='");
      BLOB_APPEND_URI(ob, ctx);
      blob_appendf(ob,"#footnote%s' id='noteref%s'>%i</a></sup>",
                      pos,           pos,  iMark);
    }
  }else{              /* misreference */
    assert( iMark == -1 );

    sprintf(pos, "%s-%s", ctx->unique.c, l.c);
    if(span && blob_size(span)) {
      blob_appendf(ob, "<span class='notescope' id='misref%s'>", pos);
      blob_appendb(ob, span);
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
      BLOB_APPEND_URI(ob, ctx);
      blob_appendf(ob, "#misreference%s'>misref</a></sup></span>", pos);
    }else{
      blob_trim(ob);
      BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    }
    BLOB_APPEND_LITERAL(ob,"</sup>\n");
    if( bJoin ){
      BLOB_APPEND_LITERAL(ob,"<sup class='fn-joined'></sup><ul>");
      blob_append(ob,blob_buffer(text)+_jfi_sz,blob_size(text)-_jfi_sz);
    }else if( nUsed ){
      append_footnote_upc(ob, upc, 1);
      BLOB_APPEND_BLOB(ob, text);
    }else{
      BLOB_APPEND_LITERAL(ob,"<i></i>\n"
          "<pre><code class='language-markdown'>");
      if( blob_size(upc) ){
        BLOB_APPEND_BLOB(ob, upc);
      }
      html_escape(ob, blob_buffer(text), blob_size(text));
      BLOB_APPEND_LITERAL(ob,"</code></pre>");
    }
    #undef _joined_footnote_indicator
    #undef _jfi_sz
  }else{             /* a footnote was defined but wasn't referenced */
    /* make.footnote_item() invocations should pass args accordingly */
    const struct Blob * id = text-1;
    assert( !nUsed );
    assert( text );
    assert( blob_size(text) );
    assert( blob_size(id) );
    BLOB_APPEND_LITERAL(ob,"<li class='fn-unreferenced'>\n[^&nbsp;<code>");
    html_escape(ob, blob_buffer(id), blob_size(id));
    BLOB_APPEND_LITERAL(ob, "</code>&nbsp;]<i></i>\n"
        "<pre><code class='language-markdown'>");
    if( blob_size(upc) ){
      BLOB_APPEND_BLOB(ob, upc);
    }
    html_escape(ob, blob_buffer(text), blob_size(text));
    BLOB_APPEND_LITERAL(ob,"</code></pre>");
  }
  BLOB_APPEND_LITERAL(ob, "\n</li>\n");
}
static void html_footnotes(
  struct Blob *ob, const struct Blob *items, void *opaque
){
  if( items && blob_size(items) ){
    BLOB_APPEND_LITERAL(ob,
      "\n<hr class='footnotes-separator'/>\n<ol class='footnotes'>\n");
    BLOB_APPEND_BLOB(ob, items);
    BLOB_APPEND_LITERAL(ob, "</ol>\n");
  }
}

/* HTML span tags */

static int html_raw_html_tag(struct Blob *ob, struct Blob *text, void *opaque){







|




|


















|












|







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
    }
    BLOB_APPEND_LITERAL(ob,"</sup>\n");
    if( bJoin ){
      BLOB_APPEND_LITERAL(ob,"<sup class='fn-joined'></sup><ul>");
      blob_append(ob,blob_buffer(text)+_jfi_sz,blob_size(text)-_jfi_sz);
    }else if( nUsed ){
      append_footnote_upc(ob, upc, 1);
      blob_appendb(ob, text);
    }else{
      BLOB_APPEND_LITERAL(ob,"<i></i>\n"
          "<pre><code class='language-markdown'>");
      if( blob_size(upc) ){
        blob_appendb(ob, upc);
      }
      html_escape(ob, blob_buffer(text), blob_size(text));
      BLOB_APPEND_LITERAL(ob,"</code></pre>");
    }
    #undef _joined_footnote_indicator
    #undef _jfi_sz
  }else{             /* a footnote was defined but wasn't referenced */
    /* make.footnote_item() invocations should pass args accordingly */
    const struct Blob * id = text-1;
    assert( !nUsed );
    assert( text );
    assert( blob_size(text) );
    assert( blob_size(id) );
    BLOB_APPEND_LITERAL(ob,"<li class='fn-unreferenced'>\n[^&nbsp;<code>");
    html_escape(ob, blob_buffer(id), blob_size(id));
    BLOB_APPEND_LITERAL(ob, "</code>&nbsp;]<i></i>\n"
        "<pre><code class='language-markdown'>");
    if( blob_size(upc) ){
      blob_appendb(ob, upc);
    }
    html_escape(ob, blob_buffer(text), blob_size(text));
    BLOB_APPEND_LITERAL(ob,"</code></pre>");
  }
  BLOB_APPEND_LITERAL(ob, "\n</li>\n");
}
static void html_footnotes(
  struct Blob *ob, const struct Blob *items, void *opaque
){
  if( items && blob_size(items) ){
    BLOB_APPEND_LITERAL(ob,
      "\n<hr class='footnotes-separator'/>\n<ol class='footnotes'>\n");
    blob_appendb(ob, items);
    BLOB_APPEND_LITERAL(ob, "</ol>\n");
  }
}

/* HTML span tags */

static int html_raw_html_tag(struct Blob *ob, struct Blob *text, void *opaque){