From 5c1aa7f3a0c6401284490fa653edb6263049a7e1 Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Fri, 26 Jan 2024 21:02:34 +0800 Subject: [PATCH] fix: fix HTML parsing error (#54) --- src/MarkdownRenderer.tsx | 47 ++++++++++++++++++++++------------- src/icons/Copy.tsx | 3 +++ webpack-md-loader/renderer.js | 12 +++------ 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/MarkdownRenderer.tsx b/src/MarkdownRenderer.tsx index f3b99de..c05f4f9 100644 --- a/src/MarkdownRenderer.tsx +++ b/src/MarkdownRenderer.tsx @@ -2,35 +2,48 @@ import React, { useEffect } from 'react'; import classNames from 'classnames'; import copy from 'copy-to-clipboard'; import mergeRefs from './utils/mergeRefs'; -import { iconPath as copyPath } from './icons/Copy'; +import { iconPath as copyPath, svgTpl } from './icons/Copy'; import { iconPath as checkPath } from './icons/Check'; interface MarkdownRendererProps extends React.HTMLAttributes { children?: string | null; } +function appendCopyButton(container?: HTMLDivElement | null) { + if (!container) { + return; + } + + const button = document.createElement('button'); + button.className = + 'copy-code-button rs-btn-icon rs-btn-icon-circle rs-btn rs-btn-subtle rs-btn-xs'; + button.title = 'Copy code'; + button.innerHTML = svgTpl(copyPath); + button.onclick = e => { + e.preventDefault(); + const code = container?.querySelector('code')?.textContent; + const icon = button.querySelector('.copy-icon-path'); + + icon?.setAttribute('d', checkPath); + if (code) { + copy(code); + } + + setTimeout(() => { + icon?.setAttribute('d', copyPath); + }, 2000); + }; + container?.appendChild(button); +} + const MarkdownRenderer = React.forwardRef( (props: MarkdownRendererProps, ref: React.Ref) => { const { children, className, ...rest } = props; const mdRef = React.useRef(null); useEffect(() => { - mdRef.current?.querySelectorAll('.copy-code-button').forEach(el => { - el.addEventListener('click', e => { - e.preventDefault(); - - const code = (el.nextElementSibling as HTMLInputElement)?.value; - const icon = el.querySelector('.copy-icon-path'); - - icon?.setAttribute('d', checkPath); - if (code) { - copy(code); - } - - setTimeout(() => { - icon?.setAttribute('d', copyPath); - }, 2000); - }); + mdRef.current?.querySelectorAll('.rcv-code-renderer').forEach((el: any) => { + appendCopyButton(el); }); }, []); diff --git a/src/icons/Copy.tsx b/src/icons/Copy.tsx index 7d19c8e..ab12aee 100644 --- a/src/icons/Copy.tsx +++ b/src/icons/Copy.tsx @@ -3,6 +3,9 @@ import React from 'react'; export const iconPath = 'M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z'; +export const svgTpl = (path: string) => + ``; + function CopyIcon(props: React.SVGProps) { return ( { ? hl.highlight(code, { language, ignoreIllegals: true }) : hl.highlightAuto(code); - return `
- - -
${value}
-
`; + return `
${value}
`; }; renderer.code = codeRenderer;