marked
marked copied to clipboard
Setting options interferes with other "require"-calls to marked.
In my NodeJS-project, marked is used by the main program and by a dependency.
When the main-program calls setOptions, the same options are also applied to the instance that is used by the dependency, because both instances are the same object.
I think, a better way to apply default options, would be like the request-package is doing it.
They create a new instance that is configured with the default options, so the original instance is untouched.
What I will try now, is to clear the cache before and after requiring marked, but that seems like a weak workaround.
idk if this is viable for you, but you could avoid setting options with setOptions and instead pass options to marked as second argument.
I do agree with you that setOptions should return a new marked instance instead! But that is an API change.
Again, I'm not too familiar with working directly with Marked; so, pardon the ignorance. Also, this sounds like the problem with Singletons (especially if they're configurable).
var marked1 = Marked().setOptions();
var marked2 = Marked().setOptions();
Is that not the way things work? Sounds like each package would want to create the instance, at which point you would access via something like:
var package = Package();
package.marked.setOptions();
In either case I'm not sure how much this is on Marked to correct. Will flag it for the 0.6.0 milestone; closing.
A work around is to use
const marked = require('marked');
marked.setOptions(marked.getDefaults());
to make sure that defaults are set to the initial defaults.
The proposed workaround can break those other marked "instances" which is also not good overall.
True. You could also send options as a second parameter to marked to override the defaults just for that call.
const marked = require('marked');
marked(markdown, marked.getDefaults());
I ran into this. As @Feder1co5oave said, the solution is to avoid using marked.setOptions({ renderer: renderer }) and instead pass options inline marked(md, { renderer: renderer }) - worked for me.
I hate to rain on a parade, but this is a really clumsy issue. We did not realize this was happening (singleton instance in the background) and to make matters worse, our test pipeline turns over our server as it runs test cases. We had 3 extensions being added when the module was imported (which occurs on each test-reset) and found we had 1,926 extensions installed because marked has no way to reset existing options and it runs as a singleton.
Long gone are the days of polluting the global namespace with singletons like this. If changing the API is a problem, then maybe provide a method to obtain a separate instance with a new method on the API, for ex:
// Get a local instance...
const localMarked = marked.create({/* options here */);
// get some HTML...
const myHtml = localMarked.parse(myMd);
...if it's helpful to others, you can clear block extensions (and other defaults - just change the property you are editing) by doing the following, but:
- this accesses private code 💣
- you will muck with any other marked instances 💥
if ((marked.defaults as any).extensions?.block?.length) {
(marked.defaults as any).extensions.block = [];
}
...or, reset the defaults with:
const markedDefaults = {
async: false,
baseUrl: null,
breaks: false,
extensions: null,
gfm: true,
headerIds: true,
headerPrefix: "",
highlight: null,
langPrefix: "language-",
mangle: true,
pedantic: false,
renderer: null,
sanitize: false,
sanitizer: null,
silent: false,
smartLists: false,
smartypants: false,
tokenizer: null,
walkTokens: null,
xhtml: false,
};
(marked as any).defaults = {...markedDefaults};
@DLiblik marked.getDefaults() will always return the default options object. You can reset marked with marked.setOptions(marked.getDefaults()).
This is something we have tried changing before with people complaining. It would be great if we can find a way to create an instance without breaking anyone who relys on the singleton.
This is something we have tried changing before with people complaining. It would be great if we can find a way to create an instance without breaking anyone who relys on the singleton.
Wouldn't a create() method as suggested by @DLiblik above work?
@rfgamaral sure. If you want to create a PR and add tests to make sure it is working we could add a create method
fyi we have another issue related to this where I proposed some approaches and also shared a simple workaround that works for my use case. It may be helpful for those struggling in some way, or for those considering making a contribution.