mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-07 13:59:28 +08:00
feat: make svg in markdown scalable
This commit is contained in:
parent
66b72e5149
commit
ede226f74d
@ -32,8 +32,6 @@ export function renderSvgInShadowHost(svgContent: string, hostElement: HTMLEleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import { Pluggable } from 'unified'
|
|||||||
import CodeBlock from './CodeBlock'
|
import CodeBlock from './CodeBlock'
|
||||||
import Link from './Link'
|
import Link from './Link'
|
||||||
import rehypeHeadingIds from './plugins/rehypeHeadingIds'
|
import rehypeHeadingIds from './plugins/rehypeHeadingIds'
|
||||||
|
import rehypeScalableSvg from './plugins/rehypeScalableSvg'
|
||||||
import remarkDisableConstructs from './plugins/remarkDisableConstructs'
|
import remarkDisableConstructs from './plugins/remarkDisableConstructs'
|
||||||
import Table from './Table'
|
import Table from './Table'
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ const Markdown: FC<Props> = ({ block, postProcess }) => {
|
|||||||
const rehypePlugins = useMemo(() => {
|
const rehypePlugins = useMemo(() => {
|
||||||
const plugins: Pluggable[] = []
|
const plugins: Pluggable[] = []
|
||||||
if (ALLOWED_ELEMENTS.test(messageContent)) {
|
if (ALLOWED_ELEMENTS.test(messageContent)) {
|
||||||
plugins.push(rehypeRaw)
|
plugins.push(rehypeRaw, rehypeScalableSvg)
|
||||||
}
|
}
|
||||||
plugins.push([rehypeHeadingIds, { prefix: `heading-${block.id}` }])
|
plugins.push([rehypeHeadingIds, { prefix: `heading-${block.id}` }])
|
||||||
if (mathEngine === 'KaTeX') {
|
if (mathEngine === 'KaTeX') {
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
import type { Element, Root } from 'hast'
|
||||||
|
import { visit } from 'unist-util-visit'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Rehype plugin that makes SVG elements scalable.
|
||||||
|
*
|
||||||
|
* This plugin traverses the HAST (HTML Abstract Syntax Tree) and performs
|
||||||
|
* the following operations on each `<svg>` element:
|
||||||
|
*
|
||||||
|
* 1. Ensures a `viewBox` attribute exists. If it's missing but `width` and
|
||||||
|
* `height` are present, it generates a `viewBox` from them. This is
|
||||||
|
* crucial for making the SVG scalable.
|
||||||
|
*
|
||||||
|
* 2. Removes the `width` and `height` attributes. This allows the SVG's size
|
||||||
|
* to be controlled by CSS (e.g., `max-width: 100%`), making it responsive
|
||||||
|
* and preventing it from overflowing its container.
|
||||||
|
*
|
||||||
|
* @returns A unified transformer function.
|
||||||
|
*/
|
||||||
|
function rehypeScalableSvg() {
|
||||||
|
return (tree: Root) => {
|
||||||
|
visit(tree, 'element', (node: Element) => {
|
||||||
|
if (node.tagName === 'svg') {
|
||||||
|
const properties = node.properties || {}
|
||||||
|
const hasViewBox = 'viewBox' in properties
|
||||||
|
const width = properties.width as string | number | undefined
|
||||||
|
const height = properties.height as string | number | undefined
|
||||||
|
|
||||||
|
if (!hasViewBox && width && height) {
|
||||||
|
const numericWidth = parseFloat(String(width))
|
||||||
|
const numericHeight = parseFloat(String(height))
|
||||||
|
if (!isNaN(numericWidth) && !isNaN(numericHeight)) {
|
||||||
|
properties.viewBox = `0 0 ${numericWidth} ${numericHeight}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove fixed width and height to allow CSS to control the size
|
||||||
|
delete properties.width
|
||||||
|
delete properties.height
|
||||||
|
|
||||||
|
node.properties = properties
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default rehypeScalableSvg
|
||||||
@ -291,6 +291,7 @@ export const makeSvgScalable = (element: Element): Element => {
|
|||||||
const numericHeight = parseFloat(height)
|
const numericHeight = parseFloat(height)
|
||||||
if (!isNaN(numericWidth) && !isNaN(numericHeight)) {
|
if (!isNaN(numericWidth) && !isNaN(numericHeight)) {
|
||||||
element.setAttribute('viewBox', `0 0 ${numericWidth} ${numericHeight}`)
|
element.setAttribute('viewBox', `0 0 ${numericWidth} ${numericHeight}`)
|
||||||
|
element.setAttribute('max-width', `${numericWidth}px`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user