denoはTypeScriptをJavaScriptに変換してから実行します。
その変換後のキャッシュファイルが必要になったので、抽出するプログラムを作成しました。
その変換後のキャッシュファイルが必要になったので、抽出するプログラムを作成しました。
変換後のファイルが必要になった経緯
denoで動作するサーバプログラムはTypeScriptで書きたいです。
ブラウザ上で動作するアプリもTypeScriptで書きたいところですが、まだサポートされていません。
しかし、できればトランスパイラは使いたくないです。(denoもTSからJSに変換してからコンパイルしていますが、それはそういう仕様だからOK)
仕方がないのでブラウザ用のプログラムはJavaScriptで書きます。
denoでもブラウザでも必要になるような汎用的な関数がありました。
同じ関数をTypeScriptとJavaScriptの両方で書くのは避けたいです。
JavaScriptで書いて、型定義ファイルを作成してTypeScriptと混在させる選択肢も検討して色々試してみました。
しかし以下の問題がありました。
- 型定義ファイルの書き方が分からない。
- そもそもJavaScriptを使うために型定義ファイルを書く、というのはTypeScriptとJavaScriptの両方で同じ関数を書くのと変わらない気がする。
型定義ファイルについて試行錯誤している最中に「deno run」する際キャッシュファイル(JSファイル)が作成されているのを思い出しました。
手書きで型定義ファイルを作るよりdenoで作成された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
// --allow-run --allow-read --allow-write | |
import * as path from "https://deno.land/std@0.97.0/path/mod.ts" | |
function 絶対Pathに変換(p: string): string{ | |
return path.fromFileUrl(new URL(p, import.meta.url)) | |
} | |
async function cmd(cmd:string): Promise<string>{ | |
const p = Deno.run({cmd:['cmd', '/C', 'chcp 65001 & '+cmd], stdout:'piped'}) | |
const o = await p.output() | |
const text = new TextDecoder().decode(o) | |
return text | |
} | |
const txt = await cmd('deno info') | |
const pathGen = txt.replace(/\\\\/g,'\\').match(/Emitted[^:]+:[^"]+"([^\n]+)"/)![1] + '\\' | |
console.log('Deno.args.length['+Deno.args.length+']') | |
for(let i=0, L=Deno.args.length; i<L ;i++){ | |
const pathTS = 絶対Pathに変換(Deno.args[i]) | |
const text = await cmd('deno cache '+pathTS) | |
console.log(text) | |
const pathUNC = pathTS.indexOf('\\\\')==0 ? 'UNC' : 'file' | |
const pathJS = pathGen + pathUNC + '\\' + pathTS.replace(/\\+/,'\\').replace(/:/,'') + '.js' | |
console.log('コピー元['+pathJS+']') | |
console.log('コピー先['+pathTS+'.js]') | |
await Deno.copyFile(pathJS, pathTS+'.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
deno run --allow-run --allow-read --allow-write ts2js.ts common.ts |
実行結果
変換対象のファイルPathに「.js」を追加したPathに、変換後のファイルが抽出されます。
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
// 変換前 | |
function for0L(arr:any, fun:any){ | |
for(let i=0, L=arr.length; i<L ;i++){ const v = fun(i, arr[i]) | |
if(v){return v} | |
} | |
} | |
function forIn(obj:any, fun:any){ | |
for(const name in obj){ | |
const v = fun(name, obj[name]) | |
if(v){return v} | |
} | |
} | |
function get日時(dt:Date = new Date()) { | |
const f = (num:number, 桁数:number) => { return ('000' + num).slice(-桁数) } | |
const obj = { | |
FullYear : 4, | |
Month : 2, | |
Date : 2, | |
Hours : 2, | |
Minutes : 2, | |
Seconds : 2, | |
Milliseconds : 3 | |
} | |
const 間 = '// ::: '.split('') | |
let str出力 = '' | |
forIn(obj, (name:string, 桁数:number)=>{ | |
str出力 += f(eval('dt.get'+name+'()') + (name=='Month'?1:0), 桁数) + 間.shift() | |
}) | |
return str出力.slice(0, str出力.length-1) | |
} |
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
// 変換後 | |
function for0L(arr, fun) { | |
for (let i = 0, L = arr.length; i < L; i++) { | |
const v = fun(i, arr[i]); | |
if (v) { | |
return v; | |
} | |
} | |
} | |
function forIn(obj, fun) { | |
for (const name in obj) { | |
const v = fun(name, obj[name]); | |
if (v) { | |
return v; | |
} | |
} | |
} | |
function get日時(dt = new Date()) { | |
const f = (num, 桁数) => { return ('000' + num).slice(-桁数); }; | |
const obj = { | |
FullYear: 4, | |
Month: 2, | |
Date: 2, | |
Hours: 2, | |
Minutes: 2, | |
Seconds: 2, | |
Milliseconds: 3 | |
}; | |
const 間 = '// ::: '.split(''); | |
let str出力 = ''; | |
forIn(obj, (name, 桁数) => { | |
str出力 += f(eval('dt.get' + name + '()') + (name == 'Month' ? 1 : 0), 桁数) + 間.shift(); | |
}); | |
return str出力.slice(0, str出力.length - 1); | |
} |
抽出されたjsファイルを使用するhtml
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
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>TS→JS</title> | |
</head> | |
<body> | |
<input id=inp style="width:100%"> | |
<textarea id=ta style="width:100%;height:200px"></textarea> | |
</body> | |
<script src="./common.ts.js"></script> | |
<script> | |
onload = ()=>{ ta.value = get日時() } | |
</script> | |
</html> |
をedgeで読み込んだ結果
ちなみに「import」を含むtsファイルはjsファイルに変換してもエラーになってしまいます。
0 件のコメント:
コメントを投稿