Babel自动生成Attribute文档实现详解

目录
  • 1. 前言
  • 2. 开发自动生成属性文档插件
    • 2.1 生成Babel插件模板:
    • 2.2 转换思路详解:
    • 2.3 单元测试用例:
    • 2.4 AST分析详解:
    • 2.5 插件开发过程:
      • 2.5.1 定义Comment、ApiTable类型对象:
      • 2.5.2 插件主逻辑分析:
      • 2.5.3 主逻辑实现:
      • 2.5.4 注释解析函数:
      • 2.5.5 Markdown表格拼装:
      • 2.5.6生成结果展示~
  • 3. 总结

1. 前言

利用Babel自动解析源码属性上的注释生成对应Markdown文档,这个场景的应用主要包括在组件库文档对组件属性的介绍中,这一篇就通过编写一个Babel插件来实现这个功能~

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

2.1 生成Babel插件模板:

  • 2.1.1 创建babel-plugin-auto-attr-doc文件夹;
  • 2.1.2 安装npm i -g yo generator-babel-plugin-x
  • 2.1.3 在新建目录下执行 yo babel-plugin-x:v7-ts

生成的插件模板如下:

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项,由于解析器关键词冲突原因,我们应该尽量避免;

/**
  * @cDescribe 类型
  * @cType string
  * @cOptions
  * @cDefault
  */
 export type IType = "primary" | "success" | "warning" | "danger" | "info";
 /**
  * @cDescribe 图标组件
  * @cType string
  * @cOptions
  * @cDefault
  */
 export type IIcon = string;
 /**
  * @cDescribe 是否为朴素按钮
  * @cType boolean
  * @cOptions
  * @cDefault false
  */
 export type IPlain = boolean;

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

2.3 单元测试用例:

  • 准备插件待解析源码文件source-code.ts
  • 准备实际生成MD后应该显示的内容文件actual.md
| 属性名 | 说明 | 类型 | 可选值	| 默认值 |
| ------ | ---- | ---- | ----- | ----- |
| 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分析详解:

  • 通过在AST explorer的源码分析,我们在Babel中可以通过遍历ExportNamedDeclaration(命名导出声明);
  • leadingComments数组中可以取出所有注释文本的集合,在Babel处理时我们需要依次处理每一块注释后增加标记来避免重复处理;
  • (path.node.declaration as t.TypeAlias).id.name中取属性名称;

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

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 插件主逻辑分析:

  • pre:初始化存放apidoc容器,避免在存放时找不到容器;
  • visitor:解析源码并获取组织MD内容数据暂存到apidoc中;
  • post:取出所有的apidoc内容解析并输出到本地文件中;
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生成结果展示~

3. 总结

插件生成目前基本功能完成,注释解析可以通过Babel的插件选项来定义作为一个扩展方向,MD文件的生成可以通过对应工具转换,更多的输出文件类型也可以作为扩展方向,欢迎喜欢玩转Babel的小伙伴一起交流交流~

已推送至GitHub https://github.com/OSpoon/awesome-examples

以上就是Babel自动生成Attribute文档实现详解的详细内容,更多关于Babel生成Attribute文档的资料请关注我们其它相关文章!

(0)

