Skip to content

Commit 09784d7

Browse files
committed
🚀 🎉 feat: 完成所有功能和文档,集成两个插件
1 parent ce57555 commit 09784d7

26 files changed

Lines changed: 911 additions & 2 deletions

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.DS_Store
2+
node_modules/
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
lib/
7+
types/
8+
9+
# Editor directories and files
10+
.idea
11+
.vscode
12+
*.suo
13+
*.ntvs*
14+
*.njsproj
15+
*.sln

.npmignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
src
2+
test
3+
yarn.lock
4+
tsconfig.json

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# 更新日志
2+
## [1.0.0] - 2021-12-12
3+
### 新增
4+
* build方法执行配置文件,走通plugin流程
5+
* 提供`parser`解析code到CBML元素
6+
* 提供`generater`从CBML元素生成code
7+
* 提供`plugin-visible-code`插件,编写`/*<visible><visible/>*/`元素来动态展示内部包裹的代码块
8+
* 提供`plugin-clean-comment`,清除指定的CBML元素,多个配置项
9+
* contribution文档
10+
* 使用场景文档
11+
### 优化
12+
* build方法返回最终转译的code,output选项变成可选
13+
* `plugin-visible-code`插件,新增`/*<visible>*/xxx/*<visible/>*/`块元素来动态展示内部包裹的代码块,现在支持块元素和注释元素

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 alanchenchen
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,51 @@
1-
# cbml-processor
2-
基于cbml parser和cbml规范实现的构建工具
1+
# cbml-processor
2+
基于cbml parser和cbml规范实现的CBML构建工具
3+
4+
> Author:alanchenchen
5+
6+
## Quote
7+
* [CBML定义](https://github.com/cbml/cbml)
8+
* [CBML Parser](https://github.com/cbml/cbmljs)
9+
* [CBML工具jdists](https://github.com/zswang/jdists)
10+
11+
## Using scenes
12+
[使用场景](./docs/using-scene.md)
13+
14+
## Feature
15+
* CBML规范不影响代码的编译器或解释器执行流程
16+
* CBML可以高度定制processor来扩展任何tag
17+
* 补全CBML缺少的generater
18+
* cbml-processor可以和任何构建工具集成,例如webpack的loader和rollup的plugin
19+
* 如果你在使用babel的AST转换发现难度,那么使用CBML的AST一定会更简单
20+
21+
## Install
22+
本地安装cbml-processor
23+
```bash
24+
npm install -D @alanchenchen/cbml-processor
25+
```
26+
## Usage
27+
### build
28+
根据配置文件构建,会执行插件,转换源文件到目标文件
29+
30+
### parseCBMLEle
31+
CBML的parser工具,转换code到CBML的AST tree
32+
> 参数类型,见`parser.ts`
33+
34+
### generateCode
35+
CBML的generate工具,转换CBML的AST tree到code
36+
> 参数类型,见`generater.ts`
37+
38+
## Plugins
39+
cbml-processor的build方法天然支持插件机制,具体开发见[详情](./src/plugins)
40+
41+
当前具备的插件清单:
42+
- [plugin-visible-code](./src/plugins/plugin-visible-code.ts) *动态展示/隐藏visible注释块内部的代码块*
43+
- [plugin-clean-comment](./src/plugins/plugin-clean-comment.ts) *清除CBML的注释块*
44+
45+
## Contribution
46+
[贡献](./docs/contribution.md)
47+
48+
## CHANGELOG
49+
[更新](./CHANGELOG.md)
50+
## license
51+
* MIT

docs/contribution.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# 开发指南
2+
3+
### 介绍
4+
5+
感谢你使用 cbml-processor。
6+
7+
以下是关于向cbml-processor 提交反馈或代码的指南。在向 cbml-processor 提交 issue 或者 PR 之前,请先花几分钟时间阅读以下文字。
8+
9+
## 参与开发
10+
11+
### 本地开发
12+
13+
按照下面的步骤操作,即可在本地开发 cbml-processor。
14+
15+
```bash
16+
# 克隆仓库
17+
# 默认为 main 分支,你需要切换到develop分支,包含 cbml-processor 的代码
18+
git clone -b develop https://github.com/alanchenchen/cbml-processor.git
19+
20+
# 安装依赖,建议使用yarn
21+
cd cbml-processor && yarn
22+
23+
# 运行example的demo代码
24+
yarn run demo
25+
```
26+
27+
### npm命令
28+
- demo,运行exmaple的示例代码
29+
- build,转译ts到js文件
30+
- test,运行test/目录的单元测试
31+
- updateTestSnapshot,更新test/目录的快照文件
32+
33+
### 添加新插件
34+
参与开发cbml-processor的插件,是对仓库贡献的主要方式,cbml-processor的build方法支持plugin机制,plugin会异步等待执行。
35+
> 建议大家选择自己的仓库来维护plugin,并且统一命名为`cbml-plugin-`开头的包,这样在使用cbml-processor的插件时会更加语义化
36+
37+
- 新建一个文件,导出一个async函数
38+
```js
39+
import { CBMLNode } from '@alanchenchen/cbml-processor/types/index.type'
40+
export default async (CBMLRootNode: CBMLNode) => {
41+
// ...
42+
// 可以选择是否返回CBMLRootNode,如果存在,则会修改AST tree,否则只执行逻辑
43+
return CBMLRootNode
44+
}
45+
```
46+
- 修改package.json的name字段为`cbml-plugin-visible-code`
47+
- npm publish到npm服务
48+
- 在当前仓库的首页README.md插件清单里添加插件描述
49+
50+
[插件的详细内容](../src/plugins)
51+
52+
## 提交 PR
53+
54+
### Pull Request 规范
55+
56+
- 如果遇到问题,建议保持你的 PR 足够小。保证一个 PR 只解决一个问题或只添加一个功能
57+
- 当新增组件或者修改原有组件时,记得增加或者修改测试代码,保证代码的稳定
58+
- 在 PR 中请添加合适的描述,并关联相关的 Issue
59+
60+
### Pull Request 流程
61+
62+
1. 同步主仓库的最新代码
63+
2. 基于主仓库的 **develop** 分支新建一个分支,比如`feature-plugin-terser`,修复问题命名为`bugfix-plugin_terser`
64+
3. 在新分支上进行开发,开发完成后,提 Pull Request 到主仓库的 **develop** 分支,Assignee写`alanchenchen`
65+
4. Pull Request 会在 Review 通过后被合并到主仓库
66+
67+
### 同步最新代码
68+
69+
提 Pull Request 前,请依照下面的流程同步主仓库的最新代码:
70+
71+
```bash
72+
# 添加主仓库到 remote,作为 fork 后仓库的上游仓库
73+
git remote add upstream https://github.com/alanchenchen/cbml-processor.git
74+
75+
# 拉取主仓库最新代码
76+
git fetch upstream
77+
78+
# 切换至 dev 分支
79+
git checkout develop
80+
81+
# 合并主仓库代码
82+
git merge upstream/develop
83+
```

docs/using-scene.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
## cbml-processor使用场景
2+
3+
### 实现ui库按需加载插件`babel-plugin-import`的替换
4+
#### ui库的按需加载大多的两种思路
5+
* 尽可能利用ES module的import静态分析,使用构建工具的tree shaking。但是无论rollup还是webpack都无法做到完全的tree shaking,这主要是因为代码存在副作用(side effect)。
6+
* 所以为了实现ui库的按需加载,很多库开发者选择了第二种思路,将单个组件抽离到单个js/css内,回到了jQuery年代。但是为了让使用者通过`import`语法来导入,Antd开发了`babel-plugin-import`插件
7+
#### `babel-plugin-import`插件原理
8+
1. 当使用者编写以下代码,并且配置好`babel.config.js`
9+
```js
10+
import { Table, Toast } from 'antd'
11+
```
12+
2. webpack/rollup通过babel转译后拿到的代码
13+
```js
14+
const Table = require('antd/es/table/index.js').default
15+
require('antd/es/table/style/index.js') // 自动引入style的css文件
16+
17+
const Toast = require('antd/es/toast/index.js').default
18+
require('antd/es/toast/style/index.js') // 自动引入style的css文件
19+
```
20+
可以看到插件是改写了js AST节点,并交给babel来生成代码
21+
#### 使用`cbml-processor`的插件替换
22+
1. 编写插件,自定义一个`es-import`注释标签,定义`import`的attribute,作为组件文件名,定义`from`的attribute,作为ui库包名
23+
2. 编写代码如下
24+
```js
25+
/*<es-import import='Table, Toast' from='antd' />*/
26+
```
27+
3. 通过`cbml-processor`转译后拿到的代码
28+
```js
29+
const Table = require('antd/es/table/index.js').default
30+
require('antd/es/table/style/index.js') // 自动引入style的css文件
31+
32+
const Toast = require('antd/es/toast/index.js').default
33+
require('antd/es/toast/style/index.js') // 自动引入style的css文件
34+
```
35+
36+
> 补充说明:虽然cbml-processor可以实现此效果,但从源码的语义可读性来讲,还是建议使用babel。
37+
38+
### 动态增删修改注释块
39+
1. 如果项目里需要某些代码在打包后不存在,使用babel来操作AST会非常麻烦,因为js的AST过于复杂
40+
2. 使用webpack/rollup的全局替换,比如vue-cli3的环境参数,虽然可以做到不同环境打包后代码动态运行,但是生成的代码始终存在,会被浏览器解释
41+
```js
42+
const shouldUseVConsole = process.env.shouldUseVConsole
43+
// 如果配置为false,虽然不会初始化vConsole,但是生成的代码会包含,并且if语句会被浏览器解释执行
44+
if (shouldUseVConsole) {
45+
const VConsole = require('vConsole')
46+
new VConsole()
47+
}
48+
```
49+
3. 编写`cbml-processor`插件,自定义一个`visible`注释标签,定义`lib`的attribute,作为包,定义`pin`的attribute,作为头部注释内容
50+
2. 编写代码如下
51+
```js
52+
/*<visible lib='VConsole' pin='初始化VConsole'>*/
53+
const vConsole = new VConsole()
54+
/*</visible>*/
55+
```
56+
3. 通过`cbml-processor`转译后拿到的代码,可以通过lib来过滤是否需要展示代码块
57+
```js
58+
// 初始化VConsole
59+
const vConsole = new VConsole()
60+
```

example/demo.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*<visible lib='XBridge' pin='初始化xbridge'>*/
2+
// 这行代码不会被转译,因为XBridge的lib被filter了,会被删掉,因为clean了blockElement
3+
const { Common } = new XBridge()
4+
/*</visible>*/
5+
6+
const arr = [1, 2, 3, 4]
7+
8+
// 这行代码不会被转译,因为没有插件处理
9+
/*<willStay />*/
10+
11+
// 这行代码将不会被转译,因为XBridge的lib被filter了
12+
/*<visible lib='XBridge' pin='初始化VConsole'>
13+
const vConsole = new VConsole()
14+
</visible>*/
15+
16+
// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
17+
/*<visible lib='VConsole' pin='初始化VConsole'>
18+
const vConsole = new VConsole()
19+
</visible>*/
20+
21+
// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
22+
/*<visible lib='vue-router;vuex' pin='初始化vue相关'>
23+
const router = new Router()
24+
const store = new Vuex.store()
25+
</visible>*/

example/demo.new.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const arr = [1, 2, 3, 4]
2+
3+
// 这行代码不会被转译,因为没有插件处理
4+
/*<willStay />*/
5+
// 这行代码将不会被转译,因为XBridge的lib被filter了
6+
/*<visible lib='XBridge' pin='初始化VConsole'>
7+
const vConsole = new VConsole()
8+
</visible>*/
9+
// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
10+
// 初始化VConsole
11+
const vConsole = new VConsole()
12+
// 这行代码将被解开注释,并打上注释(pin的内容),因为被插件处理了
13+
// 初始化vue相关
14+
const router = new Router()
15+
const store = new Vuex.store()

example/index.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { build } from '../src'
2+
import visibleCode from '../src/plugins/plugin-visible-code'
3+
import cleanComment from '../src/plugins/plugin-clean-comment'
4+
5+
build({
6+
sources: [
7+
{ input: './example/demo.js', output: './example/demo.new.js' },
8+
{ input: './example/demo.js' } // output缺失则不会写入code到文件,会返回code string
9+
],
10+
plugins: [
11+
visibleCode({
12+
filter: (attrs) => attrs.lib.value !== 'XBridge'
13+
}),
14+
cleanComment({
15+
removeBlankBlock: false,
16+
removeBlockElement: true,
17+
removeCommentElement: false,
18+
removeVoidElement: false
19+
})
20+
]
21+
}).then((res) => {
22+
// console.log(res)
23+
console.log('build complete.')
24+
}).catch(err => {
25+
console.log('build errors', err)
26+
})

0 commit comments

Comments
 (0)