fix: avoid image cls in entry content (#666)

This commit is contained in:
Stephen Zhou 2024-09-27 16:37:59 +08:00 committed by GitHub
parent a213da80b5
commit ccda8875e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 47 additions and 6 deletions

View File

@ -1,5 +1,6 @@
import { createElement, Fragment, memo, useEffect, useMemo, useState } from "react"
import type { MediaInfo } from "~/lib/parse-html"
import { parseHtml } from "~/lib/parse-html"
import type { RemarkOptions } from "~/lib/parse-markdown"
import { parseMarkdown } from "~/lib/parse-markdown"
@ -42,15 +43,17 @@ const HTMLImpl = <A extends keyof JSX.IntrinsicElements = "div">(
accessory?: React.ReactNode
noMedia?: boolean
mediaInfo?: MediaInfo
} & JSX.IntrinsicElements[A] &
Partial<{
renderInlineStyle: boolean
}>,
) => {
const { children, renderInlineStyle, as = "div", accessory, noMedia, ...rest } = props
const { children, renderInlineStyle, as = "div", accessory, noMedia, mediaInfo, ...rest } = props
const [remarkOptions, setRemarkOptions] = useState({
renderInlineStyle,
noMedia,
mediaInfo,
})
const [shouldForceReMountKey, setShouldForceReMountKey] = useState(0)

View File

@ -23,7 +23,7 @@ export const MarkdownBlockImage = (
)}
showFallback
popper
className="inline-flex justify-center"
className="flex justify-center"
/>
)
}

View File

@ -152,9 +152,11 @@ const MediaImpl: FC<MediaProps> = ({
mediaLoadState,
popper,
previewImageUrl,
props,
props.height,
props.width,
rest,
src,
thumbnail,
type,
])

View File

@ -23,11 +23,22 @@ import { BlockError } from "~/components/ui/markdown/renderers/BlockErrorBoundar
import { createHeadingRenderer } from "~/components/ui/markdown/renderers/Heading"
import { Media } from "~/components/ui/media"
function markInlineImage(node?: Element) {
for (const item of node?.children ?? []) {
if (item.type === "element" && item.tagName === "img") {
;(item.properties as any).inline = true
}
}
}
export type MediaInfo = Record<string, { width?: number; height?: number }>
export const parseHtml = (
content: string,
options?: Partial<{
renderInlineStyle: boolean
noMedia?: boolean
mediaInfo?: MediaInfo
}>,
) => {
const file = new VFile(content)
@ -84,8 +95,17 @@ export const parseHtml = (
jsxs: (type, props, key) => jsxs(type as any, props, key),
passNode: true,
components: {
a: ({ node, ...props }) => createElement(MarkdownLink, { ...props } as any),
img: Img,
a: ({ node, ...props }) => {
markInlineImage(node)
return createElement(MarkdownLink, { ...props } as any)
},
img: ({ ...props }) => {
return createElement(Img, {
...props,
width: props.src ? options?.mediaInfo?.[props.src]?.width : props.width,
height: props.src ? options?.mediaInfo?.[props.src]?.height : props.height,
})
},
h1: createHeadingRenderer(1),
h2: createHeadingRenderer(2),
@ -107,6 +127,10 @@ export const parseHtml = (
}
return createElement(MarkdownP, props, props.children)
},
span: ({ node, ...props }) => {
markInlineImage(node)
return createElement("span", props, props.children)
},
hr: ({ node, ...props }) =>
createElement("hr", {
...props,
@ -195,7 +219,7 @@ const Img: Components["img"] = ({ node, ...props }) => {
type: "photo",
...nextProps,
mediaContainerClassName: tw`max-w-full inline size-auto`,
mediaContainerClassName: tw`max-w-full inline rounded-md`,
popper: true,
className: tw`inline`,
showFallback: true,

View File

@ -148,6 +148,17 @@ export const EntryContentRender: Component<{
if (!entry) return null
const content = entry?.entries.content ?? data?.entries.content
const mediaInfo = Object.fromEntries(
(entry.entries.media ?? data?.entries.media)
?.filter((m) => m.type === "photo")
.map((cur) => [
cur.url,
{
width: cur.width,
height: cur.height,
},
]) ?? [],
)
return (
<EntryContentProvider
@ -200,6 +211,7 @@ export const EntryContentRender: Component<{
{!isInReadabilityMode ? (
<ShadowDOM>
<HTML
mediaInfo={mediaInfo}
noMedia={noMedia}
accessory={contentAccessories}
as="article"