文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Babel怎么实现自动生成Attribute文档

2023-07-04 13:13

关注

本篇内容主要讲解“Babel怎么实现自动生成Attribute文档”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Babel怎么实现自动生成Attribute文档”吧!

1. 前言

利用Babel自动解析源码属性上的注释生成对应Markdown文档,这个场景的应用主要包括在组件库文档对组件属性的介绍中

2. 开发自动生成属性文档插件

2.1 生成Babel插件模板:

生成的插件模板如下:

babel-plugin-auto-attr-doc  ├─ lib                      │  └─ index.js              ├─ src                      │  └─ index.ts              ├─ __tests__                │  ├─ fixtures              │  │  └─ example            │  │     ├─ actual.ts       │  │     └─ expected.ts     │  └─ index.js              ├─ package-lock.json        ├─ package.json             ├─ README.md                └─ tsconfig.json

2.2 转换思路详解:

转换过程:利用Babel将Typescript脚本解析为AST,通过对AST结构分析抽离对应的注释部分,再拼接Markdown表格风格的语法;

源码要求:**我们应该将组件涉及到对外提供的属性统一到对应的types.ts文件管理,分别导出对应的type字段;

注释要求:**分别定义字段描述、类型、可选项、默认值4项,由于解析器关键词冲突原因,我们应该尽量避免;

 export type IType = "primary" | "success" | "warning" | "danger" | "info";  export type IIcon = string;  export type IPlain = boolean;

 Markdown表格:**展示组件的属性、描述、类型、可选值和默认值这几项;

Babel怎么实现自动生成Attribute文档

2.3 单元测试用例:

| 属性名 | 说明 | 类型 | 可选值| 默认值 || ------ | ---- | ---- | ----- | ----- || type | 类型 | string |  |  || icon | 图标组件 | string |  |  || plain | 是否为朴素按钮 | boolean |  | false |
it(`should ${caseName.split("-").join(" ")}`, () => {  const actualPath = path.join(fixtureDir, "source-code.ts");  // 对源码进行加载解析  transformFileSync(actualPath);  // 读取我们准备好的md文件  const actual = fs    .readFileSync(path.join(fixtureDir, "actual.md"))    .toString();  // 读取插件解析生成的md文件  const expected = fs    .readFileSync(path.join(fixtureDir, "api-doc.md"))    .toString();  // diff  const diff = diffChars(actual, expected);  diff.length > 1 && _print(diff);  expect(diff.length).toBe(1);});

2.4 AST分析详解:

将注释文本通过doctrine模块解析为对象后和属性名合并对转换Markdown所需要的所有数据~

Babel怎么实现自动生成Attribute文档

2.5 插件开发过程:

2.5.1 定义Comment、ApiTable类型对象:
type Comment =  | {      describe: string;      type: any;      options?: any;      default?: any;    }  | undefined;
type ApiTable = {  attributeName: any;  attributeDescribe: any;  attributeType: any;  attributeOptions: any;  attributeDefault: any;};
2.5.2 插件主逻辑分析:
export default declare(  (api: BabelAPI, options: Record<string, any>, dirname: string) => {    api.assertVersion(7);    return {      name: "auto-attr-doc",      pre(this: PluginPass, file: BabelFile) {        this.set("api-doc", []);      },      visitor: {        ExportNamedDeclaration(          path: NodePath<t.ExportNamedDeclaration>,          state: PluginPass        ) {          const apidoc = state.get("api-doc");          // 处理 path.node.leadingComments 中未处理的数据后塞到apidoc中          state.set("api-doc", apidoc);        },      },      post(this: PluginPass, file: BabelFile) {        const apidoc = this.get("api-doc");        const output = generateMD(apidoc);        const root = path.parse(file.opts.filename || "./").dir;        fs.writeFileSync(path.join(root, "api-doc.md"), output, {          encoding: "utf-8",        });      },    } as PluginObj<PluginPass>;  });
2.5.3 主逻辑实现:

leadingComments数组会在依次访问ExportNamedDeclaration时不停增加,我们在处理掉当前索引的对象后增加一个处理过的标记skip,下次循环直接跳过;

通过parseComment函数解析后的对象可以通过tags数组获取到所有的注释项目,通过对应的title得到对应description内容;

在往apidoc存放数据时需要处理属性名称符合一定的规则,并将apidoc对象存放到原容器中;

{  ExportNamedDeclaration(    path: NodePath<t.ExportNamedDeclaration>,    state: PluginPass  ) {    const apidoc = state.get("api-doc");    let _comment: Comment = undefined;    path.node.leadingComments?.forEach((comment) => {      if (!Reflect.has(comment, "skip")) {        const tags = parseComment(comment.value)?.tags;        _comment = {          describe:            tags?.find((v) => v.title === "cDescribe")?.description || "",          type: tags?.find((v) => v.title === "cType")?.description || "",          options:            tags?.find((v) => v.title === "cOptions")?.description || "",          default:            tags?.find((v) => v.title === "cDefault")?.description || "",        };        Reflect.set(comment, "skip", true);      }    });    apidoc.push({      attributeName: (path.node.declaration as t.TypeAlias).id.name.substr(1).toLocaleLowerCase(),      attributeDescribe: _comment!.describe,      attributeType: _comment!.type,      attributeOptions: _comment!.options,      attributeDefault: _comment!.default,    } as ApiTable);    state.set("api-doc", apidoc);  },}
2.5.4 注释解析函数:
const parseComment = (comment: string) => {  if (!comment) {    return;  }  return doctrine.parse(comment, {    unwrap: true,  });};
2.5.5 Markdown表格拼装:
const generateMD = (apidoc: Array<ApiTable>) => {  let raw = `| 属性名 | 说明 | 类型 | 可选值| 默认值 |\n| ------ | ---- | ---- | ----- | ----- |\n`;  apidoc.forEach((item) => {    raw += `| ${item.attributeName} | ${item.attributeDescribe} | ${item.attributeType} | ${item.attributeOptions} | ${item.attributeDefault} |\n`;  });  return raw;};
2.5.6生成结果展示~

Babel怎么实现自动生成Attribute文档

到此,相信大家对“Babel怎么实现自动生成Attribute文档”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