Link label#
If the user decides to generate the table of contents with the anchor links, then link label rules will be applied.
cmark
, github
, gitlab
#
If a line ends in 1 or more ‘' characters, this disrupts the anchor
title. For example - [xdmdmsdm\](#xdmdmsdm)
becomes
<ul><li>[xdmdmsdm](#xdmdmsdm)</li></ul>
instead of
<ul><li><a href="xdmdmsdm">xdmdmsdm\</a></li></ul>
.
The workaround used in md-toc is to add a space character at the end of the
string, so it becomes: <ul><li><a href="xdmdmsdm">xdmdmsdm\ </a></li></ul>
If the link label contains only whitespace characters a GithubEmptyLinkLabel
exception is raised.
If the number of characters inside the link label is over 999 a
GithubOverflowCharsLinkLabel
is raised.
If the headers contains [
or ]
, these characters
are treated with the following rules.
According to a function in the source code, balanced square brackets do not
work, however they do when interpeted by the web interface. It is however
possible that they are supported within the handle_close_bracket
function.
Here is the original C function with some more comments added:
1// Parse a link label. Returns 1 if successful.
2// Note: unescaped brackets are not allowed in labels.
3// The label begins with `[` and ends with the first `]` character
4// encountered. Backticks in labels do not start code spans.
5static int link_label(subject *subj, cmark_chunk *raw_label) {
6 bufsize_t startpos = subj->pos;
7 int length = 0;
8 unsigned char c;
9
10 // advance past [
11 //
12 // Ignore the open link label identifier
13 // peek_char simply returns the current char if we are
14 // in range of the string, 0 otherwise.
15 if (peek_char(subj) == '[') {
16 advance(subj);
17 } else {
18 return 0;
19 }
20
21 while ((c = peek_char(subj)) && c != '[' && c != ']') {
22 // If there is an escape and the next character is (for example)
23 // '[' or ']' then,
24 // ignore the loop conditions.
25 // If there are nested balanced square brakets this loop ends.
26 if (c == '\\') {
27 advance(subj);
28 length++;
29
30 // Puntuation characters are the ones defined at:
31 // https://github.github.com/gfm/#ascii-punctuation-character
32 if (cmark_ispunct(peek_char(subj))) {
33 advance(subj);
34 length++;
35 }
36 } else {
37 advance(subj);
38 length++;
39 }
40 // MAX_LINK_LABEL_LENGTH is a constant defined at
41 // https://github.com/github/cmark/blob/master/src/parser.h#L13
42 if (length > MAX_LINK_LABEL_LENGTH) {
43 goto noMatch;
44 }
45 }
46
47 // If the loop terminates when the current character is ']' then
48 // everything between '[' and ']' is the link label...
49 if (c == ']') { // match found
50 *raw_label =
51 cmark_chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1));
52 cmark_chunk_trim(raw_label);
53 advance(subj); // advance past ]
54 return 1;
55 }
56
57// ...otherwise return error.
58// This label always get executed according to C rules.
59noMatch:
60 subj->pos = startpos; // rewind
61 return 0;
62}
For simpleness the escape [
and ]
rule is used.
redcarpet
#
Let’s inspect this loop:
1/* looking for the matching closing bracket */
2for (level = 1; i < size; i++) {
3 if (data[i] == '\n')
4 text_has_nl = 1;
5
6 else if (data[i - 1] == '\\')
7 continue;
8
9 else if (data[i] == '[')
10 level++;
11
12 else if (data[i] == ']') {
13 level--;
14 if (level <= 0)
15 break;
16 }
17}
18
19if (i >= size)
20 goto cleanup;
The cleanup label looks like this:
1/* cleanup */
2cleanup:
3 rndr->work_bufs[BUFFER_SPAN].size = (int)org_work_size;
4 return ret ? i : 0;
An example: [test \](test \)
becomes [test ](test )
instead of
<a href="test \">test \</a>
Infact, you can see that if the current character is \\
then the the
current iteration is skipped. If for any chance the next character is ]
then the inline link closing parenthesis detection is ignored. i
becomes
equal to size
eventually and so we jump to the cleanup
label.
That lable contains a return statement so that string is not treated as
inline link anymore. A similar code is implemented also for
detecting (
and )
. See:
To solve this we use the same workaround used for cmark
, github
, gitlab
.