前端基建-函数工具库之自动生成文档(3)

给函数库添加文档,目前想到的是两个方案

方案一:

主要方法是通过typedoc生成markdown文档,通过vitepress部署文档

TypeDoc 是一个专门为 TypeScript 项目设计的文档生成工具。它通过分析 TypeScript 代码中的类型信息、JSDoc 注释等内容,自动生成 API 文档。

TypeDoc 支持生成两种格式文件,分别是 html , markdown

html格式

地址: github.com/Stacey1018/...

安装typedoc

scss 复制代码
npm install --save-dev typedoc
npx typedoc // 生成typedoc.json

typedoc.json

perl 复制代码
{
    // Comments are supported, like tsconfig.json
    "entryPoints": ["./src/index.ts"],
    "out": "docs",
    // "plugin": ["../dist"],
      // "theme": "yaf"
    // "theme": "polymesh-docs"
    // "theme": "typedoc-theme-zt"
  }
  

package.json

json 复制代码
  "scripts": {
     "docs":"typedoc --options ./typedoc.json"
  },

生成文档目录

bash 复制代码
├── docs
│   ├── assets
│   │   ├── hierarchy.js
│   │   ├── highlight.css
│   │   ├── icons.js
│   │   ├── icons.svg
│   │   ├── main.js
│   │   ├── navigation.js
│   │   ├── search.js
│   │   └── style.css
│   ├── functions
│   │   └── sum.html
│   ├── index.html
│   └── modules.html

页面

嗯,挺丑的,官方提供了一些主题可以进行配置

markdown格式

代码地址:github.com/Stacey1018/...

markdown需要安装插件

复制代码
 npm install typedoc-plugin-markdown -D

typedoc.json

kotlin 复制代码
{
  // Comments are supported, like tsconfig.json
  "$schema": "https://typedoc.org/schema.json",
  "entryPoints": ["./src/index.ts"],
  "outputs": [
    {
      "name": "html",
      "path": "./docs/html"
    },
    {
      // requires typedoc-plugin-markdown
      "name": "markdown",
      "path": "./docs/markdown"
    }
  ],
  "plugin": ["typedoc-plugin-markdown"]
}

兼容了html的,方便对比,都放在docs目录下

生成markdown

arduino 复制代码
npm run docs

markdown的展示需要用到vitepress

安装vitepress

csharp 复制代码
npm install vitepress --savd-dev
// 初始化
npx vitepress init

.vitepress/config.ts

php 复制代码
import { basename } from "path"
import type { DefaultTheme } from "vitepress"
import { defineConfig } from "vitepress"
import fg from "fast-glob"
interface IndexTree {
  [index: string]: {
    link: string
    items?: IndexTree
  }
}

// 目录标题去除utils.前缀
function resolveTitle(title: string) {
  return title === "tools" ? title : title.replace("tools.", "")
}

// 将md文档列表转为树结构
function getTree(file: string, prefix: string, tree = {}) {
  const [cur, ...rest] = file.replace(".md", "").split(".")
  const curPath =  cur
  if (!tree[curPath]) {
    tree[curPath] = {
      link: prefix + cur + ".md",
    }
  }
  if (rest.length > 0) {
    if (!tree[curPath].items) {
      tree[curPath].items = {}
    }
    getTree(rest.join("."), curPath + ".", tree[curPath].items)
  }
}

// 将树结构转为目录数组
function treeToItems(tree: IndexTree) {
  const items: DefaultTheme.SidebarItem[] = []
  Object.keys(tree).forEach((key) => {
    const item: DefaultTheme.SidebarItem = {
      text: resolveTitle(key),
      link: tree[key].link,
    }
    if (tree[key].items) {
      if (!item.items) {
        item.items = []
      }
      item.items.push(...treeToItems(tree[key].items!))
    }
    items.push(item)
  })
  return items
}

