Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Minor code refactoring. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | markdown-footnotes |
Files: | files | file ages | folders |
SHA3-256: |
2636e2245e7ed14fb529cd4ae6352646 |
User & Date: | george 2022-02-04 19:47:39 |
Context
2022-02-04
| ||
23:07 | Handle misreferences: a reference to undefined footnote. ... (check-in: 28e6a9cd user: george tags: markdown-footnotes) | |
19:47 | Minor code refactoring. ... (check-in: 2636e224 user: george tags: markdown-footnotes) | |
19:24 | Automatically render a horizontal rule before the list of footnotes. If desired a particular skin can hide it using CSS selector "hr.footnotes-separator". ... (check-in: 6807b434 user: george tags: markdown-footnotes) | |
Changes
Changes to src/markdown.c.
︙ | ︙ | |||
169 170 171 172 173 174 175 | struct mkd_renderer make; struct Blob refs; char_trigger active_char[256]; int iDepth; /* Depth of recursion */ int nBlobCache; /* Number of entries in aBlobCache */ struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */ | > | | | > | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | struct mkd_renderer make; struct Blob refs; char_trigger active_char[256]; int iDepth; /* Depth of recursion */ int nBlobCache; /* Number of entries in aBlobCache */ struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */ struct { Blob all; /* array of footnotes */ int nLbled; /* number of labeled footnotes found during the first pass */ int nMarks; /* count distinct indices found in the second pass */ } notes; }; /* html_tag -- structure for quick HTML tag search (inspired from discount) */ struct html_tag { const char *text; int size; }; |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | struct render *rndr, const char *data, size_t size ){ struct footnote *fn = NULL; struct Blob *id = new_work_buffer(rndr); if( build_ref_id(id, data, size)<0 ) goto cleanup; | | | | | | | | | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 | struct render *rndr, const char *data, size_t size ){ struct footnote *fn = NULL; struct Blob *id = new_work_buffer(rndr); if( build_ref_id(id, data, size)<0 ) goto cleanup; fn = bsearch(id, blob_buffer(&rndr->notes.all), rndr->notes.nLbled, sizeof (struct footnote), cmp_link_ref); if( !fn ) goto cleanup; if( fn->index == 0 ){ /* the first reference to the footnote */ assert( fn->nUsed == 0 ); fn->index = ++(rndr->notes.nMarks); } fn->nUsed++; assert( fn->index > 0 ); assert( fn->nUsed > 0 ); cleanup: release_work_buffer( rndr, id ); return fn; } /* Adds unlabeled footnote to the rndr. * If text is blank then returns 0, * otherwise returns the address of the added footnote. */ static inline const struct footnote* add_inline_footnote( struct render *rndr, const char *text, size_t size ){ struct footnote fn = { empty_blob, empty_blob, 0, 0 }; while(size && (*text==' ' || *text=='\t')){ text++; size--; } if(!size) return 0; fn.index = ++(rndr->notes.nMarks); fn.nUsed = 1; assert( fn.index > 0 ); 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 |
︙ | ︙ | |||
2451 2452 2453 2454 2455 2456 2457 | /* filling the render structure */ if( !rndrer ) return; rndr.make = *rndrer; rndr.nBlobCache = 0; rndr.iDepth = 0; rndr.refs = empty_blob; | | | | 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 | /* filling the render structure */ if( !rndrer ) return; rndr.make = *rndrer; rndr.nBlobCache = 0; rndr.iDepth = 0; rndr.refs = empty_blob; rndr.notes.all = empty_blob; rndr.notes.nMarks = 0; for(i=0; i<256; i++) rndr.active_char[i] = 0; if( (rndr.make.emphasis || rndr.make.double_emphasis || rndr.make.triple_emphasis) && rndr.make.emph_chars ){ for(i=0; rndr.make.emph_chars[i]; i++){ |
︙ | ︙ | |||
2478 2479 2480 2481 2482 2483 2484 | /* first pass: iterate over lines looking for references, * 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; | | | | | | | | | | | | 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 | /* first pass: iterate over lines looking for references, * 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 */ if( end>beg ) blob_append(&text, data + beg, end - beg); while( end<size && (data[end]=='\n' || data[end]=='\r') ){ /* add one \n per newline */ if( data[end]=='\n' || (end+1<size && data[end+1]!='\n') ){ blob_append_char(&text, '\n'); } end += 1; } beg = end; } } assert( rndr.notes.nMarks==0 ); /* sorting the reference array */ if( blob_size(&rndr.refs) ){ qsort(blob_buffer(&rndr.refs), blob_size(&rndr.refs)/sizeof(struct link_ref), sizeof(struct link_ref), cmp_link_ref_sort); } rndr.notes.nLbled = COUNT_FOOTNOTES(&rndr.notes.all); /* sorting the footnotes array by id */ if( rndr.notes.nLbled ){ qsort(blob_buffer(&rndr.notes.all), rndr.notes.nLbled, sizeof(struct footnote), cmp_link_ref_sort); } /* second pass: actual rendering */ if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque); parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text)); fn = (struct footnote*)blob_buffer(&rndr.notes.all); if(rndr.notes.nMarks && rndr.make.footnote_item && rndr.make.footnotes){ Blob * one_item = new_work_buffer(&rndr); Blob * all_items = new_work_buffer(&rndr); qsort( fn, COUNT_FOOTNOTES(&rndr.notes.all), sizeof(struct footnote), cmp_footnote_sort /* sort footnotes by index */ ); blob_reset( all_items ); for(i=0; i<rndr.notes.nMarks; i++){ assert( fn[i].index == i+1 ); blob_reset( one_item ); parse_inline( one_item, &rndr, blob_buffer(&fn[i].text), blob_size(&fn[i].text)); rndr.make.footnote_item( all_items, one_item, i+1, fn[i].nUsed, rndr.make.opaque); } |
︙ | ︙ | |||
2549 2550 2551 2552 2553 2554 2555 | end = blob_size(&rndr.refs)/sizeof(struct link_ref); for(i=0; i<end; i++){ blob_reset(&lr[i].id); blob_reset(&lr[i].link); blob_reset(&lr[i].title); } blob_reset(&rndr.refs); | | | | 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 | end = blob_size(&rndr.refs)/sizeof(struct link_ref); for(i=0; i<end; i++){ blob_reset(&lr[i].id); blob_reset(&lr[i].link); blob_reset(&lr[i].title); } blob_reset(&rndr.refs); end = COUNT_FOOTNOTES(&rndr.notes.all); for(i=0; i<end; i++){ if(blob_size(&fn[i].id)) blob_reset(&fn[i].id); blob_reset(&fn[i].text); } blob_reset(&rndr.notes.all); for(i=0; i<rndr.nBlobCache; i++){ fossil_free(rndr.aBlobCache[i]); } } |