Commit eeb99c7

HPCesia <me@hpcesia.com>
2025-08-20 07:24:40
fix: local image zoom
1 parent ba9174e
src/components/utils/Markdown.astro
@@ -2,6 +2,7 @@
 import '@/styles/markdown.css';
 import type { HTMLAttributes } from 'astro/types';
 import 'cheerio';
+import { load as cheerioLoad } from 'cheerio';
 import Replacer from './Replacer.astro';
 
 interface Props extends HTMLAttributes<'article'> {
@@ -32,7 +33,7 @@ const {
 
 const references = bidirectionalReferences?.references;
 const allRefByCurrent = bidirectionalReferences?.allRefByCurrent;
-const replacer = (_: string, reference: string, alias: string) => {
+const referenceReplacer = (_: string, reference: string, alias: string) => {
   const id = references?.find((item) => item.reference === reference.split('#')[0])?.id;
   if (!id) return '';
   const refTo = allRefByCurrent?.find((it) => it.id === id);
@@ -43,11 +44,23 @@ const replacer = (_: string, reference: string, alias: string) => {
 };
 const referencePattern = /%%%%(.*?)(?:%%(.*?))?%%%%/g;
 
+const imageZoomReplacer = (html: string) => {
+  const $ = cheerioLoad(html);
+  $('img:where(:not(inline img))').attr('data-zoom', '');
+  return $.html();
+};
+const imageZoomPattern = null; // Use null to process entire HTML
+
 const Fragment = bidirectionalReferences ? Replacer : 'Fragment';
 ---
 
 <article class={className} {...rest}>
-  <Fragment option={{ pattern: referencePattern, replacer: replacer }}>
+  <Fragment
+    options={[
+      { pattern: referencePattern, replacer: referenceReplacer },
+      { pattern: imageZoomPattern, replacer: imageZoomReplacer },
+    ]}
+  >
     <slot />
   </Fragment>
 </article>
src/components/utils/Replacer.astro
@@ -21,13 +21,7 @@ type ReplaceOption =
       replacer: (match: string) => string | Promise<string>;
     };
 
-export type Props =
-  | {
-      option: ReplaceOption;
-    }
-  | {
-      options: ReplaceOption[];
-    };
+export type Props = { option: ReplaceOption } | { options: ReplaceOption[] };
 
 const raw = await Astro.slots.render('default');
 
src/plugins/remark-image-process.ts
@@ -4,10 +4,8 @@ import { visit } from 'unist-util-visit';
 export const remarkImageProcess: RemarkPlugin = function () {
   return (tree) => {
     visit(tree, 'image', (node) => {
-      // 添加 data-zoom 属性到图片节点
       node.data = node.data || {};
       node.data.hProperties = node.data.hProperties || {};
-      node.data.hProperties['data-zoom'] = '';
       // lazyload
       node.data.hProperties.loading = 'lazy';
       // async decode
package.json
@@ -40,6 +40,7 @@
     "astro-icon": "^1.1.5",
     "astro-pagefind": "^1.8.3",
     "autoprefixer": "^10.4.21",
+    "cheerio": "^1.1.2",
     "daisyui": "^5.0.46",
     "dayjs": "^1.11.13",
     "hast-util-from-html": "^2.0.3",
pnpm-lock.yaml
@@ -89,6 +89,9 @@ importers:
       autoprefixer:
         specifier: ^10.4.21
         version: 10.4.21(postcss@8.5.6)
+      cheerio:
+        specifier: ^1.1.2
+        version: 1.1.2
       daisyui:
         specifier: ^5.0.46
         version: 5.0.46
@@ -2785,6 +2788,10 @@ packages:
     resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==}
     engines: {node: '>=18.17'}
 
+  cheerio@1.1.2:
+    resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==}
+    engines: {node: '>=20.18.1'}
+
   chokidar@4.0.3:
     resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
     engines: {node: '>= 14.16.0'}
@@ -3791,6 +3798,9 @@ packages:
   html-void-elements@3.0.0:
     resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
 
+  htmlparser2@10.0.0:
+    resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==}
+
   htmlparser2@8.0.2:
     resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
 
@@ -6222,6 +6232,10 @@ packages:
     resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==}
     engines: {node: '>=18.17'}
 
+  undici@7.14.0:
+    resolution: {integrity: sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==}
+    engines: {node: '>=20.18.1'}
+
   unicode-canonical-property-names-ecmascript@2.0.1:
     resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
     engines: {node: '>=4'}
@@ -9797,6 +9811,20 @@ snapshots:
       undici: 6.21.3
       whatwg-mimetype: 4.0.0
 
+  cheerio@1.1.2:
+    dependencies:
+      cheerio-select: 2.1.0
+      dom-serializer: 2.0.0
+      domhandler: 5.0.3
+      domutils: 3.2.2
+      encoding-sniffer: 0.2.1
+      htmlparser2: 10.0.0
+      parse5: 7.3.0
+      parse5-htmlparser2-tree-adapter: 7.1.0
+      parse5-parser-stream: 7.1.2
+      undici: 7.14.0
+      whatwg-mimetype: 4.0.0
+
   chokidar@4.0.3:
     dependencies:
       readdirp: 4.1.2
@@ -11080,6 +11108,13 @@ snapshots:
 
   html-void-elements@3.0.0: {}
 
+  htmlparser2@10.0.0:
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+      domutils: 3.2.2
+      entities: 6.0.1
+
   htmlparser2@8.0.2:
     dependencies:
       domelementtype: 2.3.0
@@ -13932,6 +13967,8 @@ snapshots:
 
   undici@6.21.3: {}
 
+  undici@7.14.0: {}
+
   unicode-canonical-property-names-ecmascript@2.0.1: {}
 
   unicode-match-property-ecmascript@2.0.0: