从JSON到接口文档,教你如何优雅生成组件API!

背景

最近在做一个组件库的项目,对第三方库进行二次封装并暴露自定义属性,每个组件都有一份默认数据的 JSON格式。如何根据默认数据生成组件 API 文档?本文将教你如何使用 json-to-ts、prettier、ShellJS、TypeDoc、fs-extra、ora、path 等 JS 库优雅生成接口文档。

方案

方案非常直接,只需要两步:

  1. JSON 转 TypeScript
  2. 通过 TypeScript 生成组件 API 文档

原本以为这个需求已经有现成的轮子,但找了一下午都没有找到,只能自己实现一个

准备工作

首先,我们需要安装以下依赖:

bash 复制代码
npm install json-to-ts prettier shelljs typedoc fs-extra ora path --save-dev

我们所有的脚本文件都用 ts 来写,这样可以避免很多 类型 和 引用 问题

生成 TypeScript 接口

我们可以使用 json-to-ts 库 将 JSON 数据转换为 TypeScript 接口。首先,创建一个名为 json-to-interface.ts 的文件,并编写以下代码:

typescript 复制代码
import * as jsonToTs from "json-to-ts";
import * as fs from "fs-extra";
import * as path from "path";
import prettier from "prettier";

// 获取目标文件夹下的定义的 默认数据文件
export const getTargetFiles = (targetPath) => {
  let components = [];

  const files = fs.readdirSync(targetPath);
  files.forEach((item, index) => {
    let stat = fs.statSync(`${targetPath}/` + item);

    let isBool = true;
    try {
      fs.statSync(`${targetPath}/` + item + "/defaultProps.ts");
    } catch (error) {
      isBool = false;
    }

    if (stat.isDirectory() === true && isBool) {
      components.push(item);
    }
  });

  return components;
};

const transform = () => {
   // 获取待处理的组件名. targetPath 为存放默认数据的文件夹路径
  let components = getTargetFiles(targetPath);

  // 开始处理组件
  components.forEach((name) => {
    console.log(`当前处理组件的 - ${name}`);

    const jsonFilePath = path.resolve(
      __dirname,
      `${targetPath}/${name}/defaultProps.ts`
    );
   
    // 获取数据
    const { defaultProps: json } = require(jsonFilePath);

    // 可以先对默认数据做一下前置处理
    // ...
    
    // 获取 interface 数据
    const interfaceData: string[] = JsonToTS(json, { rootName: "DefaultProps" });
    
    // 可以对生成的 interfaceData 进行自定义配置处理
    // ...

    // interface 文件路径
    let filePath = `${targetPath}/${name}/interface.ts`;
    filePath = path.resolve(__dirname, filePath);

    // 使用 Prettier 格式化代码
    const formatData = prettier.format(interfaceData, {
      singleQuote: true,
      parser: "typescript",
    });

    // 写 interface 文件
    fs.outputFileSync(filePath, formatData);
 });
}

这段代码首先从我们的目标文件夹中读取名为 defaultProps.ts默认数据 文件(json 格式),然后使用 json-to-ts 库将 JSON 数据转换为 TypeScript 接口,并将结果写入名为 interfaces.ts 的文件中。

由于 json-to-ts 提供的 api 较少,如果我们需要给生成的接口上添加 自定义的数据,可以通过遍历 interfaceData 来动态添加

typescript 复制代码
interfaceData.map(item => {
    if (item.includes("interface DefaultProps {")) {
      const linkName = item.split(" ")[1];
      return `
            /**
             * @module ${title}
             * @see 点击此处查看区块详细 props -> {@link ${linkName}}
             */
            ${item}
        `;
    }
    return item;
  })

生成的 interfaces.ts 内容如下

生成接口文档

我们可以使用 TypeDoc 库 将生成的 TypeScript 接口转换为 HTML 文档。创建一个名为 generate-doc.ts 的文件,并编写以下代码:

typescript 复制代码
// 从 json-to-interface.ts 中导出相关的方法和属性
...

const generateDoc = () => {
  // 获取 typeDoc 配置文件
  const typeDocConfigPath = path.resolve(__dirname, "../../typedoc.json");
  let configJson = require(typeDocConfigPath);

  /** 将待生成文档的组件地址,注入到 typeDoc 配置文件中
   * basePath、name、components:是在上个阶段【生成 TypeScript 接口】获取的
   */
  configJson["entryPoints"] = components.map(
    (name) => `.${basePath}/${name}/interface.ts`
  );

  // 格式化 json 代码
  configJson = prettier.format(JSON.stringify(configJson), { parser: "json" });

  // 更新 typeDoc 配置文件
  fs.writeFileSync(typeDocConfigPath, configJson);

  // 生成文档
  shell.exec("typedoc --tsconfig ./tsconfig.json");
}

最终生成的 typedoc.json 大概如下图:

json 复制代码
{
  "entryPoints": [
    "./src/components/AboutUs/interface.ts",
    "./src/components/Contact/interface.ts",
    ...
  ],
  "out": "demo-docs",
  "name": "demo 组件 api",
  "exclude": [
    "**/__tests__/**/*",
    "**/node_modules/**/*"
  ],
  "theme": "default",
  "excludeExternals": true,
  "excludePrivate": true,
  "excludeProtected": true,
  "skipErrorChecking": true,
  "disableSources": true,
  "readme": "./scripts/generate/readme.md"
}

修改 package.json 文件,添加以下脚本:

json 复制代码
"scripts": {
  "docs": "npx tsx ./generate-doc.ts",
}

然后,执行以下命令生成接口文档:

bash 复制代码
npm run docs

这将在项目根目录下生成一个名为 demo-docs 的文件夹,其中包含接口文档的 HTML 文件。

可以定制 文档首页 的显示内容,通过一份 readme.md 来定制

最后

通过 json-to-tsTypeDoc 两个组件库的配合,以及多项交互优化,让你轻松生成组件 API

相关推荐
无双_Joney2 小时前
[更新迭代 - 1] Nestjs 在24年底更新了啥?(功能篇)
前端·后端·nestjs
在云端易逍遥2 小时前
前端必学的 CSS Grid 布局体系
前端·css
EMT2 小时前
在 Vue 项目中使用 URL Query 保存和恢复搜索条件
javascript·vue.js
ccnocare2 小时前
选择文件夹路径
前端
艾小码2 小时前
还在被超长列表卡到崩溃?3招搞定虚拟滚动,性能直接起飞!
前端·javascript·react.js
闰五月2 小时前
JavaScript作用域与作用域链详解
前端·面试
泉城老铁2 小时前
idea 优化卡顿
前端·后端·敏捷开发
前端康师傅2 小时前
JavaScript 作用域常见问题及解决方案
前端·javascript
司宸2 小时前
Prompt结构化输出:从入门到精通的系统指南
前端