Skip to content

Commit b5a5004

Browse files
authored
fix: allow async option to dictate type returned (#3341)
BREAKING CHANGE: throw an error if `async: false` is set when an extension sets `async: true`
1 parent ead7af3 commit b5a5004

File tree

4 files changed

+24
-19
lines changed

4 files changed

+24
-19
lines changed

src/Instance.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ export class Marked {
2121
defaults = _getDefaults();
2222
options = this.setOptions;
2323

24-
parse = this.#parseMarkdown(_Lexer.lex, _Parser.parse);
25-
parseInline = this.#parseMarkdown(_Lexer.lexInline, _Parser.parseInline);
24+
parse = this.parseMarkdown(_Lexer.lex, _Parser.parse);
25+
parseInline = this.parseMarkdown(_Lexer.lexInline, _Parser.parseInline);
2626

2727
Parser = _Parser;
2828
Renderer = _Renderer;
@@ -514,22 +514,25 @@ export class Marked {
514514
return _Parser.parse(tokens, options ?? this.defaults);
515515
}
516516

517-
#parseMarkdown(lexer: (src: string, options?: MarkedOptions) => TokensList | Token[], parser: (tokens: Token[], options?: MarkedOptions) => string) {
518-
return (src: string, options?: MarkedOptions | undefined | null): string | Promise<string> => {
517+
private parseMarkdown(lexer: (src: string, options?: MarkedOptions) => TokensList | Token[], parser: (tokens: Token[], options?: MarkedOptions) => string) {
518+
type overloadedParse = {
519+
(src: string, options: MarkedOptions & { async: true }): Promise<string>;
520+
(src: string, options: MarkedOptions & { async: false }): string;
521+
(src: string, options?: MarkedOptions | undefined | null): string | Promise<string>;
522+
};
523+
524+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
525+
const parse: overloadedParse = (src: string, options?: MarkedOptions | undefined | null): any => {
519526
const origOpt = { ...options };
520527
const opt = { ...this.defaults, ...origOpt };
521528

522-
// Show warning if an extension set async to true but the parse was called with async: false
523-
if (this.defaults.async === true && origOpt.async === false) {
524-
if (!opt.silent) {
525-
console.warn('marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored.');
526-
}
529+
const throwError = this.onError(!!opt.silent, !!opt.async);
527530

528-
opt.async = true;
531+
// throw error if an extension set async to true but parse was called with async: false
532+
if (this.defaults.async === true && origOpt.async === false) {
533+
return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.'));
529534
}
530535

531-
const throwError = this.#onError(!!opt.silent, !!opt.async);
532-
533536
// throw error in case of non string input
534537
if (typeof src === 'undefined' || src === null) {
535538
return throwError(new Error('marked(): input parameter is undefined or null'));
@@ -573,9 +576,11 @@ export class Marked {
573576
return throwError(e as Error);
574577
}
575578
};
579+
580+
return parse;
576581
}
577582

578-
#onError(silent: boolean, async: boolean) {
583+
private onError(silent: boolean, async: boolean) {
579584
return (e: Error): string | Promise<string> => {
580585
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
581586

src/marked.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ export function marked(src: string, options: MarkedOptions & { async: true }): P
3232
* @param options Optional hash of options
3333
* @return String of compiled HTML. Will be a Promise of string if async is set to true by any extensions.
3434
*/
35-
export function marked(src: string, options?: MarkedOptions): string | Promise<string>;
36-
export function marked(src: string, opt?: MarkedOptions): string | Promise<string> {
35+
export function marked(src: string, options: MarkedOptions & { async: false }): string;
36+
export function marked(src: string, options: MarkedOptions & { async: true }): Promise<string>;
37+
export function marked(src: string, options?: MarkedOptions | undefined | null): string | Promise<string>;
38+
export function marked(src: string, opt?: MarkedOptions | undefined | null): string | Promise<string> {
3739
return markedInstance.parse(src, opt);
3840
}
3941

test/types/marked.ts

-2
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ marked.use(asyncExtension);
261261
const md = '# foobar';
262262
const asyncMarked: string = await marked(md, { async: true });
263263
const promiseMarked: Promise<string> = marked(md, { async: true });
264-
// @ts-expect-error marked can still be async if an extension sets `async: true`
265264
const notAsyncMarked: string = marked(md, { async: false });
266265
// @ts-expect-error marked can still be async if an extension sets `async: true`
267266
const defaultMarked: string = marked(md);
@@ -270,7 +269,6 @@ const stringMarked: string = marked(md) as string;
270269

271270
const asyncMarkedParse: string = await marked.parse(md, { async: true });
272271
const promiseMarkedParse: Promise<string> = marked.parse(md, { async: true });
273-
// @ts-expect-error marked can still be async if an extension sets `async: true`
274272
const notAsyncMarkedParse: string = marked.parse(md, { async: false });
275273
// @ts-expect-error marked can still be async if an extension sets `async: true`
276274
const defaultMarkedParse: string = marked.parse(md);

test/unit/marked.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,10 @@ used extension2 walked</p>
630630
assert.strictEqual(typeof marked.parse('test', { async: false }), 'string');
631631
});
632632

633-
it('should return Promise if async is set by extension', () => {
633+
it('should throw an error if async is set by extension', () => {
634634
marked.use({ async: true });
635635

636-
assert.ok(marked.parse('test', { async: false }) instanceof Promise);
636+
assert.throws(() => marked.parse('test', { async: false }));
637637
});
638638

639639
it('should allow deleting/editing tokens', () => {

0 commit comments

Comments
 (0)