Fossil SCM

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).

george 2022-06-22 12:35 trunk
Commit 97b28feae320b8f1ff00e3f794f28ac9d12e644240f6a8fb3e50c980bf1e54c3
+16 -12
--- src/markdown.c
+++ src/markdown.c
@@ -1305,34 +1305,38 @@
13051305
struct render *rndr,
13061306
char *data,
13071307
size_t offset,
13081308
size_t size /* parse_inline() ensures that size > 0 */
13091309
){
1310
- const int is_img = (offset && data[-1] == '!');
1311
- size_t i = 1, txt_e;
1312
- struct Blob *content = 0;
1313
- struct Blob *link = 0;
1314
- struct Blob *title = 0;
1310
+ const int bFsfn = (size>3 && data[1]=='^'); /*free-standing footnote ref*/
1311
+ const int bImg = !bFsfn && (offset && data[-1] == '!');
1312
+ size_t i, txt_e;
1313
+ struct Blob *content;
1314
+ struct Blob *link;
1315
+ struct Blob *title;
13151316
struct footnote fn;
13161317
int ret;
13171318
13181319
/* checking whether the correct renderer exists */
1319
- if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){
1320
- return 0;
1320
+ if( !bFsfn ){
1321
+ if( (bImg && !rndr->make.image) || (!bImg && !rndr->make.link) ){
1322
+ return 0;
1323
+ }
13211324
}
13221325
13231326
/* looking for the matching closing bracket */
13241327
txt_e = matching_bracket_offset(data, data+size);
13251328
if( !txt_e ) return 0;
13261329
i = txt_e + 1;
13271330
ret = 0; /* error if we don't get to the callback */
1328
- fn.nUsed = 0;
13291331
1330
- /* free-standing footnote refernece */
1331
- if(!is_img && size>3 && data[1]=='^'){
1332
+ /* free-standing footnote reference */
1333
+ if( bFsfn ){
13321334
fn = get_footnote(rndr, data+2, txt_e-2);
1335
+ content = link = title = 0;
13331336
}else{
1337
+ fn.nUsed = 0;
13341338
13351339
/* skip "inter-bracket-whitespace" - any amount of whitespace or newline */
13361340
/* (this is much more lax than original markdown syntax) */
13371341
while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
13381342
@@ -1399,16 +1403,16 @@
13991403
i = txt_e+1;
14001404
}
14011405
}
14021406
/* building content: img alt is escaped, link content is parsed */
14031407
if( txt_e>1 && content ){
1404
- if( is_img ) blob_append(content, data+1, txt_e-1);
1408
+ if( bImg ) blob_append(content, data+1, txt_e-1);
14051409
else parse_inline(content, rndr, data+1, txt_e-1);
14061410
}
14071411
14081412
/* calling the relevant rendering function */
1409
- if( is_img ){
1413
+ if( bImg ){
14101414
if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ){
14111415
ob->nUsed--;
14121416
}
14131417
ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
14141418
}else if( fn.nUsed ){
14151419
--- src/markdown.c
+++ src/markdown.c
@@ -1305,34 +1305,38 @@
1305 struct render *rndr,
1306 char *data,
1307 size_t offset,
1308 size_t size /* parse_inline() ensures that size > 0 */
1309 ){
1310 const int is_img = (offset && data[-1] == '!');
1311 size_t i = 1, txt_e;
1312 struct Blob *content = 0;
1313 struct Blob *link = 0;
1314 struct Blob *title = 0;
 
1315 struct footnote fn;
1316 int ret;
1317
1318 /* checking whether the correct renderer exists */
1319 if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){
1320 return 0;
 
 
1321 }
1322
1323 /* looking for the matching closing bracket */
1324 txt_e = matching_bracket_offset(data, data+size);
1325 if( !txt_e ) return 0;
1326 i = txt_e + 1;
1327 ret = 0; /* error if we don't get to the callback */
1328 fn.nUsed = 0;
1329
1330 /* free-standing footnote refernece */
1331 if(!is_img && size>3 && data[1]=='^'){
1332 fn = get_footnote(rndr, data+2, txt_e-2);
 
1333 }else{
 
1334
1335 /* skip "inter-bracket-whitespace" - any amount of whitespace or newline */
1336 /* (this is much more lax than original markdown syntax) */
1337 while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
1338
@@ -1399,16 +1403,16 @@
1399 i = txt_e+1;
1400 }
1401 }
1402 /* building content: img alt is escaped, link content is parsed */
1403 if( txt_e>1 && content ){
1404 if( is_img ) blob_append(content, data+1, txt_e-1);
1405 else parse_inline(content, rndr, data+1, txt_e-1);
1406 }
1407
1408 /* calling the relevant rendering function */
1409 if( is_img ){
1410 if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ){
1411 ob->nUsed--;
1412 }
1413 ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
1414 }else if( fn.nUsed ){
1415
--- src/markdown.c
+++ src/markdown.c
@@ -1305,34 +1305,38 @@
1305 struct render *rndr,
1306 char *data,
1307 size_t offset,
1308 size_t size /* parse_inline() ensures that size > 0 */
1309 ){
1310 const int bFsfn = (size>3 && data[1]=='^'); /*free-standing footnote ref*/
1311 const int bImg = !bFsfn && (offset && data[-1] == '!');
1312 size_t i, txt_e;
1313 struct Blob *content;
1314 struct Blob *link;
1315 struct Blob *title;
1316 struct footnote fn;
1317 int ret;
1318
1319 /* checking whether the correct renderer exists */
1320 if( !bFsfn ){
1321 if( (bImg && !rndr->make.image) || (!bImg && !rndr->make.link) ){
1322 return 0;
1323 }
1324 }
1325
1326 /* looking for the matching closing bracket */
1327 txt_e = matching_bracket_offset(data, data+size);
1328 if( !txt_e ) return 0;
1329 i = txt_e + 1;
1330 ret = 0; /* error if we don't get to the callback */
 
1331
1332 /* free-standing footnote reference */
1333 if( bFsfn ){
1334 fn = get_footnote(rndr, data+2, txt_e-2);
1335 content = link = title = 0;
1336 }else{
1337 fn.nUsed = 0;
1338
1339 /* skip "inter-bracket-whitespace" - any amount of whitespace or newline */
1340 /* (this is much more lax than original markdown syntax) */
1341 while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
1342
@@ -1399,16 +1403,16 @@
1403 i = txt_e+1;
1404 }
1405 }
1406 /* building content: img alt is escaped, link content is parsed */
1407 if( txt_e>1 && content ){
1408 if( bImg ) blob_append(content, data+1, txt_e-1);
1409 else parse_inline(content, rndr, data+1, txt_e-1);
1410 }
1411
1412 /* calling the relevant rendering function */
1413 if( bImg ){
1414 if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ){
1415 ob->nUsed--;
1416 }
1417 ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
1418 }else if( fn.nUsed ){
1419
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -67,10 +67,13 @@
6767
This facilitates the usage in the usual case
6868
when several footnotes are refenrenced at the end
6969
of a phrase.[^scipub][^many-refs](^All these four should
7070
be parsed as "free-standing" footnotes)[^Coelurosauria]
7171
72
+An ambiguity between a link to an image and a *free-standing referenced
73
+footnote* should be resolved as a footnote![^not-image]
74
+
7275
A footnote may not be empty(^)
7376
or consist just of blank characters.(^
7477
)
7578
7679
The same holds for labeled footnotes. If definition of a labeled footnote
@@ -220,10 +223,14 @@
220223
221224
[^markup]: E.g. *emphasis*, and [so on](/md_rules).
222225
BTW, this note may not have a backreference to the "stray".
223226
224227
[^undefined label is used]: For example due to a typo.
228
+
229
+[^not-image]: The rationale is that URLs do not start with **^**
230
+ while a footnote may follow *immediately* after an exclamation mark
231
+ at the end of a sentence.
225232
226233
[^another stray]: Just to verify the correctness of ordering and styling.
227234
228235
[^scipub]: Which is common in the scientific publications.
229236
230237
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -67,10 +67,13 @@
67 This facilitates the usage in the usual case
68 when several footnotes are refenrenced at the end
69 of a phrase.[^scipub][^many-refs](^All these four should
70 be parsed as "free-standing" footnotes)[^Coelurosauria]
71
 
 
 
72 A footnote may not be empty(^)
73 or consist just of blank characters.(^
74 )
75
76 The same holds for labeled footnotes. If definition of a labeled footnote
@@ -220,10 +223,14 @@
220
221 [^markup]: E.g. *emphasis*, and [so on](/md_rules).
222 BTW, this note may not have a backreference to the "stray".
223
224 [^undefined label is used]: For example due to a typo.
 
 
 
 
225
226 [^another stray]: Just to verify the correctness of ordering and styling.
227
228 [^scipub]: Which is common in the scientific publications.
229
230
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -67,10 +67,13 @@
67 This facilitates the usage in the usual case
68 when several footnotes are refenrenced at the end
69 of a phrase.[^scipub][^many-refs](^All these four should
70 be parsed as "free-standing" footnotes)[^Coelurosauria]
71
72 An ambiguity between a link to an image and a *free-standing referenced
73 footnote* should be resolved as a footnote![^not-image]
74
75 A footnote may not be empty(^)
76 or consist just of blank characters.(^
77 )
78
79 The same holds for labeled footnotes. If definition of a labeled footnote
@@ -220,10 +223,14 @@
223
224 [^markup]: E.g. *emphasis*, and [so on](/md_rules).
225 BTW, this note may not have a backreference to the "stray".
226
227 [^undefined label is used]: For example due to a typo.
228
229 [^not-image]: The rationale is that URLs do not start with **^**
230 while a footnote may follow *immediately* after an exclamation mark
231 at the end of a sentence.
232
233 [^another stray]: Just to verify the correctness of ordering and styling.
234
235 [^scipub]: Which is common in the scientific publications.
236
237

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button