给函数库添加文档,目前想到的是两个方案
方案一:
主要方法是通过typedoc生成markdown文档,通过vitepress部署文档
TypeDoc 是一个专门为 TypeScript 项目设计的文档生成工具。它通过分析 TypeScript 代码中的类型信息、JSDoc 注释等内容,自动生成 API 文档。
TypeDoc 支持生成两种格式文件,分别是 html , markdown
html格式
安装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更符合我们想要的格式