forked from thx/gogocode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: gogocode-plugin-optional-chaining
- Loading branch information
chibing.fy
committed
Mar 2, 2022
1 parent
c2cb554
commit 87ea70c
Showing
5 changed files
with
148 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
}; |