const tree = fg
  .sync(["./docs/markdown/*.md"])
  .map((path) => basename(path))
  .reduce((tree, file) => {
    getTree(file, "", tree)
    return tree
  }, {})

  const functionTree =  fg
  .sync(["./docs/markdown/functions/*.md"])
  .map((path) => basename('1'+path))
  .reduce((tree, file) => {
    getTree(file, "/functions/", tree)
    return tree
  }, {})

  const classTree =  fg
  .sync(["./docs/markdown/classes/*.md"])
  .map((path) => basename('1'+path))
  .reduce((tree, file) => {
    getTree(file, "/classes/", tree)
    return tree
  }, {})
  

const treeList : DefaultTheme.SidebarItem[] = treeToItems(tree)
const functionTreeList : DefaultTheme.SidebarItem[] = treeToItems(functionTree)
const classTreeList : DefaultTheme.SidebarItem[] = treeToItems(classTree)

// https://vitepress.dev/reference/site-config
export default defineConfig({
  title: "zy-utils",
  description: "A VitePress Site",
  srcDir:'./docs/markdown', // 注意文件源目录
  themeConfig: {
    // https://vitepress.dev/reference/default-theme-config
    nav: [
      { text: 'Home', link: '/' },
      { text: 'api', link: '/globals' }
    ],

    sidebar: [
      ...treeList,
      {
        text: 'functions',
        items:[
          ...functionTreeList
        ]
      },
      {
        text: 'classes',
        items:[
          ...classTreeList
        ]
      }
    ],

    socialLinks: [
      { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
    ]
  }
})

docs/markdown/index.md

yaml 复制代码
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
  name: "函数工具库"
  text: "zy/utils"
  actions:
    - theme: brand
      text: 快速开始
      link: /globals
    - theme: brand
      text: gitLab
      link: https://github.com/Stacey1018
features:
- icon: 🛠️
  title: 开箱即用,简洁高效
  details: 提供一组常用的函数工具,减少重复代码,让开发更加高效。
- icon: 📦
  title: 轻量无依赖,性能优先
  details: 代码精简、无额外依赖,确保项目运行时的高性能和低开销。
- icon: 🌟 
  title: 持续优化,不断升级
  details: 持续更新和优化工具函数,保持最佳实践,助你编写更优雅的代码。
---

预览文档

arduino 复制代码
npm run docs:dev

方案二

代码地址: github.com/Stacey1018/...

使用 @microsoft/api-extractor @microsoft/api-documentervitepress生成文档

@microsoft/api-extractor 根据项目的 .d.ts 文件生成 api.json文件 @microsoft/api-documenter 根据api.json生成markdown文档

配置步骤

1.安装插件

scss 复制代码
npm install --save-dev @microsoft/api-extractor @microsoft/api-documenter

2.根文件夹下创建etc目录(插件要求必须创建)

3.跟目录下创建api-extractor.json

bash 复制代码
{
  "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
  "mainEntryPointFilePath": "<projectFolder>/dist/src/index.d.ts",
  "bundledPackages": [],
  "compiler": {},
  "apiReport": {
    "enabled": true
  },
  "docModel": {
    "enabled": true
  },
  "dtsRollup": {
    "enabled": false
  },
  "tsdocMetadata": {},
  "messages": {
    "compilerMessageReporting": {
      "default": {
        "logLevel": "warning"
      }
    },
    "extractorMessageReporting": {
      "default": {
        "logLevel": "warning"
      }
    },
    "tsdocMessageReporting": {
      "default": {
        "logLevel": "warning"
      }
    }
  }
}

4. 配置package.json

json 复制代码
    "docs": "api-extractor run --local --verbose && api-documenter markdown -i temp -o doc"

api-extractor run --local --verbose 用来生成tepm/api.json文件,api-documenter markdown -i temp -o doc 基于json文件,生成md文档

5.执行 npm run doc
6.配置vitepress
php 复制代码
import { basename } from "path"
import type { DefaultTheme } from "vitepress"
import { defineConfig } from "vitepress"
import fg from "fast-glob"
interface IndexTree {
  [index: string]: {
    link: string
    items?: IndexTree
  }
}

// 目录标题去除utils.前缀
function resolveTitle(title: string) {
  return title === "tools" ? title : title.replace("tools.", "")
}

// 将md文档列表转为树结构
function getTree(file: string, prefix: string, tree = {}) {
  const [cur, ...rest] = file.replace(".md", "").split(".")
  const curPath =  cur
  if (!tree[curPath]) {
    tree[curPath] = {
      link: prefix + cur + ".md",
    }
  }
  if (rest.length > 0) {
    if (!tree[curPath].items) {
      tree[curPath].items = {}
    }
    getTree(rest.join("."), curPath + ".", tree[curPath].items)
  }
}

// 将树结构转为目录数组
function treeToItems(tree: IndexTree) {
  const items: DefaultTheme.SidebarItem[] = []
  Object.keys(tree).forEach((key) => {
    const item: DefaultTheme.SidebarItem = {
      text: resolveTitle(key),
      link: tree[key].link,
    }
    if (tree[key].items) {
      if (!item.items) {
        item.items = []
      }
      item.items.push(...treeToItems(tree[key].items!))
    }
    items.push(item)
  })
  return items
}

const tree = fg
  .sync(["./docs/*.md"])
  .map((path) => basename(path))
  .reduce((tree, file) => {
    getTree(file, "", tree)
    return tree
  }, {})

  const functionTree =  fg
  .sync(["./docs/functions/*.md"])
  .map((path) => basename('1'+path))
  .reduce((tree, file) => {
    getTree(file, "/functions/", tree)
    return tree
  }, {})

  const classTree =  fg
  .sync(["./docs/classes/*.md"])
  .map((path) => basename('1'+path))
  .reduce((tree, file) => {
    getTree(file, "/classes/", tree)
    return tree
  }, {})
  

const treeList : DefaultTheme.SidebarItem[] = treeToItems(tree)
const functionTreeList : DefaultTheme.SidebarItem[] = treeToItems(functionTree)
const classTreeList : DefaultTheme.SidebarItem[] = treeToItems(classTree)

// https://vitepress.dev/reference/site-config
export default defineConfig({
  title: "zy-utils",
  description: "A VitePress Site",
  srcDir:'./docs', // 注意文件源目录
  themeConfig: {
    // https://vitepress.dev/reference/default-theme-config
    nav: [
      { text: 'Home', link: '/' },
      { text: 'api', link: '/globals' }
    ],

    sidebar: [
      ...treeList,
      {
        text: 'functions',
        items:[
          ...functionTreeList
        ]
      },
      {
        text: 'classes',
        items:[
          ...classTreeList
        ]
      }
    ],

    socialLinks: [
      { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
    ]
  }
})

看看效果

总结

方案一和二是通过提取函数的注释生成的结果,开发的时候一定要写好注释

方案二就是配置起来略复杂,但是方案二后续扩展一些东西应该更加方便灵活。方案一配置起来更加简单,适合小型函数库。

后续

后面还需要深入学下@microsoft/api-extractor插件的使用,看看能不能让输出的md更符合我们想要的格式

相关推荐
风象南19 分钟前
SpringBoot实现简易直播
java·spring boot·后端
这里有鱼汤28 分钟前
有人说10日低点买入法,赢率高达95%?我不信,于是亲自回测了下…
后端·python
武子康1 小时前
Java-39 深入浅出 Spring - AOP切面增强 核心概念 通知类型 XML+注解方式 附代码
xml·java·大数据·开发语言·后端·spring
米粉03051 小时前
SpringBoot核心注解详解及3.0与2.0版本深度对比
java·spring boot·后端
一只帆記2 小时前
SpringBoot EhCache 缓存
spring boot·后端·缓存
yuren_xia5 小时前
Spring Boot中保存前端上传的图片
前端·spring boot·后端
JohnYan8 小时前
Bun技术评估 - 04 HTTP Client
javascript·后端·bun
shangjg38 小时前
Kafka 的 ISR 机制深度解析:保障数据可靠性的核心防线
java·后端·kafka
青莳吖9 小时前
使用 SseEmitter 实现 Spring Boot 后端的流式传输和前端的数据接收
前端·spring boot·后端
我的golang之路果然有问题10 小时前
ElasticSearch+Gin+Gorm简单示例
大数据·开发语言·后端·elasticsearch·搜索引擎·golang·gin