Skip to content

Commit

Permalink
Update marked to v6
Browse files Browse the repository at this point in the history
  • Loading branch information
sibiraj-s committed Aug 2, 2023
1 parent bde5a21 commit 82f6141
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 50 deletions.
16 changes: 5 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@
"react": "^16.8.0 || >=17.0.0"
},
"dependencies": {
"@types/marked": "^4.0.7",
"marked": "^4.2.12"
"marked": "^6.0.0"
},
"devDependencies": {
"@commitlint/cli": "^17.6.7",
Expand Down
39 changes: 20 additions & 19 deletions src/Markdown.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { createElement, Fragment } from 'react';
import { Lexer, marked } from 'marked';
import { createElement, Fragment, useRef } from 'react';
import { Marked, MarkedOptions } from 'marked';

import ReactParser from './ReactParser';
import ReactRenderer, { ReactRendererOptions } from './ReactRenderer';

interface LexerOptions {
breaks?: marked.MarkedOptions['breaks'];
gfm?: marked.MarkedOptions['gfm'];
}
type LexerOptions = Pick<MarkedOptions, 'breaks' | 'gfm'>;

export interface MarkdownProps extends ReactRendererOptions, LexerOptions {
value?: string;
children?: string;
isInline?: boolean;
instance?: Marked;
}

const validateComponentProps = (props: MarkdownProps) => {
Expand All @@ -35,34 +33,37 @@ const defaultProps = {
renderer: undefined,
};

const Markdown = (incomingProps: MarkdownProps) => {
const props = { ...defaultProps, ...incomingProps };
const Markdown = (props: MarkdownProps) => {
validateComponentProps(props);

const options = { ...defaultProps, ...props };
const { current: marked } = useRef<Marked>(options.instance ?? new Marked());

// lexer options
const lexerOptions = {
breaks: props.breaks,
gfm: props.gfm,
breaks: options.breaks,
gfm: options.gfm,
};

// convert input markdown into tokens
const markdownString = props.value ?? props.children ?? '';
const tokens = props.isInline
? Lexer.lexInline(markdownString, lexerOptions)
: Lexer.lex(markdownString, lexerOptions);
const markdownString = options.value ?? options.children ?? '';

const tokens = options.isInline
? marked.Lexer.lexInline(markdownString, lexerOptions)
: marked.lexer(markdownString, lexerOptions);

// parser options
const parserOptions = {
renderer: new ReactRenderer({
renderer: props.renderer,
baseURL: props.baseURL,
openLinksInNewTab: props.openLinksInNewTab,
langPrefix: props.langPrefix,
renderer: options.renderer,
baseURL: options.baseURL,
openLinksInNewTab: options.openLinksInNewTab,
langPrefix: options.langPrefix,
}),
};

const parser = new ReactParser(parserOptions);
const children = props.isInline ? parser.parseInline(tokens) : parser.parse(tokens);
const children = options.isInline ? parser.parseInline(tokens) : parser.parse(tokens);

return createElement(Fragment, null, children);
};
Expand Down
14 changes: 7 additions & 7 deletions src/ReactParser.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { unescape } from './helpers';
import { marked } from 'marked';
import { ReactNode } from 'react';
import type { Token, TokensList } from 'marked';

import ReactRenderer, { HeadingLevels } from './ReactRenderer';
import { ReactNode } from 'react';
import { unescape } from './helpers';

interface ReactParserOptions {
renderer: ReactRenderer;
}

export type Tokens = marked.Token[] | marked.TokensList;
export type ParserTokens = Token[] | TokensList;

class ReactParser {
renderer: ReactRenderer;
Expand All @@ -17,7 +17,7 @@ class ReactParser {
this.renderer = options.renderer;
}

parse(tokens: Tokens): ReactNode[] {
parse(tokens: ParserTokens = []): ReactNode[] {
return tokens.map((token) => {
switch (token.type) {
case 'space': {
Expand All @@ -34,7 +34,7 @@ class ReactParser {
}

case 'text': {
const textTokens = (token as marked.Tokens.Text).tokens;
const textTokens = token.tokens;
return textTokens ? this.parseInline(textTokens) : token.text;
}

Expand Down Expand Up @@ -103,7 +103,7 @@ class ReactParser {
});
}

parseInline(tokens: Tokens): ReactNode[] {
parseInline(tokens: ParserTokens = []): ReactNode[] {
return tokens.map((token) => {
switch (token.type) {
case 'text': {
Expand Down
2 changes: 1 addition & 1 deletion src/ReactRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class ReactRenderer {
return this.#h('a', text, { href: url, target });
}

image(src: string, alt: string, title: string) {
image(src: string, alt: string, title: string | null = null) {
const url = joinBase(src, this.#options.baseURL);
return this.#h('img', null, { src: url, alt, title });
}
Expand Down
2 changes: 1 addition & 1 deletion tests/markdown.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const cases = [
html: '<pre><code>&lt;script&gt;console.log(&quot;Hello&quot;)&lt;/script&gt;</code></pre>',
},
{
title: 'render codeblocks with lang code',
title: 'render codeblocks with default lang prefix',
markdown: '```js\nconsole.log("Hello world!")\n```',
html: '<pre><code class="language-js">console.log(&quot;Hello world!&quot;)</code></pre>',
},
Expand Down
16 changes: 7 additions & 9 deletions tests/parser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { describe, expect, it } from 'vitest';

import ReactParser, { Tokens } from '../src/ReactParser';
import ReactParser, { ParserTokens } from '../src/ReactParser';
import ReactRenderer from '../src/ReactRenderer';

const renderer = new ReactRenderer({
baseURL: undefined,
openLinksInNewTab: true,
langPrefix: 'language-',
});

const parser = new ReactParser({ renderer });
Expand All @@ -30,7 +28,7 @@ describe('ReactParser', () => {
},
];

const parsed = parser.parse(tokens as Tokens);
const parsed = parser.parse(tokens as ParserTokens);
expect(parsed.length).toBe(1);
expect(parsed[0]).toEqual('Hello world!');
});
Expand All @@ -43,11 +41,11 @@ describe('ReactParser', () => {
},
];

const parsed = parser.parse(tokens as Tokens);
const parsed = parser.parse(tokens as ParserTokens);
expect(parsed.length).toBe(1);
expect(parsed[0]).toEqual('Hello world!');

const inlineParsed = parser.parseInline(tokens as Tokens);
const inlineParsed = parser.parseInline(tokens as ParserTokens);
expect(inlineParsed.length).toBe(1);
expect(inlineParsed[0]).toEqual('Hello world!');
});
Expand All @@ -59,7 +57,7 @@ describe('ReactParser', () => {
text: '\\',
},
];
const inlineParsed = parser.parseInline(tokens as Tokens);
const inlineParsed = parser.parseInline(tokens as ParserTokens);
expect(inlineParsed.length).toBe(1);
expect(inlineParsed[0]).toEqual('\\');
});
Expand All @@ -71,9 +69,9 @@ describe('ReactParser', () => {
},
];

const parsed = parser.parse(tokens as Tokens);
const parsed = parser.parse(tokens as ParserTokens);
expect(parsed[0]).toEqual(null);
const inlineParsed = parser.parseInline(tokens as Tokens);
const inlineParsed = parser.parseInline(tokens as ParserTokens);
expect(inlineParsed[0]).toEqual(null);
});
});

0 comments on commit 82f6141

Please sign in to comment.