From 042dcc54311dc3bbdce7e8cb90c530f03f980c3a Mon Sep 17 00:00:00 2001 From: Tony Brix Date: Tue, 21 Mar 2023 19:51:45 -0500 Subject: [PATCH] fix: always return promise if async (#2728) * fix: always return promise if async * docs: await walktokens when async * docs: walktokens async Co-authored-by: Steven * return rejected promise on error --------- Co-authored-by: Steven --- docs/USING_PRO.md | 2 +- src/marked.js | 28 +++++++++++++++++++--------- test/unit/marked-spec.js | 10 ++++++++++ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/docs/USING_PRO.md b/docs/USING_PRO.md index b8a4282cfc..c4757e0291 100644 --- a/docs/USING_PRO.md +++ b/docs/USING_PRO.md @@ -262,7 +262,7 @@ smartypants('"this ... string"')

Walk Tokens : walkTokens

-The walkTokens function gets called with every token. Child tokens are called before moving on to sibling tokens. Each token is passed by reference so updates are persisted when passed to the parser. The return value of the function is ignored. +The walkTokens function gets called with every token. Child tokens are called before moving on to sibling tokens. Each token is passed by reference so updates are persisted when passed to the parser. When [`async`](#async) mode is enabled, the return value is awaited. Otherwise the return value is ignored. `marked.use()` can be called multiple times with different `walkTokens` functions. Each function will be called in order, starting with the function that was assigned *last*. diff --git a/src/marked.js b/src/marked.js index 157c8ec2e9..7d5e23dd26 100644 --- a/src/marked.js +++ b/src/marked.js @@ -108,28 +108,38 @@ export function marked(src, opt, callback) { function onError(e) { e.message += '\nPlease report this to https://github.com/markedjs/marked.'; if (opt.silent) { - return '

An error occurred:

'
+      const msg = '

An error occurred:

'
         + escape(e.message + '', true)
         + '
'; + if (opt.async) { + return Promise.resolve(msg); + } + return msg; + } + if (opt.async) { + return Promise.reject(e); } throw e; } try { + if (opt.async) { + let promise = Promise.resolve(Lexer.lex(src, opt)); + if (opt.walkTokens) { + promise = promise.then((tokens) => + Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => tokens) + ); + } + return promise.then((tokens) => Parser.parse(tokens, opt)).catch(onError); + } + const tokens = Lexer.lex(src, opt); if (opt.walkTokens) { - if (opt.async) { - return Promise.all(marked.walkTokens(tokens, opt.walkTokens)) - .then(() => { - return Parser.parse(tokens, opt); - }) - .catch(onError); - } marked.walkTokens(tokens, opt.walkTokens); } return Parser.parse(tokens, opt); } catch (e) { - onError(e); + return onError(e); } } diff --git a/test/unit/marked-spec.js b/test/unit/marked-spec.js index e9bfba1782..4dab6aeaac 100644 --- a/test/unit/marked-spec.js +++ b/test/unit/marked-spec.js @@ -1112,4 +1112,14 @@ br const html = await promise; expect(html.trim()).toBe('

text walked

'); }); + + it('should return promise if async', async() => { + marked.use({ + async: true + }); + const promise = marked('*text*'); + expect(promise).toBeInstanceOf(Promise); + const html = await promise; + expect(html.trim()).toBe('

text

'); + }); });