source: node_modules/remarkable/dist/cjs/linkify.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 4.0 KB
Line 
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var Autolinker = _interopDefault(require('autolinker'));
8
9// Autoconvert URL-like texts to links
10
11
12var LINK_SCAN_RE = /www|@|\:\/\//;
13
14
15function isLinkOpen(str) {
16 return /^<a[>\s]/i.test(str);
17}
18function isLinkClose(str) {
19 return /^<\/a\s*>/i.test(str);
20}
21
22// Stupid fabric to avoid singletons, for thread safety.
23// Required for engines like Nashorn.
24//
25function createLinkifier() {
26 var links = [];
27 var autolinker = new Autolinker({
28 stripPrefix: false,
29 url: true,
30 email: true,
31 replaceFn: function (match) {
32 // Only collect matched strings but don't change anything.
33 switch (match.getType()) {
34 /*eslint default-case:0*/
35 case 'url':
36 links.push({
37 text: match.matchedText,
38 url: match.getUrl()
39 });
40 break;
41 case 'email':
42 links.push({
43 text: match.matchedText,
44 // normalize email protocol
45 url: 'mailto:' + match.getEmail().replace(/^mailto:/i, '')
46 });
47 break;
48 }
49 return false;
50 }
51 });
52
53 return {
54 links: links,
55 autolinker: autolinker
56 };
57}
58
59
60function parseTokens(state) {
61 var i, j, l, tokens, token, text, nodes, ln, pos, level, htmlLinkLevel,
62 blockTokens = state.tokens,
63 linkifier = null, links, autolinker;
64
65 for (j = 0, l = blockTokens.length; j < l; j++) {
66 if (blockTokens[j].type !== 'inline') { continue; }
67 tokens = blockTokens[j].children;
68
69 htmlLinkLevel = 0;
70
71 // We scan from the end, to keep position when new tags added.
72 // Use reversed logic in links start/end match
73 for (i = tokens.length - 1; i >= 0; i--) {
74 token = tokens[i];
75
76 // Skip content of markdown links
77 if (token.type === 'link_close') {
78 i--;
79 while (tokens[i].level !== token.level && tokens[i].type !== 'link_open') {
80 i--;
81 }
82 continue;
83 }
84
85 // Skip content of html tag links
86 if (token.type === 'htmltag') {
87 if (isLinkOpen(token.content) && htmlLinkLevel > 0) {
88 htmlLinkLevel--;
89 }
90 if (isLinkClose(token.content)) {
91 htmlLinkLevel++;
92 }
93 }
94 if (htmlLinkLevel > 0) { continue; }
95
96 if (token.type === 'text' && LINK_SCAN_RE.test(token.content)) {
97
98 // Init linkifier in lazy manner, only if required.
99 if (!linkifier) {
100 linkifier = createLinkifier();
101 links = linkifier.links;
102 autolinker = linkifier.autolinker;
103 }
104
105 text = token.content;
106 links.length = 0;
107 autolinker.link(text);
108
109 if (!links.length) { continue; }
110
111 // Now split string to nodes
112 nodes = [];
113 level = token.level;
114
115 for (ln = 0; ln < links.length; ln++) {
116
117 if (!state.inline.validateLink(links[ln].url)) { continue; }
118
119 pos = text.indexOf(links[ln].text);
120
121 if (pos) {
122 nodes.push({
123 type: 'text',
124 content: text.slice(0, pos),
125 level: level
126 });
127 }
128 nodes.push({
129 type: 'link_open',
130 href: links[ln].url,
131 title: '',
132 level: level++
133 });
134 nodes.push({
135 type: 'text',
136 content: links[ln].text,
137 level: level
138 });
139 nodes.push({
140 type: 'link_close',
141 level: --level
142 });
143 text = text.slice(pos + links[ln].text.length);
144 }
145 if (text.length) {
146 nodes.push({
147 type: 'text',
148 content: text,
149 level: level
150 });
151 }
152
153 // replace current node
154 blockTokens[j].children = tokens = [].concat(tokens.slice(0, i), nodes, tokens.slice(i + 1));
155 }
156 }
157 }
158}
159function linkify(md) {
160 md.core.ruler.push('linkify', parseTokens);
161}
162
163exports.linkify = linkify;
Note: See TracBrowser for help on using the repository browser.