1 |
|
2 |
|
3 |
|
4 | const escapeTest = /[&<>"']/;
|
5 | const escapeReplace = /[&<>"']/g;
|
6 | const escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
|
7 | const escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
|
8 | const escapeReplacements = {
|
9 | '&': '&',
|
10 | '<': '<',
|
11 | '>': '>',
|
12 | '"': '"',
|
13 | "'": '''
|
14 | };
|
15 | const getEscapeReplacement = (ch) => escapeReplacements[ch];
|
16 | export function escape(html, encode) {
|
17 | if (encode) {
|
18 | if (escapeTest.test(html)) {
|
19 | return html.replace(escapeReplace, getEscapeReplacement);
|
20 | }
|
21 | } else {
|
22 | if (escapeTestNoEncode.test(html)) {
|
23 | return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
|
24 | }
|
25 | }
|
26 |
|
27 | return html;
|
28 | }
|
29 |
|
30 | const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
|
31 |
|
32 | export function unescape(html) {
|
33 |
|
34 | return html.replace(unescapeTest, (_, n) => {
|
35 | n = n.toLowerCase();
|
36 | if (n === 'colon') return ':';
|
37 | if (n.charAt(0) === '#') {
|
38 | return n.charAt(1) === 'x'
|
39 | ? String.fromCharCode(parseInt(n.substring(2), 16))
|
40 | : String.fromCharCode(+n.substring(1));
|
41 | }
|
42 | return '';
|
43 | });
|
44 | }
|
45 |
|
46 | const caret = /(^|[^\[])\^/g;
|
47 | export function edit(regex, opt) {
|
48 | regex = regex.source || regex;
|
49 | opt = opt || '';
|
50 | const obj = {
|
51 | replace: (name, val) => {
|
52 | val = val.source || val;
|
53 | val = val.replace(caret, '$1');
|
54 | regex = regex.replace(name, val);
|
55 | return obj;
|
56 | },
|
57 | getRegex: () => {
|
58 | return new RegExp(regex, opt);
|
59 | }
|
60 | };
|
61 | return obj;
|
62 | }
|
63 |
|
64 | const nonWordAndColonTest = /[^\w:]/g;
|
65 | const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
|
66 | export function cleanUrl(sanitize, base, href) {
|
67 | if (sanitize) {
|
68 | let prot;
|
69 | try {
|
70 | prot = decodeURIComponent(unescape(href))
|
71 | .replace(nonWordAndColonTest, '')
|
72 | .toLowerCase();
|
73 | } catch (e) {
|
74 | return null;
|
75 | }
|
76 | if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
|
77 | return null;
|
78 | }
|
79 | }
|
80 | if (base && !originIndependentUrl.test(href)) {
|
81 | href = resolveUrl(base, href);
|
82 | }
|
83 | try {
|
84 | href = encodeURI(href).replace(/%25/g, '%');
|
85 | } catch (e) {
|
86 | return null;
|
87 | }
|
88 | return href;
|
89 | }
|
90 |
|
91 | const baseUrls = {};
|
92 | const justDomain = /^[^:]+:\/*[^/]*$/;
|
93 | const protocol = /^([^:]+:)[\s\S]*$/;
|
94 | const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
|
95 |
|
96 | export function resolveUrl(base, href) {
|
97 | if (!baseUrls[' ' + base]) {
|
98 |
|
99 |
|
100 |
|
101 | if (justDomain.test(base)) {
|
102 | baseUrls[' ' + base] = base + '/';
|
103 | } else {
|
104 | baseUrls[' ' + base] = rtrim(base, '/', true);
|
105 | }
|
106 | }
|
107 | base = baseUrls[' ' + base];
|
108 | const relativeBase = base.indexOf(':') === -1;
|
109 |
|
110 | if (href.substring(0, 2) === '//') {
|
111 | if (relativeBase) {
|
112 | return href;
|
113 | }
|
114 | return base.replace(protocol, '$1') + href;
|
115 | } else if (href.charAt(0) === '/') {
|
116 | if (relativeBase) {
|
117 | return href;
|
118 | }
|
119 | return base.replace(domain, '$1') + href;
|
120 | } else {
|
121 | return base + href;
|
122 | }
|
123 | }
|
124 |
|
125 | export const noopTest = { exec: function noopTest() {} };
|
126 |
|
127 | export function merge(obj) {
|
128 | let i = 1,
|
129 | target,
|
130 | key;
|
131 |
|
132 | for (; i < arguments.length; i++) {
|
133 | target = arguments[i];
|
134 | for (key in target) {
|
135 | if (Object.prototype.hasOwnProperty.call(target, key)) {
|
136 | obj[key] = target[key];
|
137 | }
|
138 | }
|
139 | }
|
140 |
|
141 | return obj;
|
142 | }
|
143 |
|
144 | export function splitCells(tableRow, count) {
|
145 |
|
146 |
|
147 | const row = tableRow.replace(/\|/g, (match, offset, str) => {
|
148 | let escaped = false,
|
149 | curr = offset;
|
150 | while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
|
151 | if (escaped) {
|
152 |
|
153 |
|
154 | return '|';
|
155 | } else {
|
156 |
|
157 | return ' |';
|
158 | }
|
159 | }),
|
160 | cells = row.split(/ \|/);
|
161 | let i = 0;
|
162 |
|
163 |
|
164 | if (!cells[0].trim()) { cells.shift(); }
|
165 | if (!cells[cells.length - 1].trim()) { cells.pop(); }
|
166 |
|
167 | if (cells.length > count) {
|
168 | cells.splice(count);
|
169 | } else {
|
170 | while (cells.length < count) cells.push('');
|
171 | }
|
172 |
|
173 | for (; i < cells.length; i++) {
|
174 |
|
175 | cells[i] = cells[i].trim().replace(/\\\|/g, '|');
|
176 | }
|
177 | return cells;
|
178 | }
|
179 |
|
180 |
|
181 |
|
182 |
|
183 | export function rtrim(str, c, invert) {
|
184 | const l = str.length;
|
185 | if (l === 0) {
|
186 | return '';
|
187 | }
|
188 |
|
189 |
|
190 | let suffLen = 0;
|
191 |
|
192 |
|
193 | while (suffLen < l) {
|
194 | const currChar = str.charAt(l - suffLen - 1);
|
195 | if (currChar === c && !invert) {
|
196 | suffLen++;
|
197 | } else if (currChar !== c && invert) {
|
198 | suffLen++;
|
199 | } else {
|
200 | break;
|
201 | }
|
202 | }
|
203 |
|
204 | return str.substr(0, l - suffLen);
|
205 | }
|
206 |
|
207 | export function findClosingBracket(str, b) {
|
208 | if (str.indexOf(b[1]) === -1) {
|
209 | return -1;
|
210 | }
|
211 | const l = str.length;
|
212 | let level = 0,
|
213 | i = 0;
|
214 | for (; i < l; i++) {
|
215 | if (str[i] === '\\') {
|
216 | i++;
|
217 | } else if (str[i] === b[0]) {
|
218 | level++;
|
219 | } else if (str[i] === b[1]) {
|
220 | level--;
|
221 | if (level < 0) {
|
222 | return i;
|
223 | }
|
224 | }
|
225 | }
|
226 | return -1;
|
227 | }
|
228 |
|
229 | export function checkSanitizeDeprecation(opt) {
|
230 | if (opt && opt.sanitize && !opt.silent) {
|
231 | console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
|
232 | }
|
233 | }
|
234 |
|
235 |
|
236 | export function repeatString(pattern, count) {
|
237 | if (count < 1) {
|
238 | return '';
|
239 | }
|
240 | let result = '';
|
241 | while (count > 1) {
|
242 | if (count & 1) {
|
243 | result += pattern;
|
244 | }
|
245 | count >>= 1;
|
246 | pattern += pattern;
|
247 | }
|
248 | return result + pattern;
|
249 | }
|