mirror of
https://github.com/Orc/discount.git
synced 2026-09-25 04:10:00 +03:00
implement a toc label uniquifier
This commit is contained in:
+4
-5
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user