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