Skip to content

Commit

Permalink
feat: gogocode-plugin-optional-chaining
Browse files Browse the repository at this point in the history
  • Loading branch information
chibing.fy committed Mar 2, 2022
1 parent c2cb554 commit 87ea70c
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 0 deletions.
27 changes: 27 additions & 0 deletions packages/gogocode-plugin-optional-chaining/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
作为 npm 包,项目根目录的 transform.js 会被 gogocode-cli 调用

fileInfo 会包括 source 和 path 作为单个代码文件的内容和路径
api 目前只有 gogocode 作为转换库注入
options 将透传命令行的 options

```javascript

module.exports = function(fileInfo, api, options) {
const sourceCode = fileInfo.source;
const $ = api.gogocode;
return $(sourceCode)
.replace('const a = $_$', 'const a = 2')
.generate();
};

```

命令行调用方式:


```
gogogcode --src script.js --out script-compiled.js --transform=transform.js
```
21 changes: 21 additions & 0 deletions packages/gogocode-plugin-optional-chaining/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "gogocode-plugin-optional-chaining",
"version": "0.0.1",
"description": "gogocode-plugin-optional-chaining",
"scripts": {
"start": "node ./test/run.js"
},
"keywords": [
"gogocode",
"ast"
],
"main": "transform.js",
"author": "chibing",
"license": "ISC",
"engines": {
"node": "*"
},
"devDependencies": {
"gogocode": "^1.0.48"
}
}
7 changes: 7 additions & 0 deletions packages/gogocode-plugin-optional-chaining/test/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const a = x?.b?.c;

const t = x?.[0]?.[1];

const f = x?.['name']?.[1];

const g = x?.["s"];
34 changes: 34 additions & 0 deletions packages/gogocode-plugin-optional-chaining/test/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const $ = require('gogocode');
const t = require('../transform');
const path = require('path');
const fs = require('fs');

const inputPath = path.resolve(__dirname, './input.vue');
const outputPath = path.resolve(__dirname, './output.vue');

fs.readFile(inputPath, function read(err, code) {
if (err) {
throw err;
}
const outputCode = t(
{
source: code.toString(),
path: inputPath
},
{
gogocode: $
},
{
rootPath: __dirname,
outFilePath: outputPath,
outRootPath: __dirname,
}
);

fs.writeFile(outputPath, outputCode, function (err) {
if (err) {
throw err;
}
console.log('The file was saved!');
});
});
59 changes: 59 additions & 0 deletions packages/gogocode-plugin-optional-chaining/transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* 转换入口导出一个函数,按照如下函数签名
* @param {*} fileInfo 包含 source 和 path 属性
* @param {*} api 包含 gogocode 作为转换工具
* @param {*} options 其他 option 由此传入
* @returns {string} 返回转换后的代码
*/
module.exports = function (fileInfo, api, options) {
const $ = api.gogocode
const source = fileInfo.source
const ast = $(source)

const opt = ast.find(
{type: 'OptionalMemberExpression'}
)

if(!opt.length) {
return ast.generate();
}

if(!ast.has([`const _ = require('lodash')`, `import _ from 'lodash'`])) {
ast.prepend(`const _ = require('lodash')\n\n`)
}

function toNormalChain(optAst) {
const property = optAst.attr('property')
const object = optAst.attr('object')
let str = $(property).generate()

if (property.type === 'StringLiteral' || property.type === 'NumericLiteral') {
str = `[${str}]`
} else {
str = `.${str}`
}

if(object.type === 'MemberExpression' || object.type === 'OptionalMemberExpression') {
const res = toNormalChain($(object))
return {
object: res.object,
path: `${res.path}${str}`
}
} else {
return {
object: $(object).generate(),
path: str.replace(/^\./, '')
}
}
}

opt.each(item => {
if(item.parent()?.node?.type !== 'OptionalMemberExpression') {
const { object, path } = toNormalChain(item)
item.replaceBy(`_.get(${object}, \`${path}\`)`)
}
})

// return your transformed code here
return ast.generate()
};

0 comments on commit 87ea70c

Please sign in to comment.