- ジェネレーターは、関数の引数の中間などのコメントを移動させることがある
- ジェネレーターによっては、不自然な位置のコメントを失うことがある
- ジェネレーターは、互換性のあるパーサーを使用する必要がある
使用する JavaScript コード
すべての単語の間にコメントを入れている。
最初の //a
は、テストコードが動作しているかを確かめるため。
コメントあり
//a
/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/
コメントなし
function fn(x,y){}
ジェネレーターが生成したコード
acorn 8.7.0 + astravel 0.6.1 + astring 1.8.1
ソース:
let acorn = require("acorn");
const { attachComments } = require('astravel')
const astring = require('astring')
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
const comments = []
var ast = acorn.parse(code, {
ecmaVersion: 2020,
onComment: comments,
})
attachComments(ast, comments)
var formattedCode =
astring.generate(ast, {
comments: true,
})
console.log(formattedCode)
出力:
// a
/*b*/
function fn(x, y) {
/*c*/
/*d*/
/*e*/
/*f*/
/*g*/
/*h*/
/*i*/
/*j*/
}
/*k*/
meriyah 4.2.1 + astravel 0.6.1 + astring 1.8.1
ソース:
const { parse } = require('meriyah')
const { attachComments } = require('astravel')
const astring = require('astring')
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
const comments = []
ast = parse(code, {
ranges: true,
onComment: comments,
})
attachComments(ast, comments)
var formattedCode =
astring.generate(ast, {
comments: true,
})
console.log(formattedCode)
出力:
// a
/*b*/
function fn(x, y) {
/*c*/
/*d*/
/*e*/
/*f*/
/*g*/
/*h*/
/*i*/
/*j*/
}
/*k*/
esprima 4.0.1 + escodegen 2.0.0
astravel で生成したコメントは、
escodegen で使用されないため、
esprima をパーサーに使用した。
一部のコメントが生成されなかった。
ソース:
var esprima = require('esprima')
const es = require('escodegen')
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
let ast = esprima.parse(code, {range: true, tokens: true, comment: true})
ast = es.attachComments(ast, ast.comments, ast.tokens)
var formattedCode =
es.generate(ast, {
comment: true,
})
console.log(formattedCode)
出力:
//a
/*b*/
function fn(x, y)
/*i*/
{
} /*k*/
esprima 4.0.1 + escodegen 2.0.0 + @babel/generator 7.17.9
Meriyah + astravel で生成したASTでは、
@babel/generator でコメントが生成されないため、
esprima をパーサーに使用した。
esprima のコメントは @babel/generator では使用されないため、
escodegen を使ってコメントを抽出する。
@babel/generator で生成することで、
escodegen でもコメントを生成することができた。
ただし、jだけ出力されていない。
ソース:
var esprima = require('esprima')
const es = require('escodegen')
const generate = require('@babel/generator').default
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
let ast = esprima.parse(code, { range: true, tokens: true, comment: true })
ast = es.attachComments(ast, ast.comments, ast.tokens)
ast = { type: 'File', sourceType: 'script', program: ast }
var formattedCode =
generate(ast).code
console.log(formattedCode)
出力:
//a
//b
function //c
fn //d
( //e
x //f
, //g
y //h
) //i
{} //k
uglify-js 3.15.4
元のコードに近いが、iが出力されていない。
ただし、コメントが失われる場合がある。
その場合は、オプションに compress: { unused: false }
を追加すると保存される。
引数の変数名が変わらないよう、 mangle: false
をオプションに追加している。
ソース:
var UglifyJS = require('uglify-js')
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
var formattedCode =
UglifyJS.minify(code, {
mangle: false,
output: {
comments: true
},
}).code
console.log(formattedCode)
出力:
//a
/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/){/*j*/}/*k*/
terser 5.12.1
terser は uglify-es のフォーク。
結果は uglify-js と同様。
ソース:
const { minify } = require('terser')
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
async function asyncCall() {
var result = await minify(code, {
mangle: false,
output: {
comments: true
},
});
console.log(result.code);
}
asyncCall();
出力:
//a
/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/){/*j*/}/*k*/
prettier 2.6.2
全然きれいじゃない(コードのせい)。
ソース:
const prettier = require("prettier")
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
var formattedCode =
prettier.format(code, { parser: "babel" })
console.log(formattedCode)
出力:
//a
/*b*/ function /*c*/ fn /*d*/(/*e*/ x /*f*/, /*g*/ y /*h*/) /*i*/ {
/*j*/
} /*k*/
sucrase 3.21.0
コード:
const {transform} = require('sucrase')
const code = `//a\n/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/`
var formattedCode =
transform(code, {transforms: ["typescript", "imports"]}).code
console.log(formattedCode)
出力:
"use strict";//a
/*b*/function/*c*/fn/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/