implement a toc label uniquifier

This commit is contained in:
david parsons
2022-03-22 17:01:14 -07:00
parent 5b0d7fd8e8
commit 599617843e
6 changed files with 74 additions and 9 deletions
+4 -5
View File
@@ -183,10 +183,9 @@ Qprintf(MMIOT *f, char *fmt, ...)
/* Qanchor() prints out a suitable-for-id-tag version of a string
*/
static void
Qanchor(struct line *p, MMIOT *f)
Qanchor(char *name, MMIOT *f)
{
mkd_string_to_anchor(T(p->text), S(p->text),
(mkd_sta_function_t)Qchar, f, 1, f);
mkd_string_to_anchor(name, strlen(name), (mkd_sta_function_t)Qchar, f, 1, f);
}
@@ -1528,14 +1527,14 @@ printheader(Paragraph *pp, MMIOT *f)
Qprintf(f, "<h%d", pp->hnumber);
if ( is_flag_set(&f->flags, MKD_TOC) ) {
Qstring(" id=\"", f);
Qanchor(pp->text, f);
Qanchor(pp->label, f);
Qchar('"', f);
}
Qchar('>', f);
} else {
if ( is_flag_set(&f->flags, MKD_TOC) ) {
Qstring("<a name=\"", f);
Qanchor(pp->text, f);
Qanchor(pp->label, f);
Qstring("\"></a>\n", f);
}
Qprintf(f, "<h%d>", pp->hnumber);
+3 -2
View File
@@ -20,8 +20,6 @@
typedef int (*stfu)(const void*,const void*);
typedef ANCHOR(Paragraph) ParagraphRoot;
static Paragraph *Pp(ParagraphRoot *, Line *, int);
static Paragraph *compile(Line *, int, MMIOT *);
@@ -1358,6 +1356,9 @@ compile(Line *ptr, int toplevel, MMIOT *f)
else if ( ishdr(ptr, &hdr_type, &(f->flags) ) ) {
p = Pp(&d, ptr, HDR);
ptr = headerblock(p, hdr_type);
if ( is_flag_set(&(f->flags), MKD_TOC) )
p->label = ___mkd_uniquetag(&d, T(p->text->text),
S(p->text->text));
}
else {
/* either markup or an html block element
+7
View File
@@ -96,6 +96,7 @@ typedef struct paragraph {
struct paragraph *next; /* next paragraph */
struct paragraph *down; /* recompiled contents of this paragraph */
struct line *text; /* all the text in this paragraph */
char *label; /* toc label, uniqued */
char *ident; /* %id% tag for QUOTE */
char *lang; /* lang attribute for CODE */
enum { WHITESPACE=0, CODE, QUOTE, MARKUP,
@@ -108,6 +109,8 @@ typedef struct paragraph {
#define IS_CHECKED 0x02
} Paragraph;
typedef ANCHOR(Paragraph) ParagraphRoot;
enum { ETX, SETEXT }; /* header types */
/* reference-style links (and images) are stored in an array
@@ -288,6 +291,10 @@ extern void __mkd_trim_line(Line *, int);
extern int __mkd_io_strget(struct string_stream *);
/* toc uniquifier
*/
extern char *___mkd_uniquetag(ParagraphRoot *, char *, int);
/* utility function to do some operation and exit the current function
* if it fails
*/
+2
View File
@@ -49,6 +49,8 @@ ___mkd_freeParagraph(Paragraph *p)
___mkd_freeParagraph(p->down);
if (p->text)
___mkd_freeLines(p->text);
if (p->label)
free(p->label);
if (p->ident)
free(p->ident);
if (p->lang)
+23
View File
@@ -91,5 +91,28 @@ try '-T -ftoc,html5anchor' 'html5 multibyte chars' \
<a name="It’s-an-apostrophe"></a>
<h1>It’s an apostrophe</h1>'
summary $0
# Check that the uniquifier works
#
title "uniquifying duplicate headers"
try '-T -ftoc' 'uniquifying duplicate labels' \
'# this
# this' \
'<ul>
<li><a href="#this">this</a></li>
<li><a href="#this_1">this</a></li>
</ul>
<a name="this"></a>
<h1>this</h1>
<a name="this_1"></a>
<h1>this</h1>'
summary $0
exit $rc
+35 -2
View File
@@ -72,8 +72,7 @@ mkd_toc(Document *p, char **doc)
++last_hnumber;
}
Csprintf(&res, "%*s<li><a href=\"#", srcp->hnumber, "");
mkd_string_to_anchor(T(srcp->text->text),
S(srcp->text->text),
mkd_string_to_anchor(srcp->label, strlen(srcp->label),
(mkd_sta_function_t)Csputc,
&res,1,p->ctx);
Csprintf(&res, "\">");
@@ -104,6 +103,40 @@ mkd_toc(Document *p, char **doc)
}
char *
___mkd_uniquetag(ParagraphRoot *pr, char *name, int length)
{
Paragraph *content;
char *label;
int suffix;
int seq = 0;
if ( !(pr && name) ) return 0;
suffix = length;
label = calloc(1, suffix+20);
strcpy(label, name);
restart:
for ( content = T(*pr); content; content = content->next ) {
if ( content->text && content->typ == HDR ) {
if ( content->label && strcmp(label, content->label) == 0 ) {
/* collision; bump trailing sequence and try again
*/
sprintf(label+suffix, "_%d", ++seq);
goto restart;
}
}
}
return label;
}
/* write an header index
*/
int