最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Babel自動生成Attribute文檔實現(xiàn)詳解

 更新時間:2022年11月03日 16:36:16   作者:小鑫同學  
這篇文章主要為大家介紹了Babel自動生成Attribute文檔實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

1. 前言

利用Babel自動解析源碼屬性上的注釋生成對應Markdown文檔,這個場景的應用主要包括在組件庫文檔對組件屬性的介紹中,這一篇就通過編寫一個Babel插件來實現(xiàn)這個功能~

2. 開發(fā)自動生成屬性文檔插件

2.1 生成Babel插件模板:

  • 2.1.1 創(chuàng)建babel-plugin-auto-attr-doc文件夾;
  • 2.1.2 安裝npm i -g yo generator-babel-plugin-x;
  • 2.1.3 在新建目錄下執(zhí)行 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表格風格的語法;

源碼要求:**我們應該將組件涉及到對外提供的屬性統(tǒng)一到對應的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后應該顯示的內(nèi)容文件actual.md;
| 屬性名 | 說明 | 類型 | 可選值	| 默認值 |
| ------ | ---- | ---- | ----- | ----- |
| type | 類型 | string |  |  |
| icon | 圖標組件 | string |  |  |
| plain | 是否為樸素按鈕 | boolean |  | false |
  • 調(diào)整單元測試文件讀?。?/li>
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數(shù)組中可以取出所有注釋文本的集合,在Babel處理時我們需要依次處理每一塊注釋后增加標記來避免重復處理;
  • (path.node.declaration as t.TypeAlias).id.name中取屬性名稱;

將注釋文本通過doctrine模塊解析為對象后和屬性名合并對轉換Markdown所需要的所有數(shù)據(jù)~

2.5 插件開發(fā)過程:

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內(nèi)容數(shù)據(jù)暫存到apidoc中;
  • post:取出所有的apidoc內(nèi)容解析并輸出到本地文件中;
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 中未處理的數(shù)據(jù)后塞到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 主邏輯實現(xiàn):

leadingComments數(shù)組會在依次訪問ExportNamedDeclaration時不停增加,我們在處理掉當前索引的對象后增加一個處理過的標記skip,下次循環(huán)直接跳過;

通過parseComment函數(shù)解析后的對象可以通過tags數(shù)組獲取到所有的注釋項目,通過對應的title得到對應description內(nèi)容;

在往apidoc存放數(shù)據(jù)時需要處理屬性名稱符合一定的規(guī)則,并將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 注釋解析函數(shù):

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文檔實現(xiàn)詳解的詳細內(nèi)容,更多關于Babel生成Attribute文檔的資料請關注腳本之家其它相關文章!

相關文章

  • vue-cli腳手架的安裝教程圖解

    vue-cli腳手架的安裝教程圖解

    vue-cli腳手架模板是基于node下的npm來完成安裝,這篇文章主要介紹了vue-cli腳手架的安裝教程圖解 ,需要的朋友可以參考下
    2018-09-09
  • Vue使用axios進行數(shù)據(jù)異步交互的方法

    Vue使用axios進行數(shù)據(jù)異步交互的方法

    大家都知道在Vue里面有兩種出名的插件能夠支持發(fā)起異步數(shù)據(jù)傳輸和接口交互,分別是axios和vue-resource,同時vue更新到2.0之后,宣告不再對vue-resource更新,而是推薦的axios,今天就講一下怎么引入axios,需要的朋友可以參考下
    2024-01-01
  • 在瀏覽器console中如何調(diào)用vue內(nèi)部方法

    在瀏覽器console中如何調(diào)用vue內(nèi)部方法

    這篇文章主要介紹了在瀏覽器console中如何調(diào)用vue內(nèi)部方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Vuex 單狀態(tài)庫與多模塊狀態(tài)庫詳解

    Vuex 單狀態(tài)庫與多模塊狀態(tài)庫詳解

    這篇文章主要介紹了Vuex 單狀態(tài)庫與多模塊狀態(tài)庫詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-12-12
  • 解決vue watch數(shù)據(jù)的方法被調(diào)用了兩次的問題

    解決vue watch數(shù)據(jù)的方法被調(diào)用了兩次的問題

    這篇文章主要介紹了解決vue watch數(shù)據(jù)的方法被調(diào)用了兩次的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 深入了解Vue中Vuex的用法

    深入了解Vue中Vuex的用法

    Vuex的官方解釋是一個專為vue.js應用程序開發(fā)的狀態(tài)管理模式,這篇文章主要為大家介紹了Vuex的具體用法,希望對大家深入了解Vuex有一定的幫助
    2023-06-06
  • Vue的data為啥只能是函數(shù)原理詳解

    Vue的data為啥只能是函數(shù)原理詳解

    這篇文章主要為大家介紹了Vue的data為啥只能是函數(shù)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • 基于Vue封裝實現(xiàn)全屏功能工具類

    基于Vue封裝實現(xiàn)全屏功能工具類

    在?Web?應用程序中,有時需要為某些內(nèi)容提供全屏顯示的功能,本文將介紹如何使用?Vue.js?3?的?Composition?API?創(chuàng)建一個全屏功能的工具類,希望對大家有所幫助
    2024-03-03
  • 對vue下點擊事件傳參和不傳參的區(qū)別詳解

    對vue下點擊事件傳參和不傳參的區(qū)別詳解

    今天小編就為大家分享一篇對vue下點擊事件傳參和不傳參的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • vue中移動端調(diào)取本地的復制的文本方式

    vue中移動端調(diào)取本地的復制的文本方式

    這篇文章主要介紹了vue中移動端調(diào)取本地的復制的文本方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07

最新評論

惠东县| 沙雅县| 双流县| 武义县| 友谊县| 班玛县| 奉化市| 新绛县| 新昌县| 丰原市| 额尔古纳市| 雷山县| 崇礼县| 平罗县| 五原县| 沈阳市| 石棉县| 高雄县| 儋州市| 安多县| 澄江县| 吉隆县| 惠东县| 紫云| 仲巴县| 北安市| 沙田区| 南投县| 晋江市| 宽甸| 虞城县| 苏尼特左旗| 阿巴嘎旗| 朔州市| 昂仁县| 红桥区| 虹口区| 谢通门县| 静海县| 花莲县| 兴和县|