Fossil

Check-in [97b28feae3]
Login

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

Overview
Comment:Fix a minor footnotes-related bug that was discovered by Stephan: if a free-standing footnote reference follows immediately after the exclamation mark then parse that as a footnote (and not as an image). This check-in also postpones initialization of a few local variables within <code>char_link()</code> function (which may save a few CPU cycles).
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 97b28feae320b8f1ff00e3f794f28ac9d12e644240f6a8fb3e50c980bf1e54c3
User & Date: george 2022-06-22 12:35:58.505
Context
2022-06-22
13:33
Add an option to the 'timeline' command to display only items on a specific branch. check-in: 213ca339c2 user: danield tags: trunk
12:35
Fix a minor footnotes-related bug that was discovered by Stephan: if a free-standing footnote reference follows immediately after the exclamation mark then parse that as a footnote (and not as an image). This check-in also postpones initialization of a few local variables within <code>char_link()</code> function (which may save a few CPU cycles). check-in: 97b28feae3 user: george tags: trunk
11:11
In directory/repolist mode, do not link to X/Y.fossil if X.fossil exists, to avoid the X/Y/... URI ambiguity. Reported in [forum:f50f647c97c72fc1 | forum post f50f647c97c72fc1]. check-in: 9584806cc6 user: stephan tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/markdown.c.
1303
1304
1305
1306
1307
1308
1309

1310
1311
1312
1313
1314
1315
1316
1317
1318

1319
1320

1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332

1333

1334
1335
1336
1337
1338
1339
1340
static size_t char_link(
  struct Blob *ob,
  struct render *rndr,
  char *data,
  size_t offset,
  size_t size     /* parse_inline() ensures that size > 0 */
){

  const int is_img = (offset && data[-1] == '!');
  size_t i = 1, txt_e;
  struct Blob *content = 0;
  struct Blob *link = 0;
  struct Blob *title = 0;
  struct footnote fn;
  int ret;

  /* checking whether the correct renderer exists */

  if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){
    return 0;

  }

  /* looking for the matching closing bracket */
  txt_e = matching_bracket_offset(data, data+size);
  if( !txt_e ) return 0;
  i = txt_e + 1;
  ret = 0; /* error if we don't get to the callback */
  fn.nUsed = 0;

  /* free-standing footnote refernece */
  if(!is_img && size>3 && data[1]=='^'){
    fn = get_footnote(rndr, data+2, txt_e-2);

  }else{


    /* skip "inter-bracket-whitespace" - any amount of whitespace or newline */
    /* (this is much more lax than original markdown syntax) */
    while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }

    /* allocate temporary buffers to store content, link and title */
    title = new_work_buffer(rndr);







>
|
|
|
|
|




>
|
|
>







<

|
|

>

>







