UNPKG

5.02 kBJavaScriptView Raw
1const Lexer = require('./Lexer.js');
2const Parser = require('./Parser.js');
3const Tokenizer = require('./Tokenizer.js');
4const Renderer = require('./Renderer.js');
5const TextRenderer = require('./TextRenderer.js');
6const Slugger = require('./Slugger.js');
7const {
8 merge,
9 checkSanitizeDeprecation,
10 escape
11} = require('./helpers.js');
12const {
13 getDefaults,
14 changeDefaults,
15 defaults
16} = require('./defaults.js');
17
18/**
19 * Marked
20 */
21function marked(src, opt, callback) {
22 // throw error in case of non string input
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 * Options
122 */
123
124marked.options =
125marked.setOptions = function(opt) {
126 merge(marked.defaults, opt);
127 changeDefaults(marked.defaults);
128 return marked;
129};
130
131marked.getDefaults = getDefaults;
132
133marked.defaults = defaults;
134
135/**
136 * Use Extension
137 */
138
139marked.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 * Run callback for every token
183 */
184
185marked.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 * Expose
215 */
216
217marked.Parser = Parser;
218marked.parser = Parser.parse;
219
220marked.Renderer = Renderer;
221marked.TextRenderer = TextRenderer;
222
223marked.Lexer = Lexer;
224marked.lexer = Lexer.lex;
225
226marked.Tokenizer = Tokenizer;
227
228marked.Slugger = Slugger;
229
230marked.parse = marked;
231
232module.exports = marked;