Skip to content

Commit

Permalink
🚀 🎉 feat: 完成所有功能和文档,集成两个插件
Browse files Browse the repository at this point in the history
  • Loading branch information
alanchenchen committed Dec 12, 2021
1 parent ce57555 commit 09784d7
Show file tree
Hide file tree
Showing 26 changed files with 911 additions and 2 deletions.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.DS_Store
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lib/
types/

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src
test
yarn.lock
tsconfig.json
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 更新日志
## [1.0.0] - 2021-12-12
### 新增
* build方法执行配置文件,走通plugin流程
* 提供`parser`解析code到CBML元素
* 提供`generater`从CBML元素生成code
* 提供`plugin-visible-code`插件,编写`/*<visible><visible/>*/`元素来动态展示内部包裹的代码块
* 提供`plugin-clean-comment`,清除指定的CBML元素,多个配置项
* contribution文档
* 使用场景文档
### 优化
* build方法返回最终转译的code,output选项变成可选
* `plugin-visible-code`插件,新增`/*<visible>*/xxx/*<visible/>*/`块元素来动态展示内部包裹的代码块,现在支持块元素和注释元素
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 alanchenchen

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,51 @@
# cbml-processor
基于cbml parser和cbml规范实现的构建工具
# cbml-processor
基于cbml parser和cbml规范实现的CBML构建工具

