Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async and hooks extensions not working together #2919

Closed
BearToCode opened this issue Aug 6, 2023 · 4 comments · Fixed by #2920
Closed

Async and hooks extensions not working together #2919

BearToCode opened this issue Aug 6, 2023 · 4 comments · Fixed by #2920

Comments

@BearToCode
Copy link

Marked version: 6.0.0

Describe the bug
I have recently updated marked to version 6.0.0. I had to install marked-gfm-heading-id to use heading links, and that caused my app to crash with the following error: src.replace is not a function.

Turns out that this is caused by an attempt to render markdown using { async: false } together with an async extension and one that uses hooks. Here's why:

  1. When rendering content, this.defaults in marked class has async set to true,
  2. At Instance.ts, line 256, markdown is preprocessed,
  3. At Instance.ts, line 178, this.defaults.async makes the preprocesser return a Promise instead of a string.

It seems like the problem is that the optOrCallback passed to parse do not end up affecting the preprocess.

Demo here: https://codesandbox.io/s/marked-async-hooks-bug-7t8wkp?file=/src/index.js:63-84

Expected behavior
App should not crash

@BearToCode BearToCode changed the title Async extensions not working together Async and hooks extensions not working together Aug 6, 2023
@UziTech
Copy link
Member

UziTech commented Aug 6, 2023

the async option is assumed to be true by marked if async is ever true. Which means that you can not change async to true then change async to false. It doesn't make sense for async to be true in some part of marked and false in other parts.

Maybe we should throw an error in this case before trying to parse, but I think this is a clear case of invalid way of using marked.

@BearToCode
Copy link
Author

Thanks for the answer, I know that it is not actually using async extensions, but by using { async: false } I was able to render a html page that could be used in server side renderings, where a top level await is not available. I was hoping that that could still be the case, but I understand that this is kind of an hacky way that may not be wanted.

Aside from a better error message, it would be great to have a way to get marked working in a sync way skipping async extensions, but that's up to you.

@UziTech
Copy link
Member

UziTech commented Aug 6, 2023

I don't understand what you mean skipping async extensions? are you saying you want marked to skip the highlight extensions because it is async and the request was for async = false? We already have way accomplish this by using instances. You can create one marked instance with async extensions and one with only sync extensions. Then just call the one you want:

import { Marked } from 'marked';

const syncMarked = new Marked();
const asyncMarked = new Marked();

syncMarked.use(gfmHeadingId());

asyncMarked.use(gfmHeadingId());
asyncMarked.use(markedHighlight(...));

console.log(syncMarked.parse('...'));
asyncMarked.parse('...').then(html => console.log(html));

@UziTech UziTech closed this as completed Aug 6, 2023
@BearToCode
Copy link
Author

BearToCode commented Aug 6, 2023

I guess I'll use it this way then. Thanks for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants