-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
85 lines (57 loc) · 2.33 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
'use strict';
const escapeHtml = require('markdown-it/lib/common/utils').escapeHtml;
const EMAIL_RE = /^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/;
module.exports = (md, opts) => {
md.inline.ruler.before('autolink', 'email_autolink', (state, silent) => {
const pos = state.pos;
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
const tail = state.src.slice(pos);
if (!tail.includes('@') || !tail.includes('>')) { return false; }
const emailMatch = tail.match(EMAIL_RE);
if (emailMatch === null) {
return false;
}
const url = emailMatch[1]; // First matching group.
const fullUrl = state.md.normalizeLink('mailto:' + url);
if (!state.md.validateLink(fullUrl)) { return false; }
if (!silent) {
let token = state.push('email_open', 'a', 1);
token.attrs = [ [ 'href', fullUrl ] ];
token.markup = 'autolink';
token.info = 'auto';
token = state.push('email_text', '', 0);
token.content = state.md.normalizeLinkText(url);
token = state.push('email_close', 'a', -1);
token.markup = 'autolink';
token.info = 'auto';
}
state.pos += emailMatch[0].length;
return true;
});
const toEntities = (str) => str.split('')
.map((ch) => `&#${ch.charCodeAt(0)};`)
.join('');
const renderEmailAttrs = function renderEmailAttrs(token) {
if (!token.attrs) { return ''; }
let result = '';
for (let i = 0, l = token.attrs.length; i < l; i++) {
const prop = token.attrs[i][0];
const value = token.attrs[i][1];
result += ' ' + escapeHtml(prop) + '="' + (prop === 'href' ? value : escapeHtml(value)) + '"';
}
return result;
};
md.renderer.rules.email_open = function emailOpen(tokens, idx, options, env, self) {
const linkToken = tokens[idx];
const href = linkToken.attrGet('href');
linkToken.attrSet('href', href.replace(
/^mailto:(.+)/,
(whole, group) => `mailto:${ toEntities(group) }`)
);
return '<a' + renderEmailAttrs(tokens[idx]) + '>';
};
md.renderer.rules.email_text = function emailText(tokens, idx, options, env, self) {
const textToken = tokens[idx];
return textToken.content.replace(/./gim, toEntities);
};
};