◆ 簡単な置換で大体のコードは動く感じにできる
◆ コメント内や文字列中にも影響してしまう
◆  「(」 などで始まる時の 「;」 から始める分岐が構文の判断が必要そう

定期的にセミコロンは書かないようにしよう記事を書いてますが 基本的にはどっちでもいいのです
私は書かないだけで書きたい人は勝手に書いていたらいいと思います

ですが ときどきセミコロンは書くのが常識 書かないのは悪習だ みたいなこと書いてる人いますよね
そういうのを見つけると それを信じこんでしまう人が減るようにとセミコロンなんてイラネな記事を書いてます

書かない人からすれば C 言語などで セミコロン 2 つ書いてるようなものですからね
無駄な努力してますねー と思うだけです



それはおいておいて セミコロンありなコードをいじるときに あったりなかったりするのは気持ち悪いのでファイルでは統一したいものです

セミコロンをつけるのは構文の解析が必要です

セミコロンがなくても文を分割してくれるのは
特定の語 (return) とかのあと か 「}」 の前か 改行を挟んでいて構文的に来れないものがあるときです

なので 構文見ないで簡単につけられないです

ですが そういうツールもありますのでそこまで苦労しないはず


では逆にセミコロンありなコードからセミコロンを外したい時
これは基本的には簡単にできそうな気がします

行末の 「;」を消します
行頭が 「(」「[」「`」 の場合に 「;」 をつけます

問題はテキスト中の場合です
ES6 の場合は 「`」 のテンプレートストリングでヒアドキュメントをかけるので 文字列の中で行末と行頭が出てきます
行をまたぐテンプレートストリングはそうそうないですし 目で見て確認も容易な方なので とりあえず単純に行末セミコロン外してみます
str.replace(/;+\s*$/mg, "").replace(/(^\s*)([\(\[\`])/mg, "$1;$2")

確認はとりあえず大きそうなコードということで lodash の最新版 (master) のコードを使ってみました


結果は というと だいたいはうまく行ってます

問題があるのは 「+」 や 「||」 などの次の行が 「(」 で始まっているとき
if((tes1 || tes2) &&
  (tes3  || tes4)){
    noop()
}
こんな場合

&& とかは行頭の方に書いて とかいっても目的がセミコロンのある任意のファイルを変換なので意味が無いのです

行頭 「(」 や 「[」 の場合はその直前の行を見てセミコロンがあればつける でよさそうですが 一括置換といかずちょっと面倒になります
str.split("\n").reduce((a,b) => {
var commited = a.commited + a.pre.replace(/;+\s*$/, "") + "\n"
var pre = a.pre.match(/;+\s*$/) ? b.replace(/(^\s*)([\(\[\`])/, "$1;$2") : b
return {pre, commited}
}, {pre:"", commited:""}).commited
これでいけるかな

と思ったら今度はコメント問題
直前の行にセミコロンがあればという簡単な条件だとうまくいかないです
var a = 1 +
// dummy;
(1 / 2)
var a = 1 +
// dummy
;(1 / 2)



var a = 1;
// no semicolon
(1+2).toString().split("").forEach(e => console.log(e))
var a = 1
// no semicolon
(1+2).toString().split("").forEach(e => console.log(e))

の 2 パターンあります

これらの解決までとなると 直前の有効なトークンが何かと構文を見始めることになるので 単純な
str.replace(/;+\s*$/mg, "").replace(/(^\s*)([\(\[\`])/mg, "$1;$2")
で 「(」 などの前にはとりあえずセミコロン入れて 不要なところを見て消すのがいいかもしれないです

普通 は「(」 などから始まる行はそうそうないものですし コード編集しようとした時にセミコロンなしのスタイルに変更したいってときに使う程度の考えですので 全自動でまとめて変換する用途にする気がないならこれでとりあえずいいかな