1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
static size_t char_link(
  struct Blob *ob,
  struct render *rndr,
  char *data,
  size_t offset,
  size_t size     /* parse_inline() ensures that size > 0 */
){
  const int bFsfn = (size>3 && data[1]=='^'); /*free-standing footnote ref*/
  const int bImg = !bFsfn && (offset && data[-1] == '!');
  size_t i, txt_e;
  struct Blob *content;
  struct Blob *link;
  struct Blob *title;
  struct footnote fn;
  int ret;

  /* checking whether the correct renderer exists */
  if( !bFsfn ){
    if( (bImg && !rndr->make.image) || (!bImg && !rndr->make.link) ){
      return 0;
    }
  }

  /* looking for the matching closing bracket */
  txt_e = matching_bracket_offset(data, data+size);
  if( !txt_e ) return 0;
  i = txt_e + 1;
  ret = 0; /* error if we don't get to the callback */


  /* free-standing footnote reference */
  if( bFsfn ){
    fn = get_footnote(rndr, data+2, txt_e-2);
    content = link = title = 0;
  }else{
    fn.nUsed = 0;

    /* skip "inter-bracket-whitespace" - any amount of whitespace or newline */
    /* (this is much more lax than original markdown syntax) */
    while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }

    /* allocate temporary buffers to store content, link and title */
    title = new_work_buffer(rndr);
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
      }
      /* rewinding an "inter-bracket-whitespace" */
      i = txt_e+1;
    }
  }
  /* building content: img alt is escaped, link content is parsed */
  if( txt_e>1 && content ){
    if( is_img ) blob_append(content, data+1, txt_e-1);
    else parse_inline(content, rndr, data+1, txt_e-1);
  }

  /* calling the relevant rendering function */
  if( is_img ){
    if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ){
      ob->nUsed--;
    }
    ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
  }else if( fn.nUsed ){
    if( rndr->make.footnote_ref ){
      ret = rndr->make.footnote_ref(ob, content, &fn.upc, fn.iMark,







|




|







1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
      }
      /* rewinding an "inter-bracket-whitespace" */
      i = txt_e+1;
    }
  }
  /* building content: img alt is escaped, link content is parsed */
  if( txt_e>1 && content ){
    if( bImg ) blob_append(content, data+1, txt_e-1);
    else parse_inline(content, rndr, data+1, txt_e-1);
  }

  /* calling the relevant rendering function */
  if( bImg ){
    if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ){
      ob->nUsed--;
    }
    ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
  }else if( fn.nUsed ){
    if( rndr->make.footnote_ref ){
      ret = rndr->make.footnote_ref(ob, content, &fn.upc, fn.iMark,
Changes to test/markdown-test3.md.
65
66
67
68
69
70
71



72
73
74
75
76
77
78
a "free-standing" footnote followed by another footnote
then interpret as the later case.
This facilitates the usage in the usual case
when several footnotes are refenrenced at the end
of a phrase.[^scipub][^many-refs](^All these four should
be parsed as "free-standing" footnotes)[^Coelurosauria]




A footnote may not be empty(^)
or consist just of blank characters.(^        
              )

The same holds for labeled footnotes. If definition of a labeled footnote
is blank then it is not accepted by the first pass of the parser and
is recognized during the second pass as misreference.







>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
a "free-standing" footnote followed by another footnote
then interpret as the later case.
This facilitates the usage in the usual case
when several footnotes are refenrenced at the end
of a phrase.[^scipub][^many-refs](^All these four should
be parsed as "free-standing" footnotes)[^Coelurosauria]

An ambiguity between a link to an image and a *free-standing referenced
footnote* should be resolved as a footnote![^not-image]

A footnote may not be empty(^)
or consist just of blank characters.(^        
              )

The same holds for labeled footnotes. If definition of a labeled footnote
is blank then it is not accepted by the first pass of the parser and
is recognized during the second pass as misreference.
218
219
220
221
222
223
224




225
226
227
228
229
230
231
   
   (^This is inline note defined inside of [a labeled note][^lost1].)

[^markup]:   E.g. *emphasis*, and [so on](/md_rules).
   BTW, this note may not have a backreference to the "stray".

[^undefined label is used]: For example due to a typo.





[^another stray]: Just to verify the correctness of ordering and styling.

[^scipub]: Which is common in the scientific publications.

[^bare1]:  .at.the.1st.line.of.labeled.footnote.definition:
     







>
>
>
>







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
   
   (^This is inline note defined inside of [a labeled note][^lost1].)

[^markup]:   E.g. *emphasis*, and [so on](/md_rules).
   BTW, this note may not have a backreference to the "stray".

[^undefined label is used]: For example due to a typo.

[^not-image]: The rationale is that URLs do not start with **^**
  while a footnote may follow *immediately* after an exclamation mark
  at the end of a sentence.

[^another stray]: Just to verify the correctness of ordering and styling.

[^scipub]: Which is common in the scientific publications.

[^bare1]:  .at.the.1st.line.of.labeled.footnote.definition: