Fossil

Check-in [a62c8768]
Login

Check-in [a62c8768]

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

Overview
Comment:Clean-up and rephrase some comments.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | markdown-footnotes
Files: files | file ages | folders
SHA3-256: a62c876896ae11002ba464a71fc92ef94a191be617042923dd0dd4db5dd461d3
User & Date: george 2022-02-17 00:17:28
Context
2022-02-17
22:09
If a footnote's text starts with a token of the special form then use this token to derive a set of CSS classes that are added to that footnote and its references. This enables users to style elements of a particular footnote provided that the administrator provisioned and documented some special CSS classes in a custum skin. Default skin does not provide any of such special classes which makes this feature an "opt-in". ... (check-in: 92516ced user: george tags: markdown-footnotes)
00:17
Clean-up and rephrase some comments. ... (check-in: a62c8768 user: george tags: markdown-footnotes)
2022-02-16
23:08
Make parsing slightly faster and fix a comment. No changes in functionality. ... (check-in: a36dd09d user: george tags: markdown-footnotes)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/markdown.c.

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
};

/***************************
 * STATIC HELPER FUNCTIONS *
 ***************************/

/* build_ref_id -- collapse whitespace from input text to make it a ref id */
/* FIXME: does this function handle non-Unix newlines? */
static int build_ref_id(struct Blob *id, const char *data, size_t size){
  size_t beg, i;
  char *id_data;

  /* skip leading whitespace */
  while( size>0 && (data[0]==' ' || data[0]=='\t' || data[0]=='\n') ){
    data++;







|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
};

/***************************
 * STATIC HELPER FUNCTIONS *
 ***************************/

/* build_ref_id -- collapse whitespace from input text to make it a ref id */
/* TODO: maybe also handle CR+LF line endings? */
static int build_ref_id(struct Blob *id, const char *data, size_t size){
  size_t beg, i;
  char *id_data;

  /* skip leading whitespace */
  while( size>0 && (data[0]==' ' || data[0]=='\t' || data[0]=='\n') ){
    data++;
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
  const int szA = blob_size(&a->id), szB = blob_size(&b->id);
  if( szA ){
    if( szB ){
      int cmp = blob_compare(&a->id, &b->id);
      if( cmp ) return cmp;
    }else return -1;
  }else return szB ? 1 : 0;
  /* ids are equal and non-empty */
  if( a->defno < b->defno ) return -1;
  if( a->defno > b->defno ) return  1;

  return 0; /* should never reach here */
}

/* cmp_footnote_sort -- comparison function for footnotes qsort.
 * Unreferenced footnotes (when nUsed == 0) sort last and
 * are sorted in the order of definition in the source */
static int cmp_footnote_sort(const void *fna, const void *fnb){







|


>







282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  const int szA = blob_size(&a->id), szB = blob_size(&b->id);
  if( szA ){
    if( szB ){
      int cmp = blob_compare(&a->id, &b->id);
      if( cmp ) return cmp;
    }else return -1;
  }else return szB ? 1 : 0;
  /* IDs are equal and non-empty */
  if( a->defno < b->defno ) return -1;
  if( a->defno > b->defno ) return  1;
  assert(!"reachable");
  return 0; /* should never reach here */
}

/* cmp_footnote_sort -- comparison function for footnotes qsort.
 * Unreferenced footnotes (when nUsed == 0) sort last and
 * are sorted in the order of definition in the source */
static int cmp_footnote_sort(const void *fna, const void *fnb){
1120
1121
1122
1123
1124
1125
1126
1127





1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  blob_append(&fn.text, text, size);
  blob_append(&rndr->notes.all, (char *)&fn, sizeof fn);
  return (struct footnote*)( blob_buffer(&rndr->notes.all)
                            +( blob_size(&rndr->notes.all)-sizeof fn ));
}

/* Return the offset of the matching closing bracket or 0 if not found.
 * begin[0] must be either '[' or '('          */





static inline size_t matching_bracket_offset(
  const char* begin,
  const char* end
){
  const char *i;
  int level;
  const char bra = *begin;
  const char ket = bra=='[' ? ']' : ')';
  assert( bra=='[' || bra=='(' );      /* FIXME: only when debugging */
  for(i=begin+1,level=1; i!=end; i++){
    if( *i=='\n' )        /* do nothing */;
    else if( i[-1]=='\\' ) continue;   /* ? FIXME: what if \\( ? */
    else if( *i==bra )     level++;
    else if( *i==ket ){
      if( --level<=0 ) return i-begin;
    }
  }
  return 0;
}







|
>
>
>
>
>








|


|







1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
  blob_append(&fn.text, text, size);
  blob_append(&rndr->notes.all, (char *)&fn, sizeof fn);
  return (struct footnote*)( blob_buffer(&rndr->notes.all)
                            +( blob_size(&rndr->notes.all)-sizeof fn ));
}

/* Return the offset of the matching closing bracket or 0 if not found.
** begin[0] must be either '[' or '('
**
** TODO: It seems that things like "\\(" are not handled correctly.
**       That is historical behavior for a corner-case,
**       so it's left as it is until somebody complains.
*/
static inline size_t matching_bracket_offset(
  const char* begin,
  const char* end
){
  const char *i;
  int level;
  const char bra = *begin;
  const char ket = bra=='[' ? ']' : ')';
  assert( bra=='[' || bra=='(' );
  for(i=begin+1,level=1; i!=end; i++){
    if( *i=='\n' )        /* do nothing */;
    else if( i[-1]=='\\' ) continue;
    else if( *i==bra )     level++;
    else if( *i==ket ){
      if( --level<=0 ) return i-begin;
    }
  }
  return 0;
}
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
   && data[i]!=' '
   && data[i]!='\t'
   && data[i]!='\n'
   && data[i]!='\r'
  ){
    i += 1;
  }
  /* ? FIXME: if( data[i-1]=='>' && data[link_offset-1]!='<' ) */
  if( data[i-1]=='>' ) link_end = i-1; else link_end = i;

  /* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
  while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }
  if( i<end
   && data[i]!='\n'
   && data[i]!='\r'







|







2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
   && data[i]!=' '
   && data[i]!='\t'
   && data[i]!='\n'
   && data[i]!='\r'
  ){
    i += 1;
  }
  /* TODO: maybe require both data[i-1]=='>' && data[link_offset-1]=='<' ? */
  if( data[i-1]=='>' ) link_end = i-1; else link_end = i;

  /* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
  while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }
  if( i<end
   && data[i]!='\n'
   && data[i]!='\r'
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
  id_end = i++;

  /* spacer: colon (space | tab)* */
  if( i>=end || data[i]!=':' ) return 0;
  i++;
  while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }

  /* passthrough truncated footnote definition
   * FIXME: maybe omit it? */
  if( i>=end ) return 0;

  if( build_ref_id(&fn.id, data+id_offset, id_end-id_offset)<0 ) return 0;

  /* footnote's text may start on the same line */
  if( data[i]!='\n' && data[i]!='\r' ){
    const size_t j = i;







|
<







2410
2411
2412
2413
2414
2415
2416
2417

2418
2419
2420
2421
2422
2423
2424
  id_end = i++;

  /* spacer: colon (space | tab)* */
  if( i>=end || data[i]!=':' ) return 0;
  i++;
  while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }

  /* passthrough truncated footnote definition */

  if( i>=end ) return 0;

  if( build_ref_id(&fn.id, data+id_offset, id_end-id_offset)<0 ) return 0;

  /* footnote's text may start on the same line */
  if( data[i]!='\n' && data[i]!='\r' ){
    const size_t j = i;
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
   * copying everything else into "text" */
  beg = 0;
  for(const size_t size = blob_size(ib); beg<size ;){
    const char* const data = blob_buffer(ib);
    if( is_ref(data, beg, size, &end, &rndr.refs) ){
      beg = end;
    }else if(is_footnote(data, beg, size, &end, &rndr.notes.all)){
      /* FIXME: fossil_print("\nfootnote found at %i\n", beg); */
      beg = end;
    }else{ /* skipping to the next line */
      end = beg;
      while( end<size && data[end]!='\n' && data[end]!='\r' ){
        end += 1;
      }
      /* adding the line body if present */







<







2529
2530
2531
2532
2533
2534
2535

2536
2537
2538
2539
2540
2541
2542
   * copying everything else into "text" */
  beg = 0;
  for(const size_t size = blob_size(ib); beg<size ;){
    const char* const data = blob_buffer(ib);
    if( is_ref(data, beg, size, &end, &rndr.refs) ){
      beg = end;
    }else if(is_footnote(data, beg, size, &end, &rndr.notes.all)){

      beg = end;
    }else{ /* skipping to the next line */
      end = beg;
      while( end<size && data[end]!='\n' && data[end]!='\r' ){
        end += 1;
      }
      /* adding the line body if present */