1 | const Lexer = require('./Lexer.js');
|
2 | const Parser = require('./Parser.js');
|
3 | const Tokenizer = require('./Tokenizer.js');
|
4 | const Renderer = require('./Renderer.js');
|
5 | const TextRenderer = require('./TextRenderer.js');
|
6 | const Slugger = require('./Slugger.js');
|
7 | const {
|
8 | merge,
|
9 | checkSanitizeDeprecation,
|
10 | escape
|
11 | } = require('./helpers.js');
|
12 | const {
|
13 | getDefaults,
|
14 | changeDefaults,
|
15 | defaults
|
16 | } = require('./defaults.js');
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | function marked(src, opt, callback) {
|
22 |
|
23 | if (typeof src === 'undefined' || src === null) {
|
24 | throw new Error('marked(): input parameter is undefined or null');
|
25 | }
|
26 | if (typeof src !== 'string') {
|
27 | throw new Error('marked(): input parameter is of type '
|
28 | + Object.prototype.toString.call(src) + ', string expected');
|
29 | }
|
30 |
|
31 | if (typeof opt === 'function') {
|
32 | callback = opt;
|
33 | opt = null;
|
34 | }
|
35 |
|
36 | opt = merge({}, marked.defaults, opt || {});
|
37 | checkSanitizeDeprecation(opt);
|
38 |
|
39 | if (callback) {
|
40 | const highlight = opt.highlight;
|
41 | let tokens;
|
42 |
|
43 | try {
|
44 | tokens = Lexer.lex(src, opt);
|
45 | } catch (e) {
|
46 | return callback(e);
|
47 | }
|
48 |
|
49 | const done = function(err) {
|
50 | let out;
|
51 |
|
52 | if (!err) {
|
53 | try {
|
54 | if (opt.walkTokens) {
|
55 | marked.walkTokens(tokens, opt.walkTokens);
|
56 | }
|
57 | out = Parser.parse(tokens, opt);
|
58 | } catch (e) {
|
59 | err = e;
|
60 | }
|
61 | }
|
62 |
|
63 | opt.highlight = highlight;
|
64 |
|
65 | return err
|
66 | ? callback(err)
|
67 | : callback(null, out);
|
68 | };
|
69 |
|
70 | if (!highlight || highlight.length < 3) {
|
71 | return done();
|
72 | }
|
73 |
|
74 | delete opt.highlight;
|
75 |
|
76 | if (!tokens.length) return done();
|
77 |
|
78 | let pending = 0;
|
79 | marked.walkTokens(tokens, function(token) {
|
80 | if (token.type === 'code') {
|
81 | pending++;
|
82 | setTimeout(() => {
|
83 | highlight(token.text, token.lang, function(err, code) {
|
84 | if (err) {
|
85 | return done(err);
|
86 | }
|
87 | if (code != null && code !== token.text) {
|
88 | token.text = code;
|
89 | token.escaped = true;
|
90 | }
|
91 |
|
92 | pending--;
|
93 | if (pending === 0) {
|
94 | done();
|
95 | }
|
96 | });
|
97 | }, 0);
|
98 | }
|
99 | });
|
100 |
|
101 | if (pending === 0) {
|
102 | done();
|
103 | }
|
104 |
|
105 | return;
|
106 | }
|
107 |
|
108 | try {
|
109 | const tokens = Lexer.lex(src, opt);
|
110 | if (opt.walkTokens) {
|
111 | marked.walkTokens(tokens, opt.walkTokens);
|
112 | }
|
113 | return Parser.parse(tokens, opt);
|
114 | } catch (e) {
|
115 | e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
116 | if (opt.silent) {
|
117 | return '<p>An error occurred:</p><pre>'
|
118 | + escape(e.message + '', true)
|
119 | + '</pre>';
|
120 | }
|
121 | throw e;
|
122 | }
|
123 | }
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 | marked.options =
|
130 | marked.setOptions = function(opt) {
|
131 | merge(marked.defaults, opt);
|
132 | changeDefaults(marked.defaults);
|
133 | return marked;
|
134 | };
|
135 |
|
136 | marked.getDefaults = getDefaults;
|
137 |
|
138 | marked.defaults = defaults;
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 | marked.use = function(extension) {
|
145 | const opts = merge({}, extension);
|
146 | if (extension.renderer) {
|
147 | const renderer = marked.defaults.renderer || new Renderer();
|
148 | for (const prop in extension.renderer) {
|
149 | const prevRenderer = renderer[prop];
|
150 | renderer[prop] = (...args) => {
|
151 | let ret = extension.renderer[prop].apply(renderer, args);
|
152 | if (ret === false) {
|
153 | ret = prevRenderer.apply(renderer, args);
|
154 | }
|
155 | return ret;
|
156 | };
|
157 | }
|
158 | opts.renderer = renderer;
|
159 | }
|
160 | if (extension.tokenizer) {
|
161 | const tokenizer = marked.defaults.tokenizer || new Tokenizer();
|
162 | for (const prop in extension.tokenizer) {
|
163 | const prevTokenizer = tokenizer[prop];
|
164 | tokenizer[prop] = (...args) => {
|
165 | let ret = extension.tokenizer[prop].apply(tokenizer, args);
|
166 | if (ret === false) {
|
167 | ret = prevTokenizer.apply(tokenizer, args);
|
168 | }
|
169 | return ret;
|
170 | };
|
171 | }
|
172 | opts.tokenizer = tokenizer;
|
173 | }
|
174 | if (extension.walkTokens) {
|
175 | const walkTokens = marked.defaults.walkTokens;
|
176 | opts.walkTokens = (token) => {
|
177 | extension.walkTokens(token);
|
178 | if (walkTokens) {
|
179 | walkTokens(token);
|
180 | }
|
181 | };
|
182 | }
|
183 | marked.setOptions(opts);
|
184 | };
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 | marked.walkTokens = function(tokens, callback) {
|
191 | for (const token of tokens) {
|
192 | callback(token);
|
193 | switch (token.type) {
|
194 | case 'table': {
|
195 | for (const cell of token.tokens.header) {
|
196 | marked.walkTokens(cell, callback);
|
197 | }
|
198 | for (const row of token.tokens.cells) {
|
199 | for (const cell of row) {
|
200 | marked.walkTokens(cell, callback);
|
201 | }
|
202 | }
|
203 | break;
|
204 | }
|
205 | case 'list': {
|
206 | marked.walkTokens(token.items, callback);
|
207 | break;
|
208 | }
|
209 | default: {
|
210 | if (token.tokens) {
|
211 | marked.walkTokens(token.tokens, callback);
|
212 | }
|
213 | }
|
214 | }
|
215 | }
|
216 | };
|
217 |
|
218 |
|
219 |
|
220 |
|
221 | marked.parseInline = function(src, opt) {
|
222 |
|
223 | if (typeof src === 'undefined' || src === null) {
|
224 | throw new Error('marked.parseInline(): input parameter is undefined or null');
|
225 | }
|
226 | if (typeof src !== 'string') {
|
227 | throw new Error('marked.parseInline(): input parameter is of type '
|
228 | + Object.prototype.toString.call(src) + ', string expected');
|
229 | }
|
230 |
|
231 | opt = merge({}, marked.defaults, opt || {});
|
232 | checkSanitizeDeprecation(opt);
|
233 |
|
234 | try {
|
235 | const tokens = Lexer.lexInline(src, opt);
|
236 | if (opt.walkTokens) {
|
237 | marked.walkTokens(tokens, opt.walkTokens);
|
238 | }
|
239 | return Parser.parseInline(tokens, opt);
|
240 | } catch (e) {
|
241 | e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
242 | if (opt.silent) {
|
243 | return '<p>An error occurred:</p><pre>'
|
244 | + escape(e.message + '', true)
|
245 | + '</pre>';
|
246 | }
|
247 | throw e;
|
248 | }
|
249 | };
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 | marked.Parser = Parser;
|
256 | marked.parser = Parser.parse;
|
257 |
|
258 | marked.Renderer = Renderer;
|
259 | marked.TextRenderer = TextRenderer;
|
260 |
|
261 | marked.Lexer = Lexer;
|
262 | marked.lexer = Lexer.lex;
|
263 |
|
264 | marked.Tokenizer = Tokenizer;
|
265 |
|
266 | marked.Slugger = Slugger;
|
267 |
|
268 | marked.parse = marked;
|
269 |
|
270 | module.exports = marked;
|