Commit 16eb26d

HPCesia <me@hpcesia.com>
2025-02-12 05:58:06
refactor: update plugins to TypeScript
1 parent 26fec11
src/plugins/rehype-wrap-tables.mjs → src/plugins/rehype-wrap-tables.ts
@@ -1,13 +1,8 @@
+import type { RehypePlugin } from '@astrojs/markdown-remark';
+import type { ElementContent } from 'hast';
 import { visit } from 'unist-util-visit';
 
-/**
- * Rehype plugin to wrap tables with a div for overflow auto
- *
- * Rehype 插件,为表格包裹一个带有 overflow auto 样式的 div
- *
- * @returns {import('unified').Plugin}
- */
-export function rehypeWrapTables() {
+export const rehypeWrapTables: RehypePlugin = function () {
   return (tree) => {
     visit(tree, 'element', (node, index, parent) => {
       if (node.tagName === 'table' && parent && typeof index === 'number') {
@@ -17,8 +12,8 @@ export function rehypeWrapTables() {
           properties: { className: ['overflow-auto'] },
           children: [node],
         };
-        parent.children[index] = wrapper;
+        parent.children[index] = wrapper as ElementContent;
       }
     });
   };
-}
+};
src/plugins/remark-excerpt.js → src/plugins/remark-excerpt.ts
@@ -1,22 +1,17 @@
+import type { RemarkPlugin } from '@astrojs/markdown-remark';
 import { toString } from 'mdast-util-to-string';
 
-/**
- * Remark plugin to extract the first paragraph as excerpt
- *
- * 提取第一个段落作为摘要的 Remark 插件
- *
- * @returns {import('unified').Plugin}
- */
-export function remarkExcerpt() {
+export const remarkExcerpt: RemarkPlugin = function () {
   return (tree, { data }) => {
     let excerpt = '';
-    for (let node of tree.children) {
+    for (const node of tree.children) {
       if (node.type !== 'paragraph') {
         continue;
       }
       excerpt = toString(node);
       break;
     }
+    // @ts-expect-error data.astro.frontmatter must be defined
     data.astro.frontmatter.excerpt = excerpt;
   };
-}
+};
src/plugins/remark-heading-shift.mjs
@@ -1,17 +0,0 @@
-import { visit } from 'unist-util-visit';
-
-/**
- * Remark plugin to shift all heading levels down by one (starting from h2)
- *
- * Remark 插件,将所有标题层级下移一级(从 h2 开始)
- *
- * @type {import('unified').Plugin}
- */
-export default function remarkHeadingShift() {
-  return (tree) => {
-    visit(tree, 'heading', (node) => {
-      // 将所有标题层级加1(最大到6)
-      node.depth = Math.min(node.depth + 1, 6);
-    });
-  };
-}
src/plugins/remark-heading-shift.ts
@@ -0,0 +1,11 @@
+import type { RemarkPlugin } from '@astrojs/markdown-remark';
+import { visit } from 'unist-util-visit';
+
+export const remarkHeadingShift: RemarkPlugin = function () {
+  return (tree) => {
+    visit(tree, 'heading', (node) => {
+      // 将所有标题层级加1(最大到6)
+      node.depth = Math.min(node.depth + 1, 6) as 1 | 2 | 3 | 4 | 5 | 6;
+    });
+  };
+};
src/plugins/remark-image-process.mjs → src/plugins/remark-image-process.ts
@@ -1,9 +1,7 @@
+import type { RemarkPlugin } from '@astrojs/markdown-remark';
 import { visit } from 'unist-util-visit';
 
-/**
- * Remark plugin to add data-zoom attribute to all images
- */
-export function remarkImageProcess() {
+export const remarkImageProcess: RemarkPlugin = function () {
   return (tree) => {
     visit(tree, 'image', (node) => {
       // 添加 data-zoom 属性到图片节点
@@ -16,4 +14,4 @@ export function remarkImageProcess() {
       node.data.hProperties.decoding = 'async';
     });
   };
-}
+};
src/plugins/remark-reading-time.mjs → src/plugins/remark-reading-time.ts
@@ -1,18 +1,16 @@
+import type { RemarkPlugin } from '@astrojs/markdown-remark';
 import { toString } from 'mdast-util-to-string';
 import getReadingTime from 'reading-time';
 
-/**
- * Remark plugin to calculate reading time and word count
- *
- * Remark 插件,用于计算阅读时间和字数
- *
- * @returns {import('unified').Plugin}
- */
-export function remarkReadingTime() {
+export const remarkReadingTime: RemarkPlugin = function () {
   return (tree, { data }) => {
     const textOnPage = toString(tree);
     const readingTime = getReadingTime(textOnPage);
+
+    // @ts-expect-error data.astro.frontmatter must be defined
     data.astro.frontmatter.minutes = Math.max(1, Math.round(readingTime.minutes));
+
+    // @ts-expect-error data.astro.frontmatter must be defined
     data.astro.frontmatter.words = readingTime.words;
   };
-}
+};
astro.config.mjs
@@ -1,9 +1,10 @@
 // @ts-check
 import { CDN } from './src/constants/cdn.mjs';
-import { rehypeWrapTables } from './src/plugins/rehype-wrap-tables.mjs';
-import { remarkExcerpt } from './src/plugins/remark-excerpt';
-import { remarkImageProcess } from './src/plugins/remark-image-process.mjs';
-import { remarkReadingTime } from './src/plugins/remark-reading-time.mjs';
+import { rehypeWrapTables } from './src/plugins/rehype-wrap-tables.ts';
+import { remarkExcerpt } from './src/plugins/remark-excerpt.ts';
+// import { remarkHeadingShift } from './src/plugins/remark-heading-shift.ts';
+import { remarkImageProcess } from './src/plugins/remark-image-process.ts';
+import { remarkReadingTime } from './src/plugins/remark-reading-time.ts';
 import { rehypeHeadingIds } from '@astrojs/markdown-remark';
 import mdx from '@astrojs/mdx';
 import sitemap from '@astrojs/sitemap';
package.json
@@ -49,6 +49,7 @@
     "@astrojs/ts-plugin": "^1.10.4",
     "@eslint/js": "^9.20.0",
     "@trivago/prettier-plugin-sort-imports": "^5.2.2",
+    "@types/hast": "^3.0.4",
     "@types/markdown-it": "^14.1.2",
     "@types/mdast": "^4.0.4",
     "@types/sanitize-html": "^2.13.0",