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

fix: allow Renderer class in marked.use #3118

Merged
merged 1 commit into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/Instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,13 @@ export class Marked {
if (pack.renderer) {
const renderer = this.defaults.renderer || new _Renderer(this.defaults);
for (const prop in pack.renderer) {
if (!(prop in renderer) || prop === 'options') {
if (!(prop in renderer)) {
throw new Error(`renderer '${prop}' does not exist`);
}
if (prop === 'options') {
// ignore options property
continue;
}
const rendererProp = prop as Exclude<keyof _Renderer, 'options'>;
const rendererFunc = pack.renderer[rendererProp] as GenericRendererFunction;
const prevRenderer = renderer[rendererProp] as GenericRendererFunction;
Expand All @@ -162,9 +166,13 @@ export class Marked {
if (pack.tokenizer) {
const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
for (const prop in pack.tokenizer) {
if (!(prop in tokenizer) || ['options', 'rules', 'lexer'].includes(prop)) {
if (!(prop in tokenizer)) {
throw new Error(`tokenizer '${prop}' does not exist`);
}
if (['options', 'rules', 'lexer'].includes(prop)) {
// ignore options, rules, and lexer properties
continue;
}
const tokenizerProp = prop as Exclude<keyof _Tokenizer, 'options' | 'rules' | 'lexer'>;
const tokenizerFunc = pack.tokenizer[tokenizerProp] as UnknownFunction;
const prevTokenizer = tokenizer[tokenizerProp] as UnknownFunction;
Expand All @@ -185,9 +193,13 @@ export class Marked {
if (pack.hooks) {
const hooks = this.defaults.hooks || new _Hooks();
for (const prop in pack.hooks) {
if (!(prop in hooks) || prop === 'options') {
if (!(prop in hooks)) {
throw new Error(`hook '${prop}' does not exist`);
}
if (prop === 'options') {
// ignore options property
continue;
}
const hooksProp = prop as Exclude<keyof _Hooks, 'options'>;
const hooksFunc = pack.hooks[hooksProp] as UnknownFunction;
const prevHook = hooks[hooksProp] as UnknownFunction;
Expand Down
54 changes: 52 additions & 2 deletions test/unit/instance.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { marked, Marked, Renderer } from '../../lib/marked.esm.js';
import { describe, it } from 'node:test';
import { marked, Marked, Renderer, Tokenizer, Hooks } from '../../lib/marked.esm.js';
import { describe, it, beforeEach } from 'node:test';
import assert from 'node:assert';

describe('Marked', () => {
Expand Down Expand Up @@ -89,4 +89,54 @@ describe('Marked', () => {

assert.strictEqual(html, 'test');
});

describe('use class objects', () => {
beforeEach(() => {
marked.setOptions(marked.getDefaults());
});

it('allow new Renderer()', () => {
const marked1 = new Marked();
const newRenderer = new Renderer();
newRenderer.heading = () => 'im marked renderer';

marked1.use({ renderer: newRenderer });
marked.use({ renderer: newRenderer });

assert.strictEqual(marked1.parse('# header'), 'im marked renderer');
assert.strictEqual(marked.parse('# header'), 'im marked renderer');
});

it('allow new Tokenizer()', () => {
const marked1 = new Marked();
const newTokenizer = new Tokenizer();
newTokenizer.heading = function(src) {
return {
type: 'heading',
raw: src,
depth: 1,
text: 'im marked tokenizer',
tokens: this.lexer.inlineTokens('im marked tokenizer')
};
};

marked1.use({ tokenizer: newTokenizer });
marked.use({ tokenizer: newTokenizer });

assert.strictEqual(marked1.parse('# header'), '<h1>im marked tokenizer</h1>\n');
assert.strictEqual(marked.parse('# header'), '<h1>im marked tokenizer</h1>\n');
});

it('allow new Hooks()', () => {
const marked1 = new Marked();
const newHooks = new Hooks();
newHooks.preprocess = () => 'im marked hooks';

marked1.use({ hooks: newHooks });
marked.use({ hooks: newHooks });

assert.strictEqual(marked1.parse('# header'), '<p>im marked hooks</p>\n');
assert.strictEqual(marked.parse('# header'), '<p>im marked hooks</p>\n');
});
});
});