> Author:alanchenchen
## Quote
* [CBML定义](https://github.com/cbml/cbml)
* [CBML Parser](https://github.com/cbml/cbmljs)
* [CBML工具jdists](https://github.com/zswang/jdists)

## Using scenes
[使用场景](./docs/using-scene.md)

## Feature
* CBML规范不影响代码的编译器或解释器执行流程
* CBML可以高度定制processor来扩展任何tag
* 补全CBML缺少的generater
* cbml-processor可以和任何构建工具集成,例如webpack的loader和rollup的plugin
* 如果你在使用babel的AST转换发现难度,那么使用CBML的AST一定会更简单

## Install
本地安装cbml-processor
```bash
npm install -D @alanchenchen/cbml-processor
```
## Usage
### build
根据配置文件构建,会执行插件,转换源文件到目标文件

### parseCBMLEle
CBML的parser工具,转换code到CBML的AST tree
> 参数类型,见`parser.ts`
### generateCode
CBML的generate工具,转换CBML的AST tree到code
> 参数类型,见`generater.ts`
## Plugins
cbml-processor的build方法天然支持插件机制,具体开发见[详情](./src/plugins)

当前具备的插件清单:
- [plugin-visible-code](./src/plugins/plugin-visible-code.ts) *动态展示/隐藏visible注释块内部的代码块*
- [plugin-clean-comment](./src/plugins/plugin-clean-comment.ts) *清除CBML的注释块*

## Contribution
[贡献](./docs/contribution.md)

## CHANGELOG
[更新](./CHANGELOG.md)
## license
* MIT
83 changes: 83 additions & 0 deletions docs/contribution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 开发指南

### 介绍

感谢你使用 cbml-processor。

以下是关于向cbml-processor 提交反馈或代码的指南。在向 cbml-processor 提交 issue 或者 PR 之前,请先花几分钟时间阅读以下文字。

## 参与开发

### 本地开发

按照下面的步骤操作,即可在本地开发 cbml-processor。

```bash
# 克隆仓库
# 默认为 main 分支,你需要切换到develop分支,包含 cbml-processor 的代码
git clone -b develop https://github.com/alanchenchen/cbml-processor.git

# 安装依赖,建议使用yarn
cd cbml-processor && yarn

# 运行example的demo代码
yarn run demo
```

### npm命令
- demo,运行exmaple的示例代码
- build,转译ts到js文件
- test,运行test/目录的单元测试
- updateTestSnapshot,更新test/目录的快照文件

### 添加新插件
参与开发cbml-processor的插件,是对仓库贡献的主要方式,cbml-processor的build方法支持plugin机制,plugin会异步等待执行。
> 建议大家选择自己的仓库来维护plugin,并且统一命名为`cbml-plugin-`开头的包,这样在使用cbml-processor的插件时会更加语义化
- 新建一个文件,导出一个async函数
```js
import { CBMLNode } from '@alanchenchen/cbml-processor/types/index.type'
export default async (CBMLRootNode: CBMLNode) => {
// ...
// 可以选择是否返回CBMLRootNode,如果存在,则会修改AST tree,否则只执行逻辑
return CBMLRootNode
}
```
- 修改package.json的name字段为`cbml-plugin-visible-code`
- npm publish到npm服务
- 在当前仓库的首页README.md插件清单里添加插件描述

[插件的详细内容](../src/plugins)

## 提交 PR

### Pull Request 规范

- 如果遇到问题,建议保持你的 PR 足够小。保证一个 PR 只解决一个问题或只添加一个功能
- 当新增组件或者修改原有组件时,记得增加或者修改测试代码,保证代码的稳定
- 在 PR 中请添加合适的描述,并关联相关的 Issue

### Pull Request 流程

1. 同步主仓库的最新代码
2. 基于主仓库的 **develop** 分支新建一个分支,比如`feature-plugin-terser`,修复问题命名为`bugfix-plugin_terser`
3. 在新分支上进行开发,开发完成后,提 Pull Request 到主仓库的 **develop** 分支,Assignee写`alanchenchen`
4. Pull Request 会在 Review 通过后被合并到主仓库

### 同步最新代码

提 Pull Request 前,请依照下面的流程同步主仓库的最新代码:

```bash
# 添加主仓库到 remote,作为 fork 后仓库的上游仓库
git remote add upstream https://github.com/alanchenchen/cbml-processor.git

# 拉取主仓库最新代码
git fetch upstream

# 切换至 dev 分支
git checkout develop

# 合并主仓库代码
git merge upstream/develop
```
60 changes: 60 additions & 0 deletions docs/using-scene.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## cbml-processor使用场景

### 实现ui库按需加载插件`babel-plugin-import`的替换
#### ui库的按需加载大多的两种思路
* 尽可能利用ES module的import静态分析,使用构建工具的tree shaking。但是无论rollup还是webpack都无法做到完全的tree shaking,这主要是因为代码存在副作用(side effect)。
* 所以为了实现ui库的按需加载,很多库开发者选择了第二种思路,将单个组件抽离到单个js/css内,回到了jQuery年代。但是为了让使用者通过`import`语法来导入,Antd开发了`babel-plugin-import`插件
#### `babel-plugin-import`插件原理
1. 当使用者编写以下代码,并且配置好`babel.config.js`
```js
import { Table, Toast } from 'antd'
```
2. webpack/rollup通过babel转译后拿到的代码
```js
const Table = require('antd/es/table/index.js').default
require('antd/es/table/style/index.js') // 自动引入style的css文件

const Toast = require('antd/es/toast/index.js').default
require('antd/es/toast/style/index.js') // 自动引入style的css文件
```
可以看到插件是改写了js AST节点,并交给babel来生成代码
#### 使用`cbml-processor`的插件替换
1. 编写插件,自定义一个`es-import`注释标签,定义`import`的attribute,作为组件文件名,定义`from`的attribute,作为ui库包名
2. 编写代码如下
```js
/*<es-import import='Table, Toast' from='antd' />*/
```
3. 通过`cbml-processor`转译后拿到的代码
```js
const Table = require('antd/es/table/index.js').default
require('antd/es/table/style/index.js') // 自动引入style的css文件

const Toast = require('antd/es/toast/index.js').default
require('antd/es/toast/style/index.js') // 自动引入style的css文件
```

> 补充说明:虽然cbml-processor可以实现此效果,但从源码的语义可读性来讲,还是建议使用babel。
### 动态增删修改注释块
1. 如果项目里需要某些代码在打包后不存在,使用babel来操作AST会非常麻烦,因为js的AST过于复杂
2. 使用webpack/rollup的全局替换,比如vue-cli3的环境参数,虽然可以做到不同环境打包后代码动态运行,但是生成的代码始终存在,会被浏览器解释
```js
const shouldUseVConsole = process.env.shouldUseVConsole
// 如果配置为false,虽然不会初始化vConsole,但是生成的代码会包含,并且if语句会被浏览器解释执行
if (shouldUseVConsole) {
const VConsole = require('vConsole')
new VConsole()
}
```
3. 编写`cbml-processor`插件,自定义一个`visible`注释标签,定义`lib`的attribute,作为包,定义`pin`的attribute,作为头部注释内容
2. 编写代码如下
```js
/*<visible lib='VConsole' pin='初始化VConsole'>*/
const vConsole = new VConsole()
/*</visible>*/
```
3. 通过`cbml-processor`转译后拿到的代码,可以通过lib来过滤是否需要展示代码块
```js
// 初始化VConsole
const vConsole = new VConsole()
```
25 changes: 25 additions & 0 deletions example/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*<visible lib='XBridge' pin='初始化xbridge'>*/
// 这行代码不会被转译,因为XBridge的lib被filter了,会被删掉,因为clean了blockElement
const { Common } = new XBridge()
/*</visible>*/

const arr = [1, 2, 3, 4]

// 这行代码不会被转译,因为没有插件处理
/*<willStay />*/

// 这行代码将不会被转译,因为XBridge的lib被filter了
/*<visible lib='XBridge' pin='初始化VConsole'>
const vConsole = new VConsole()
</visible>*/

// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
/*<visible lib='VConsole' pin='初始化VConsole'>
const vConsole = new VConsole()
</visible>*/

// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
/*<visible lib='vue-router;vuex' pin='初始化vue相关'>
const router = new Router()
const store = new Vuex.store()
</visible>*/
15 changes: 15 additions & 0 deletions example/demo.new.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const arr = [1, 2, 3, 4]

// 这行代码不会被转译,因为没有插件处理
/*<willStay />*/
// 这行代码将不会被转译,因为XBridge的lib被filter了
/*<visible lib='XBridge' pin='初始化VConsole'>
const vConsole = new VConsole()
</visible>*/
// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
// 初始化VConsole
const vConsole = new VConsole()
// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
// 初始化vue相关
const router = new Router()
const store = new Vuex.store()
26 changes: 26 additions & 0 deletions example/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { build } from '../src'
import visibleCode from '../src/plugins/plugin-visible-code'
import cleanComment from '../src/plugins/plugin-clean-comment'

build({
sources: [
{ input: './example/demo.js', output: './example/demo.new.js' },
{ input: './example/demo.js' } // output缺失则不会写入code到文件,会返回code string
],
plugins: [
visibleCode({
filter: (attrs) => attrs.lib.value !== 'XBridge'
}),
cleanComment({
removeBlankBlock: false,
removeBlockElement: true,
removeCommentElement: false,
removeVoidElement: false
})
]
}).then((res) => {
// console.log(res)
console.log('build complete.')
}).catch(err => {
console.log('build errors', err)
})
48 changes: 48 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@alanchenchen/cbml-processor",
"version": "1.0.0",
"private": false,
"description": "基于cbml parser和cbml规范实现的构建工具",
"author": "alanchenchen",
"main": "lib/index.js",
"types": "types/index.d.ts",
"engines": {
"node": ">= 14.0.0"
},
"keywords": [
"cbml",
"cbml parser",
"cbml generator",
"processor",
"commonet"
],
"license": "MIT",
"scripts": {
"demo": "ts-node example/index.ts",
"build": "tsc",
"test": "jest --colors --verbose",
"updateTestSnapshot": "jest --updateSnapshot",
"prepublishOnly": "npm test && npm run build",
"deploy": "npm publish --access=public"
},
"dependencies": {
"cbml": "^1.0.0-alpha.33"
},
"devDependencies": {
"@types/node": "^16.11.11",
"@types/jest": "^27.0.3",
"jest": "^27.4.0",
"ts-node": "^10.4.0",
"tslib": "^2.3.1",
"typescript": "^4.5.2"
},
"bugs": {
"url": "https://github.com/alanchenchen/cbml-processor/issues",
"email": "[email protected]"
},
"homepage": "https://github.com/alanchenchen/cbml-processor",
"repository": {
"type": "git",
"url": "https://github.com/alanchenchen/cbml-processor"
}
}
Loading

0 comments on commit 09784d7

Please sign in to comment.