diff --git a/src/ReactParser.ts b/src/ReactParser.ts index a67e2f4..c648e21 100644 --- a/src/ReactParser.ts +++ b/src/ReactParser.ts @@ -16,7 +16,8 @@ class ReactParser { } parse(tokens: Token[]): ReactNode[] { - return tokens.map((token) => { + this.renderer.elIdList.push(0); + const result = tokens.map((token) => { switch (token.type) { case 'space': { return null; @@ -33,7 +34,9 @@ class ReactParser { case 'text': { const textToken = token as Tokens.Text; - return textToken.tokens ? this.parseInline(textToken.tokens) : token.text; + return textToken.tokens + ? this.parseInline(textToken.tokens) + : token.text; } case 'blockquote': { @@ -49,7 +52,9 @@ class ReactParser { const listItemChildren = []; if (item.task) { - listItemChildren.push(this.renderer.checkbox(item.checked ?? false)); + listItemChildren.push( + this.renderer.checkbox(item.checked ?? false) + ); } listItemChildren.push(this.parse(item.tokens)); @@ -57,7 +62,11 @@ class ReactParser { return this.renderer.listItem(listItemChildren); }); - return this.renderer.list(children, token.ordered, token.ordered ? token.start : undefined); + return this.renderer.list( + children, + token.ordered, + token.ordered ? token.start : undefined + ); } case 'code': { @@ -71,7 +80,10 @@ class ReactParser { case 'table': { const tableToken = token as Tokens.Table; const headerCells = tableToken.header.map((cell, index) => { - return this.renderer.tableCell(this.parseInline(cell.tokens), { header: true, align: token.align[index] }); + return this.renderer.tableCell(this.parseInline(cell.tokens), { + header: true, + align: token.align[index], + }); }); const headerRow = this.renderer.tableRow(headerCells); @@ -103,10 +115,13 @@ class ReactParser { } } }); + this.renderer.elIdList.pop(); + return result; } parseInline(tokens: Token[] = []): ReactNode[] { - return tokens.map((token) => { + this.renderer.elIdList.push(0); + const result = tokens.map((token) => { switch (token.type) { case 'text': { return this.renderer.text(unescape(token.text)); @@ -154,6 +169,8 @@ class ReactParser { } } }); + this.renderer.elIdList.pop(); + return result; } } diff --git a/src/ReactRenderer.ts b/src/ReactRenderer.ts index cd22340..3ddfca9 100644 --- a/src/ReactRenderer.ts +++ b/src/ReactRenderer.ts @@ -19,7 +19,7 @@ export interface ReactRendererOptions { } class ReactRenderer { - #elId = 0; + elIdList: number[] = []; #options: ReactRendererOptions; constructor(options: ReactRendererOptions = {}) { @@ -32,13 +32,20 @@ class ReactRenderer { const rendererName = key as keyof ReactRenderer; const rendererFunction = value; - if (!this[rendererName] || rendererName === 'elementId' || typeof rendererFunction !== 'function') { + if ( + !this[rendererName] || + rendererName === 'elementId' || + rendererName === 'elIdList' || + typeof rendererFunction !== 'function' + ) { return; } const originalFunction = this[rendererName]; - this[rendererName] = (...args: Parameters) => { + this[rendererName] = ( + ...args: Parameters + ) => { this.#incrementElId(); return rendererFunction.apply(this, args); }; @@ -46,7 +53,11 @@ class ReactRenderer { } } - #h(el: T, children: ReactNode = null, props = {}): ReactElement { + #h( + el: T, + children: ReactNode = null, + props = {} + ): ReactElement { const elProps = { key: `marked-react-${this.elementId}`, }; @@ -56,11 +67,11 @@ class ReactRenderer { } #incrementElId() { - this.#elId += 1; + this.elIdList[this.elIdList.length - 1] += 1; } get elementId() { - return this.#elId; + return this.elIdList.join('-'); } heading(children: ReactNode, level: HeadingLevels) { @@ -96,7 +107,11 @@ class ReactRenderer { } list(children: ReactNode, ordered: boolean, start: number | undefined) { - return this.#h(ordered ? 'ol' : 'ul', children, ordered && start !== 1 ? { start } : {}); + return this.#h( + ordered ? 'ol' : 'ul', + children, + ordered && start !== 1 ? { start } : {} + ); } listItem(children: ReactNode[]) { @@ -104,7 +119,11 @@ class ReactRenderer { } checkbox(checked: ReactNode) { - return this.#h('input', null, { type: 'checkbox', disabled: true, checked }); + return this.#h('input', null, { + type: 'checkbox', + disabled: true, + checked, + }); } table(children: ReactNode[]) {