|
| 1 | +diff --git a/cpp/md4c/md4c.c b/cpp/md4c/md4c.c |
| 2 | +--- a/cpp/md4c/md4c.c |
| 3 | ++++ b/cpp/md4c/md4c.c |
| 4 | +@@ -3908,10 +3908,10 @@ |
| 5 | + int min_components; |
| 6 | + const MD_CHAR optional_end_char; |
| 7 | + } URL_MAP[] = { |
| 8 | +- { _T('\0'), _T('.'), _T(".-_"), 2, _T('\0') }, /* host, mandatory */ |
| 9 | +- { _T('/'), _T('/'), _T("/.-_"), 0, _T('/') }, /* path */ |
| 10 | +- { _T('?'), _T('&'), _T("&.-+_=()"), 1, _T('\0') }, /* query */ |
| 11 | +- { _T('#'), _T('\0'), _T(".-+_") , 1, _T('\0') } /* fragment */ |
| 12 | ++ { _T('\0'), _T('.'), _T(".-_"), 2, _T('\0') }, /* host, mandatory */ |
| 13 | ++ { _T('/'), _T('/'), _T("/.-_():~%+@&!,;"), 0, _T('/') }, /* path */ |
| 14 | ++ { _T('?'), _T('&'), _T("&.-+_=().:!~%,;@"), 1, _T('\0') }, /* query */ |
| 15 | ++ { _T('#'), _T('\0'), _T(".-+_:%~") , 1, _T('\0') } /* fragment */ |
| 16 | + }; |
| 17 | + |
| 18 | + MD_MARK* opener = &ctx->marks[mark_index]; |
| 19 | +@@ -3981,8 +3981,11 @@ |
| 20 | + } else if(end < line_end && |
| 21 | + ISANYOF(end, URL_MAP[i].allowed_nonalnum_chars) && |
| 22 | + md_scan_right_for_resolved_mark(ctx, right_cursor, end, &right_cursor) == NULL && |
| 23 | +- ((end > line_beg && (ISALNUM(end-1) || CH(end-1) == _T(')'))) || CH(end) == _T('(')) && |
| 24 | +- ((end+1 < line_end && (ISALNUM(end+1) || CH(end+1) == _T('('))) || CH(end) == _T(')'))) |
| 25 | ++ /* Scheme URLs keep '...' and ':' in the path and query. |
| 26 | ++ * Host, e-mail, and www labels stay flanked by alphanumerics. */ |
| 27 | ++ ((opener->ch == _T(':') && i > 0) || |
| 28 | ++ (((end > line_beg && (ISALNUM(end-1) || CH(end-1) == _T(')'))) || CH(end) == _T('(')) && |
| 29 | ++ ((end+1 < line_end && (ISALNUM(end+1) || CH(end+1) == _T('('))) || CH(end) == _T(')'))))) |
| 30 | + { |
| 31 | + if(CH(end) == URL_MAP[i].delim_char) |
| 32 | + n_components++; |
| 33 | +@@ -4006,16 +4009,35 @@ |
| 34 | + CH(end) == URL_MAP[i].optional_end_char) |
| 35 | + end++; |
| 36 | + |
| 37 | +- if(n_components < URL_MAP[i].min_components || n_open_brackets != 0) |
| 38 | ++ /* Scheme autolinks allow one host label, so localhost and devbox link. |
| 39 | ++ * E-mail and www autolinks still require a dotted host. */ |
| 40 | ++ if(n_components < (i == 0 && opener->ch == ':' ? 1 : URL_MAP[i].min_components) || |
| 41 | ++ n_open_brackets != 0) |
| 42 | + return; |
| 43 | + |
| 44 | ++ /* Optional port on a scheme autolink: ':' followed by digits. */ |
| 45 | ++ if(i == 0 && opener->ch == ':' && end + 1 < line_end && |
| 46 | ++ CH(end) == _T(':') && ISDIGIT(end + 1)) { |
| 47 | ++ end++; |
| 48 | ++ while(end < line_end && ISDIGIT(end)) |
| 49 | ++ end++; |
| 50 | ++ } |
| 51 | ++ |
| 52 | + if(opener->ch == '@') /* E-mail autolinks wants only the host. */ |
| 53 | + break; |
| 54 | ++ } |
| 55 | ++ |
| 56 | ++ /* GFM leaves a trailing run of punctuation outside the link, including |
| 57 | ++ * the sentence dots in "https://example.com/a...". */ |
| 58 | ++ if(opener->ch == _T(':')) { |
| 59 | ++ while(end > opener->end && ISANYOF(end - 1, _T("?!.,:*_~"))) |
| 60 | ++ end--; |
| 61 | + } |
| 62 | + |
| 63 | + /* Verify there's line boundary, whitespace, allowed punctuation or |
| 64 | + * resolved emphasis mark just after the suspected autolink. */ |
| 65 | +- if(end == line_end || ISUNICODEWHITESPACE(end) || ISANYOF(end, _T(")}].!?,;"))) { |
| 66 | ++ if(end == line_end || ISUNICODEWHITESPACE(end) || |
| 67 | ++ ISANYOF(end, opener->ch == _T(':') ? _T(")}].!?,;:*_~'\"`<>") : _T(")}].!?,;"))) { |
| 68 | + right_boundary_ok = TRUE; |
| 69 | + } else { |
| 70 | + MD_MARK* right_mark; |
0 commit comments