相关推荐

  • Babel 插件开发&访问节点实例详解

    目录 访问节点 获取子节点的Path: 检查节点的类型: 检查路径(Path)类型: 检查标识符(Identifier)是否被引用: 找到特定的父路径: 获取同级路径: 停止遍历: 访问节点 获取子节点的Path: 我们在处理节点的属性之前必须要拿到节点对象才能进行操作,我们使用path.node.property来访问属性~ BinaryExpression(path) { path.node.left; path.node.right; path.node.operator; } 我们还可以

  • react源码层深入刨析babel解析jsx实现

    目录 jsx v16.x及以前版本 v17及之后版本 ReactElement React.createElement ReactElement React.Component 总结 经过多年的发展,React已经更新了大版本16.17.18,本系列主要讲的是 version:17.0.2,在讲这个版本之前,我们先看一看在babel的编译下,每个大版本之下会有什么样的变化. jsx <div className='box'> <h1 className='title' style={{'

  • babel插件去除console示例详解

    目录 起因 介绍 窥探 初见AST Program ExpressionStatement CallExpression MemberExpression Identifier StringLiteral 公共属性 如何写一个babel插件? 构造visitor方法 去除所有console 增加env api 增加exclude api 增加commentWords api 细节完善 对于后缀注释 对于前缀注释 发布到线上 安装 使用 起因 已经颓废了很久 因为实在不知道写啥了 突然我某个同事对

  • Node.js基础模块babel使用详解

    目录 安装配置 使用babel 实际例子 类的转化 babel-polyfill 前言: 由于ES6到ES7增加了很多新的语法,新特性的出现使得大家都希望通过新语法来提升自身的开发效率,但在之前的最新的node可能也没有百分之百的支持ES2017的新特性,而且开发者在开发环境和生产环境中的版本一般是不同的,所以新特性的代码可能不能完美的运行在线上环境中,为了解决难题,babel提供一系列的api来将新特性的语法转化成低版本环境中能够运行的代码 安装配置 babel是由一系列的组件构成,所以我们在

  • vue3中的透传attributes教程示例详解

    目录 引言 绑定样式 对象 数组 透传的attributes 透传 attributes 之样式绑定 透传 attributes 之事件绑定 特殊1:组件嵌套 特殊2:禁用透传attributes 特殊3:在 javascript 中访问透传的attributes 总结 引言 最近两年都是在使用 react 进行项目开发,看技术博客都是针对 react 和 javaScript 高级方面的,对 vue 的知识基本上遗忘的差不多了.最近开始慢慢回顾 vue 的知识以及对新的语法进行学习,为后面的计

  • Vue 3.0的attribute强制行为理解学习

    目录 理解property和attribute property 形容词 名词 attribute vue3中的property和attribute xml中的属性节点 vue3.0的attribute强制行为 源代码分析 vue3.0的变化 理解property和attribute 这个要看具体的语境了.不过我们可以从词源的角度来区分一下这两者: property 形容词 property的词源可追溯到proper,意为合适的,适当的. 短语示例: a proper job 一份合适(自己的)

  • Babel自动生成Attribute文档实现详解

    目录 1. 前言 2. 开发自动生成属性文档插件 2.1 生成Babel插件模板: 2.2 转换思路详解: 2.3 单元测试用例: 2.4 AST分析详解: 2.5 插件开发过程: 2.5.1 定义Comment.ApiTable类型对象: 2.5.2 插件主逻辑分析: 2.5.3 主逻辑实现: 2.5.4 注释解析函数: 2.5.5 Markdown表格拼装: 2.5.6生成结果展示~ 3. 总结 1. 前言 利用Babel自动解析源码属性上的注释生成对应Markdown文档,这个场景的应用主

  • Django restful framework生成API文档过程详解

    自动生成api文档(不管是函数视图还是类视图都能显示) 1.安装rest_framework_swagger库 pip install django-rest-swagger 2.在项目下的 urls.py 中加入如下: from rest_framework_swagger.views import get_swagger_view schema_view = get_swagger_view(title='API文档') urlpatterns += [ path(r'docs/', sch

  • spring boot集成smart-doc自动生成接口文档详解

    目录 前言 功能特性 1 项目中创建 /src/main/resources/smart-doc.json配置文件 2 配置内容如下(指定文档的输出路径) 3 pom.xml下添加配置 4 运行插件 5 找到存放路径浏览器打开 6 测试结果 前言 smart-doc 是一款同时支持 java restful api 和 Apache Dubbo rpc 接口文档生成的工具,smart-doc 颠覆了传统类似 swagger 这种大量采用注解侵入来生成文档的实现方法. smart-doc 完全基于

  • SpringBoot如何自动生成API文档详解

    前言 在做项目的时候,如果项目是前后分离的,后端一定要和前端或者是移动端对接接口,那么问题来了,接口是不是要自己写给他们看,一般的会采用Excel或者Word来写,高级一点的就采用API管理平台手工录入,一个项目有上千上万个接口,天啊,这是多么大的工作量,在接口维护的时候更加痛苦,为了解决这样的事我们可以借助 japi这个项目来完成RESTFul文档的自动生成,完全基于注释生成,更多详细配置可查看https://github.com/dounine/japi. 使用说明 克隆项目下来 git c

  • eclipse中自动生成javadoc文档的方法

    本文实例讲述了eclipse中自动生成javadoc文档的方法.分享给大家供大家参考.具体方法如下: 使用eclipse生成文档(javadoc)主要有三种方法: 1. 在项目列表中按右键,选择Export(导出),然后在Export(导出)对话框中选择java下的javadoc,提交到下一步. 在Javadoc Generation对话框中有两个地方要注意的: javadoc command:应该选择jdk的bin/javadoc.exe destination:为生成文档的保存路径,可自由选

  • SpringBoot结合Swagger2自动生成api文档的方法

    首先在pom.xml中添加如下依赖,其它web,lombok等依赖自行添加 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.spri

  • 使用Python 自动生成 Word 文档的教程

    当然要用第三方库啦 :) 使用以下命令安装: pip install python-docx 使用该库的基本步骤为: 1.建立一个文档对象(可自动使用默认模板建立,也可以使用已有文件). 2.设置文档的格式(默认字体.页面边距等). 3.在文档对象中加入段落文本.表格.图像等,并指定其样式. 4.保存文档. 注:本库仅支持生成Word2007以后版本的文档类型,即扩展名为.docx 的. 下面分步介绍其基本使用方法: 步骤一: from docx import Document doc = Do

  • idea创建JAVA Class时自动生成头部文档注释的方法

    IDEA设置文档注释模板 创建Class文件时自动生成的头部注释如图 如何配置idea的头部注释格式,可以生成像之前的注释格式一样的文档注释? File->settings->Editor->File and Code Templates->Files->Class 原先模板 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse(&

  • 教你怎么用java一键自动生成数据库文档

    这是该工具的github地址:https://github.com/pingfangushi/screw 一.引入pom.xml依赖 <dependencies> <!-- screw 库,简洁好用的数据库表结构文档生成器 --> <dependency> <groupId>cn.smallbun.screw</groupId> <artifactId>screw-core</artifactId> <version

  • MySQL5.7.10 安装文档教程详解

    1.安装依赖包 yum -y install gcc-c++ ncurses-devel cmake make perl gcc autoconf automake zlib libxml libgcrypt libtool bison 2.安装boost库: 首先先查询是否已经安装过boost rpm -qa boost* 卸载旧boost-*等库: yum -y remove boost-* 下载Boost库,在解压后复制到/usr/local/boost目录下,然后重新cmake并在后面的

随机推荐