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 | highlight(token.text, token.lang, function(err, code) {
|
80 | if (err) {
|
81 | return done(err);
|
82 | }
|
83 | if (code != null && code !== token.text) {
|
84 | token.text = code;
|
85 | token.escaped = true;
|
86 | }
|
87 |
|
88 | pending--;
|
89 | if (pending === 0) {
|
90 | done();
|
91 | }
|
92 | });
|
93 | }
|
94 | });
|
95 |
|
96 | if (pending === 0) {
|
97 | done();
|
98 | }
|
99 |
|
100 | return;
|
101 | }
|
102 |
|
103 | try {
|
104 | const tokens = Lexer.lex(src, opt);
|
105 | if (opt.walkTokens) {
|
106 | marked.walkTokens(tokens, opt.walkTokens);
|
107 | }
|
108 | return Parser.parse(tokens, opt);
|
109 | } catch (e) {
|
110 | e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
111 | if (opt.silent) {
|
112 | return '<p>An error occurred:</p><pre>'
|
113 | + escape(e.message + '', true)
|
114 | + '</pre>';
|
115 | }
|
116 | throw e;
|
117 | }
|
118 | }
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | marked.options =
|
125 | marked.setOptions = function(opt) {
|
126 | merge(marked.defaults, opt);
|
127 | changeDefaults(marked.defaults);
|
128 | return marked;
|
129 | };
|
130 |
|
131 | marked.getDefaults = getDefaults;
|
132 |
|
133 | marked.defaults = defaults;
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 | marked.use = function(extension) {
|
140 | const opts = merge({}, extension);
|
141 | if (extension.renderer) {
|
142 | const renderer = marked.defaults.renderer || new Renderer();
|
143 | for (const prop in extension.renderer) {
|
144 | const prevRenderer = renderer[prop];
|
145 | renderer[prop] = (...args) => {
|
146 | let ret = extension.renderer[prop].apply(renderer, args);
|
147 | if (ret === false) {
|
148 | ret = prevRenderer.apply(renderer, args);
|
149 | }
|
150 | return ret;
|
151 | };
|
152 | }
|
153 | opts.renderer = renderer;
|
154 | }
|
155 | if (extension.tokenizer) {
|
156 | const tokenizer = marked.defaults.tokenizer || new Tokenizer();
|
157 | for (const prop in extension.tokenizer) {
|
158 | const prevTokenizer = tokenizer[prop];
|
159 | tokenizer[prop] = (...args) => {
|
160 | let ret = extension.tokenizer[prop].apply(tokenizer, args);
|
161 | if (ret === false) {
|
162 | ret = prevTokenizer.apply(tokenizer, args);
|
163 | }
|
164 | return ret;
|
165 | };
|
166 | }
|
167 | opts.tokenizer = tokenizer;
|
168 | }
|
169 | if (extension.walkTokens) {
|
170 | const walkTokens = marked.defaults.walkTokens;
|
171 | opts.walkTokens = (token) => {
|
172 | extension.walkTokens(token);
|
173 | if (walkTokens) {
|
174 | walkTokens(token);
|
175 | }
|
176 | };
|
177 | }
|
178 | marked.setOptions(opts);
|
179 | };
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 | marked.walkTokens = function(tokens, callback) {
|
186 | for (const token of tokens) {
|
187 | callback(token);
|
188 | switch (token.type) {
|
189 | case 'table': {
|
190 | for (const cell of token.tokens.header) {
|
191 | marked.walkTokens(cell, callback);
|
192 | }
|
193 | for (const row of token.tokens.cells) {
|
194 | for (const cell of row) {
|
195 | marked.walkTokens(cell, callback);
|
196 | }
|
197 | }
|
198 | break;
|
199 | }
|
200 | case 'list': {
|
201 | marked.walkTokens(token.items, callback);
|
202 | break;
|
203 | }
|
204 | default: {
|
205 | if (token.tokens) {
|
206 | marked.walkTokens(token.tokens, callback);
|
207 | }
|
208 | }
|
209 | }
|
210 | }
|
211 | };
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 | marked.Parser = Parser;
|
218 | marked.parser = Parser.parse;
|
219 |
|
220 | marked.Renderer = Renderer;
|
221 | marked.TextRenderer = TextRenderer;
|
222 |
|
223 | marked.Lexer = Lexer;
|
224 | marked.lexer = Lexer.lex;
|
225 |
|
226 | marked.Tokenizer = Tokenizer;
|
227 |
|
228 | marked.Slugger = Slugger;
|
229 |
|
230 | marked.parse = marked;
|
231 |
|
232 | module.exports = marked;
|