@yhotamos/enja-cli 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/index.js +11 -9
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
- Google Apps Script の LanguageApp を使用した軽量な翻訳
|
|
13
13
|
- 引数,パイプ,ファイルから翻訳可能
|
|
14
14
|
- HTML タグ除去機能で Web ページも翻訳可能
|
|
15
|
-
- API
|
|
16
|
-
- カスタム翻訳エンドポイント対応
|
|
15
|
+
- OpenAI API や Gemini API を使用して高品質な翻訳も可能
|
|
17
16
|
- 翻訳履歴の保存・参照機能
|
|
18
17
|
|
|
19
18
|
## インストール
|
|
@@ -38,6 +37,9 @@ enja -f input.txt -o output.txt
|
|
|
38
37
|
|
|
39
38
|
# 翻訳方向を逆にする (日本語 → 英語)
|
|
40
39
|
enja "こんにちは" -F
|
|
40
|
+
|
|
41
|
+
# OpenAI API を使用して翻訳
|
|
42
|
+
enja "Hello, world!" --provider openai --api-key YOUR_OPENAI_API_KEY
|
|
41
43
|
```
|
|
42
44
|
|
|
43
45
|
### 履歴と設定
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import*as c from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import Y from'ora';import*as d from'path';import*as C from'os';import {randomUUID,createHash}from'crypto';import l from'kleur';var x=class{apiUrl;apiKey;constructor(t,r){this.apiUrl=t,this.apiKey=r;}async translate(t,r,o){try{let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let n=await fetch(this.apiUrl,{method:"POST",headers:i,body:JSON.stringify({text:t,sourceLang:r,targetLang:o})});if(!n.ok)throw new Error(`HTTP ${n.status} ${n.statusText}`);let s=await n.json();if(s.code!==200||!s.translatedText)throw new Error(`${s.error||"\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F"}`);return {text:s.translatedText,detectedSourceLang:s.detectedSourceLang}}catch(i){throw i}}};function m(){if(process.platform==="win32"){let r=process.env.APPDATA||d.join(C.homedir(),"AppData","Roaming");if(!r)throw new Error("APPDATA \u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u304A\u3089\u305A\uFF0C\u4EE3\u66FF\u30D1\u30B9\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return d.join(r,"enja-cli")}let t=C.homedir();return d.join(t,".config","enja-cli")}function A(){return d.join(m(),"history.json")}function L(){return d.join(m(),"config.json")}var h={provider:"gas",endpoint:"https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec",apiKey:void 0},y=class{filePath;constructor(){this.filePath=L();}ensureConfigDir(){let t=m();c.existsSync(t)||c.mkdirSync(t,{recursive:true});}async readConfig(){try{if(!c.existsSync(this.filePath))return {...h};let t=c.readFileSync(this.filePath,"utf-8"),r=JSON.parse(t);return {...h,...r}}catch{return console.warn("\u8A2D\u5B9A\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u898F\u5B9A\u5024\u3092\u4F7F\u7528\u3057\u307E\u3059"),{...h}}}async writeConfig(t){try{this.ensureConfigDir(),c.writeFileSync(this.filePath,JSON.stringify(t,null,2),"utf-8");}catch{throw new Error("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async get(){return await this.readConfig()}async set(t,r){let o=await this.readConfig();switch(t){case "endpoint":o.endpoint=r;break;case "api-key":o.apiKey=r;break;case "provider":if(r!=="gas"&&r!=="custom")throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r}): gas \u307E\u305F\u306F custom \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);o.provider=r;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(o);}async unset(t){let r=await this.readConfig();switch(t){case "endpoint":r.endpoint=h.endpoint;break;case "api-key":r.apiKey=void 0;break;case "provider":r.provider=h.provider;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(r);}async reset(){await this.writeConfig({...h});}};var J="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";async function K(e){let r=await new y().get(),o=e?.endpoint||r.endpoint||J,i=e?.apiKey||r.apiKey||void 0,n=e?.provider||r.provider||"gas";return {endpoint:o,provider:n,apiKey:i}}async function k(e){let t=await K(e);switch(t.provider){case "gas":case "custom":return new x(t.endpoint,t.apiKey);default:throw new Error(`\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${t.provider})`)}}var B=100,w=class{filePath;constructor(){this.filePath=A();}ensureConfigDir(){let t=m();c.existsSync(t)||c.mkdirSync(t,{recursive:true});}async readHistory(){try{let t=await promises.readFile(this.filePath,"utf-8");return JSON.parse(t)}catch(t){return t&&t.code==="ENOENT"?[]:(console.warn("\u5C65\u6B74\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u7A7A\u914D\u5217\u3092\u8FD4\u3057\u307E\u3059"),[])}}async writeHistory(t){try{this.ensureConfigDir();let r=`${this.filePath}.tmp`,o=JSON.stringify(t,null,2);await promises.writeFile(r,o,"utf-8"),await promises.rename(r,this.filePath);}catch{throw new Error("\u5C65\u6B74\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async add(t){let r=await this.readHistory(),o={...t,id:randomUUID(),timestamp:new Date().toISOString()};r.unshift(o),r.length>B&&r.splice(B),await this.writeHistory(r);}async getAll(){return await this.readHistory()}async getRecent(t){return (await this.readHistory()).slice(0,t)}async deleteById(t){let r=await this.readHistory(),o=r.filter(i=>i.id!==t);return o.length===r.length?false:(await this.writeHistory(o),true)}async clear(){await this.writeHistory([]);}async findById(t){return (await this.readHistory()).find(o=>o.id===t)||null}async findByShortId(t){return (await this.readHistory()).filter(o=>o.id.startsWith(t))}async findByHash(t,r,o){return (await this.readHistory()).find(n=>n.sourceHash===t&&n.sourceLang===r&&n.targetLang===o)||null}};function F(e){return createHash("sha256").update(e).digest("hex")}async function R(e,t){try{if(!e&&!t.file&&!process.stdin.isTTY){let r=await _();await j(r,t,"stdin");return}if(t.file){if(!c.existsSync(t.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t.file})`);let r=c.readFileSync(t.file,"utf-8");await j(r,t,"file");return}if(e){await j(e,t,"arg");return}console.error("error: \u5165\u529B\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093"),console.error("\u4F7F\u3044\u65B9: enja <\u30C6\u30AD\u30B9\u30C8> \u307E\u305F\u306F enja -f <\u30D5\u30A1\u30A4\u30EB> \u307E\u305F\u306F \u30D1\u30A4\u30D7\u5165\u529B"),process.exit(1);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function j(e,t,r){if(!e||e.trim().length===0)throw new Error("\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u3067\u3059");let o=e;if(t.stripHtml&&(o=G(e),!o||o.trim().length===0))throw new Error("HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u305F\u7D50\u679C\uFF0C\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u306B\u306A\u308A\u307E\u3057\u305F");let i=await k(t),n=new w,s=t.flip?"ja":"en",a=t.flip?"en":"ja",p=F(o),g=await n.findByHash(p,s,a);if(g&&t.cache!==false){console.log(`${l.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let H=g.translatedText;if(t.output)try{c.writeFileSync(t.output,H,"utf-8"),console.log(`${l.green("\u2714")} ${t.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${t.output})`)}else console.log(H);return}let u=`(${s} \u2192 ${a})`,O=Y(`\u7FFB\u8A33\u4E2D... ${u}`).start();try{let T=(await i.translate(o,s,a)).text;if(O.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${u}`),await n.add({sourceText:o,translatedText:T,sourceLang:s,targetLang:a,textLength:o.length,sourceHash:p,options:{stripHtml:t.stripHtml,file:t.file,inputMethod:r}}),t.output)try{c.writeFileSync(t.output,T,"utf-8"),console.log(`${l.green("\u2714")} ${t.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${t.output})`)}else console.log(T);}catch(H){throw O.fail(`\u7FFB\u8A33\u5931\u6557 ${u}`),H}}function _(){return new Promise((e,t)=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",o=>{r+=o;}),process.stdin.on("end",()=>{e(r);}),process.stdin.on("error",o=>{t(o);});})}function G(e){return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,"").replace(/<[^>]+>/g,"").replace(/ /g," ").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/\n\s*\n/g,`
|
|
3
|
-
`).trim()}function E(e,t=false){return e.length===0?"\u5C65\u6B74\u306F\u3042\u308A\u307E\u305B\u3093":t?
|
|
4
|
-
`),e.forEach((r,
|
|
5
|
-
`)}function
|
|
6
|
-
`),e.forEach((r,
|
|
7
|
-
`)}async function
|
|
2
|
+
import*as l from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import Q from'ora';import*as u from'path';import*as D from'os';import _ from'openai';import {GoogleGenAI}from'@google/genai';import {randomUUID,createHash}from'crypto';import p from'kleur';var v=class{apiUrl;apiKey;constructor(t,r){this.apiUrl=t,this.apiKey=r;}async translate(t,r,n){try{let o={"Content-Type":"application/json"};this.apiKey&&(o.Authorization=`Bearer ${this.apiKey}`);let i=await fetch(this.apiUrl,{method:"POST",headers:o,body:JSON.stringify({text:t,sourceLang:r,targetLang:n})});if(!i.ok)throw new Error(`HTTP ${i.status} ${i.statusText}`);let s=await i.json();if(s.code!==200||!s.translatedText)throw new Error(`${s.error||"\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F"}`);return {text:s.translatedText,detectedSourceLang:s.detectedSourceLang}}catch(o){throw o}}};function d(){if(process.platform==="win32"){let r=process.env.APPDATA||u.join(D.homedir(),"AppData","Roaming");if(!r)throw new Error("APPDATA \u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u304A\u3089\u305A\uFF0C\u4EE3\u66FF\u30D1\u30B9\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return u.join(r,"enja-cli")}let t=D.homedir();return u.join(t,".config","enja-cli")}function K(){return u.join(d(),"history.json")}function R(){return u.join(d(),"config.json")}var h={provider:"gas",endpoint:"https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec",apiKey:void 0},w=class{filePath;constructor(){this.filePath=R();}ensureConfigDir(){let t=d();l.existsSync(t)||l.mkdirSync(t,{recursive:true});}async readConfig(){try{if(!l.existsSync(this.filePath))return {...h};let t=l.readFileSync(this.filePath,"utf-8"),r=JSON.parse(t);return {...h,...r}}catch{return console.warn("\u8A2D\u5B9A\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u898F\u5B9A\u5024\u3092\u4F7F\u7528\u3057\u307E\u3059"),{...h}}}async writeConfig(t){try{this.ensureConfigDir(),l.writeFileSync(this.filePath,JSON.stringify(t,null,2),"utf-8");}catch{throw new Error("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async get(){return await this.readConfig()}async set(t,r){let n=await this.readConfig();switch(t){case "endpoint":n.endpoint=r;break;case "api-key":n.apiKey=r;break;case "provider":if(!["gas","custom","openai","gemini"].includes(r))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r}): 'gas', 'custom', 'openai', 'gemini' \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);n.provider=r;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(n);}async unset(t){let r=await this.readConfig();switch(t){case "endpoint":r.endpoint=h.endpoint;break;case "api-key":r.apiKey=void 0;break;case "provider":r.provider=h.provider;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(r);}async reset(){await this.writeConfig({...h});}};var Y="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";async function k(e){let r=await new w().get(),n=e?.endpoint||r.endpoint||Y,o=e?.apiKey||r.apiKey,i=e?.provider||r.provider||"gas";return {endpoint:n,provider:i,apiKey:o}}var x=class{client;constructor(t){this.client=new _({apiKey:t});}async translate(t,r,n){try{let o=this.mapLanguageCode(r),i=this.mapLanguageCode(n),s=`You are a professional translator. Translate the following text from ${o} to ${i}. Only return the translated text without any additional explanation or comments.`,c=(await this.client.chat.completions.create({model:"gpt-4o-mini",messages:[{role:"system",content:s},{role:"user",content:t}],temperature:.3})).choices[0]?.message?.content;if(!c)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:c.trim(),detectedSourceLang:r}}catch(o){throw o instanceof Error?new Error(`OpenAI\u7FFB\u8A33\u30A8\u30E9\u30FC: ${o.message}`):o}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};var C=class{client;constructor(t){this.client=new GoogleGenAI({apiKey:t});}async translate(t,r,n){try{let o=this.mapLanguageCode(r),i=this.mapLanguageCode(n),s=`You are a professional translator. Translate the following text from ${o} to ${i}. Only return the translated text without any additional explanation or comments.`,c=(await this.client.models.generateContent({model:"gemini-2.5-flash-lite",contents:t,config:{systemInstruction:s}})).text;if(!c)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:c.trim(),detectedSourceLang:r}}catch(o){throw o instanceof Error?new Error(`Gemini\u7FFB\u8A33\u30A8\u30E9\u30FC: ${o.message}`):o}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};async function B(e){let t=await k(e);switch(t.provider){case "gas":case "custom":return new v(t.endpoint,t.apiKey);case "openai":if(!t.apiKey)throw new Error("OpenAI\u3092\u4F7F\u7528\u3059\u308B\u306B\u306FAPI\u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return new x(t.apiKey);case "gemini":if(!t.apiKey)throw new Error("Gemini\u3092\u4F7F\u7528\u3059\u308B\u306B\u306FAPI\u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return new C(t.apiKey);default:throw new Error(`\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${t.provider})`)}}var M=100,y=class{filePath;constructor(){this.filePath=K();}ensureConfigDir(){let t=d();l.existsSync(t)||l.mkdirSync(t,{recursive:true});}async readHistory(){try{let t=await promises.readFile(this.filePath,"utf-8");return JSON.parse(t)}catch(t){return t&&t.code==="ENOENT"?[]:(console.warn("\u5C65\u6B74\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u7A7A\u914D\u5217\u3092\u8FD4\u3057\u307E\u3059"),[])}}async writeHistory(t){try{this.ensureConfigDir();let r=`${this.filePath}.tmp`,n=JSON.stringify(t,null,2);await promises.writeFile(r,n,"utf-8"),await promises.rename(r,this.filePath);}catch{throw new Error("\u5C65\u6B74\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async add(t){let r=await this.readHistory(),n={...t,id:randomUUID(),timestamp:new Date().toISOString()};r.unshift(n),r.length>M&&r.splice(M),await this.writeHistory(r);}async getAll(){return await this.readHistory()}async getRecent(t){return (await this.readHistory()).slice(0,t)}async deleteById(t){let r=await this.readHistory(),n=r.filter(o=>o.id!==t);return n.length===r.length?false:(await this.writeHistory(n),true)}async clear(){await this.writeHistory([]);}async findById(t){return (await this.readHistory()).find(n=>n.id===t)||null}async findByShortId(t){return (await this.readHistory()).filter(n=>n.id.startsWith(t))}async findByHash(t,r,n){return (await this.readHistory()).find(i=>i.sourceHash===t&&i.sourceLang===r&&i.targetLang===n)||null}};function F(e){return createHash("sha256").update(e).digest("hex")}async function U(e,t){try{if(!e&&!t.file&&!process.stdin.isTTY){let r=await Z();await A(r,t,"stdin");return}if(t.file){if(!l.existsSync(t.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t.file})`);let r=l.readFileSync(t.file,"utf-8");await A(r,t,"file");return}if(e){await A(e,t,"arg");return}console.error("error: \u5165\u529B\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093"),console.error("\u4F7F\u3044\u65B9: enja <\u30C6\u30AD\u30B9\u30C8> \u307E\u305F\u306F enja -f <\u30D5\u30A1\u30A4\u30EB> \u307E\u305F\u306F \u30D1\u30A4\u30D7\u5165\u529B"),process.exit(1);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function A(e,t,r){if(!e||e.trim().length===0)throw new Error("\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u3067\u3059");let n=e;if(t.stripHtml&&(n=V(e),!n||n.trim().length===0))throw new Error("HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u305F\u7D50\u679C\uFF0C\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u306B\u306A\u308A\u307E\u3057\u305F");let o=await B(t),i=new y,s=t.flip?"ja":"en",a=t.flip?"en":"ja",c=F(n),f=await i.findByHash(c,s,a);if(f&&t.cache!==false){console.log(`${p.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let P=f.translatedText;if(t.output)try{l.writeFileSync(t.output,P,"utf-8"),console.log(`${p.green("\u2714")} ${t.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${t.output})`)}else console.log(P);return}let m=`(${s} \u2192 ${a})`,b=Q(`\u7FFB\u8A33\u4E2D... ${m}`).start();try{let H=(await o.translate(n,s,a)).text;if(b.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${m}`),await i.add({sourceText:n,translatedText:H,sourceLang:s,targetLang:a,textLength:n.length,sourceHash:c,options:{stripHtml:t.stripHtml,file:t.file,inputMethod:r}}),t.output)try{l.writeFileSync(t.output,H,"utf-8"),console.log(`${p.green("\u2714")} ${t.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${t.output})`)}else console.log(H);}catch(P){throw b.fail(`\u7FFB\u8A33\u5931\u6557 ${m}`),P}}function Z(){return new Promise((e,t)=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",n=>{r+=n;}),process.stdin.on("end",()=>{e(r);}),process.stdin.on("error",n=>{t(n);});})}function V(e){return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,"").replace(/<[^>]+>/g,"").replace(/ /g," ").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/\n\s*\n/g,`
|
|
3
|
+
`).trim()}function E(e,t=false){return e.length===0?"\u5C65\u6B74\u306F\u3042\u308A\u307E\u305B\u3093":t?tt(e):X(e)}function X(e){let t=[];return t.push(`\u5168 ${e.length} \u4EF6\u306E\u5C65\u6B74
|
|
4
|
+
`),e.forEach((r,n)=>{let o=new Date(r.timestamp).toLocaleString("ja-JP"),i=r.sourceText.length>30?r.sourceText.replace(/[\r\n]+/g," ").substring(0,30)+"...":r.sourceText;t.push(`${p.cyan("["+(n+1)+"]")} ${r.id.substring(0,8)} | ${o}`),t.push(` ${r.sourceLang} \u2192 ${r.targetLang} | ${i}`),t.push("");}),t.join(`
|
|
5
|
+
`)}function tt(e){let t=[];return t.push(`\u5168 ${e.length} \u4EF6\u306E\u5C65\u6B74\u306E\u8A73\u7D30
|
|
6
|
+
`),e.forEach((r,n)=>{n>0&&t.push("\u2500".repeat(60));let o=new Date(r.timestamp).toLocaleString("ja-JP");if(t.push(`${p.cyan("ID:")} ${r.id}`),t.push(`${p.cyan("Date:")} ${o}`),t.push(`${p.cyan("Direction:")} ${r.sourceLang} \u2192 ${r.targetLang}`),t.push(`${p.cyan("Length:")} ${r.textLength} characters`),r.options){let i=[];r.options.inputMethod&&i.push(`input=${r.options.inputMethod}`),r.options.stripHtml&&i.push("stripHtml=true"),r.options.file&&i.push(`file=${r.options.file}`),i.length>0&&t.push(`${p.cyan("Options:")} ${i.join(", ")}`);}t.push(""),t.push(`${p.cyan("Input:")}`),t.push(r.sourceText),t.push(""),t.push(`${p.cyan("Output:")}`),t.push(r.translatedText),t.push("");}),t.join(`
|
|
7
|
+
`)}async function G(e,t){try{let r=new y;if(e){let s=e.trim();if(!s)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(s.length>=36){let f=await r.findById(s);if(!f)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${e})`);console.log(E([f],t.detail));return}if(s.length<8)throw new Error(`\u77ED\u7E2EID\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${s.length})`);let a=await r.findByShortId(s);if(a.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${e})`);let c=E(a,t.detail);console.log(c);return}if(t.delete){let s=t.delete.trim();if(!s)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(s.length>=36){if(await r.deleteById(s))console.log(`${p.green("\u2714")} \u5C65\u6B74ID ${s} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${s})`);return}if(s.length<8)throw new Error(`\u77ED\u7E2EID\u3067\u524A\u9664\u3059\u308B\u5834\u5408\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${s.length})`);let a=await r.findByShortId(s);if(a.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${s})`);if(a.length>1){console.error("error: \u6307\u5B9A\u3055\u308C\u305F\u77ED\u7E2EID\u306F\u8907\u6570\u306E\u5C65\u6B74\u306B\u4E00\u81F4\u3057\u307E\u3057\u305F\uFF0E\u5B8C\u5168\u306AID\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF0E");let m=E(a,!1);console.error(m),process.exit(1);}let c=a[0].id;if(await r.deleteById(c))console.log(`${p.green("\u2714")} \u5C65\u6B74ID ${c} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u524A\u9664\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${c})`);return}if(t.clear){await r.clear(),console.log(`${p.green("\u2714")} \u5C65\u6B74\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F`);return}let n=Number(t.number)||10,o=await r.getRecent(n),i=E(o,t.detail);console.log(i);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function N(e,t,r){let n=new w;try{if(r?.reset){await n.reset(),console.log(`${p.green("\u2714")} \u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(r?.unset){await n.unset(r.unset),console.log(`${p.green("\u2714")} ${r.unset} \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(e&&t){await n.set(e,t),console.log(`${p.green("\u2714")} ${e} \u3092\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if(e&&!t){let i=await n.get();if(e==="endpoint")console.log(i.endpoint);else if(e==="api-key")console.log(i.apiKey?J(i.apiKey):"(not set)");else if(e==="provider")console.log(i.provider);else throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`);return}let o=await n.get();console.log(`${p.blue("provider:")} ${o.provider}`),console.log(`${p.blue("endpoint:")} ${o.endpoint}`),console.log(`${p.blue("apiKey:")} ${o.apiKey?J(o.apiKey):"(not set)"}`);}catch(o){console.error(o instanceof Error?`error: ${o.message}`:o),process.exit(1);}}function J(e){if(e.length<=8)return "*".repeat(e.length);let t=4,r=e.slice(0,t),n=e.slice(-t),o="*".repeat(e.length-t*2);return `${r}${o}${n}`}var L=JSON.parse(readFileSync(new URL("../package.json",import.meta.url),"utf-8")),T=new Command;T.name("enja").usage("[arguments] [options]").description(`Description: ${L.description}`).version(L.version,"-v, --version","output the current version");T.argument("[text]","\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33\u3059\u308B").option("-f, --file <path>","\u30D5\u30A1\u30A4\u30EB\u3092\u7FFB\u8A33\u3059\u308B").option("-o, --output <path>","\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B\u3059\u308B (\u30C7\u30D5\u30A9\u30EB\u30C8: \u6A19\u6E96\u51FA\u529B)").option("-s, --strip-html","HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u3066\u304B\u3089\u7FFB\u8A33\u3059\u308B").option("-N, --no-cache","\u30AD\u30E3\u30C3\u30B7\u30E5\u3092\u4F7F\u7528\u305B\u305A\u306B\u518D\u7FFB\u8A33\u3059\u308B").option("-F, --flip","\u7FFB\u8A33\u65B9\u5411\u3092\u9006\u306B\u3059\u308B (default: \u82F1\u8A9E\u2192\u65E5\u672C\u8A9E)").option("--endpoint <url>","\u30AB\u30B9\u30BF\u30E0\u7FFB\u8A33\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A").option("--api-key <key>","API \u30AD\u30FC\u3092\u6307\u5B9A").option("--provider <name>","\u7FFB\u8A33\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A (gas, custom, openai, gemini)").showHelpAfterError().addHelpText("after",`
|
|
8
8
|
Examples:
|
|
9
9
|
$ enja "Hello, world!" # \u5F15\u6570\u3067\u6E21\u3055\u308C\u305F\u6587\u5B57\u5217\u3092\u7FFB\u8A33
|
|
10
10
|
$ git --help | enja # \u30D1\u30A4\u30D7(\u6A19\u6E96\u5165\u529B)\u3067\u6E21\u3055\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33
|
|
@@ -12,8 +12,10 @@ Examples:
|
|
|
12
12
|
$ enja -f input.txt -o output.txt # \u30D5\u30A1\u30A4\u30EB\u304B\u3089\u8AAD\u307F\u8FBC\u307F\uFF0C\u7FFB\u8A33\u7D50\u679C\u3092\u30D5\u30A1\u30A4\u30EB\u306B\u4FDD\u5B58
|
|
13
13
|
$ cat README.md | enja -o japanese.md # \u30D1\u30A4\u30D7\u3068\u30D5\u30A1\u30A4\u30EB\u51FA\u529B\u306E\u7D44\u307F\u5408\u308F\u305B
|
|
14
14
|
$ curl -s https://example.com | enja -s # HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u3066\u7FFB\u8A33
|
|
15
|
-
$ enja "Hello" --
|
|
16
|
-
Enja CLI v${
|
|
15
|
+
$ enja "Hello, world!" --provider openai --api-key YOUR_OPENAI_API_KEY # OpenAI API \u3092\u4F7F\u7528\u3057\u3066\u7FFB\u8A33`).addHelpText("afterAll",`
|
|
16
|
+
Enja CLI v${L.version}`).addHelpText("afterAll","Copyright (c) 2025 yhotta240").addHelpText("afterAll","GitHub: https://github.com/yhotamos/enja-cli").action(U);T.command("history").description("Description: \u7FFB\u8A33\u5C65\u6B74\u3092\u8868\u793A\u3059\u308B").argument("[id]","ID \u3067\u5C65\u6B74\u3092\u8868\u793A\u3059\u308B\uFF08\u5B8C\u5168 ID \u307E\u305F\u306F\u77ED\u7E2E ID\uFF09").option("-d, --detail","\u8A73\u7D30\u8868\u793A").option("-n, --number <number>","\u8868\u793A\u4EF6\u6570","10").option("--delete <id>","\u7279\u5B9A\u306E\u5C65\u6B74\u3092\u524A\u9664\u3059\u308B").option("--clear","\u5C65\u6B74\u3092\u30AF\u30EA\u30A2").action(G);T.command("config").description("Description: \u8A2D\u5B9A\u3092\u7BA1\u7406\u3059\u308B").argument("[key]","\u8A2D\u5B9A\u30AD\u30FC (endpoint, api-key, provider)").argument("[value]","\u8A2D\u5B9A\u5024").option("-l, --list","\u8A2D\u5B9A\u3092\u4E00\u89A7\u8868\u793A").option("--unset <key>","\u8A2D\u5B9A\u3092\u524A\u9664\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u623B\u3059\uFF09").option("--reset","\u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8").addHelpText("after",`
|
|
17
|
+
Values for provider: gas, custom, openai, gemini
|
|
18
|
+
|
|
17
19
|
Examples:
|
|
18
20
|
$ enja config # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A
|
|
19
21
|
$ enja config --list # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A
|
|
@@ -22,4 +24,4 @@ Examples:
|
|
|
22
24
|
$ enja config api-key <KEY> # API \u30AD\u30FC\u3092\u8A2D\u5B9A
|
|
23
25
|
$ enja config provider gas # \u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u8A2D\u5B9A
|
|
24
26
|
$ enja config --unset api-key # API \u30AD\u30FC\u3092\u524A\u9664
|
|
25
|
-
$ enja config --reset # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8`).action(N);
|
|
27
|
+
$ enja config --reset # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8`).action(N);T.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yhotamos/enja-cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "英語を日本語に翻訳するシンプルなコマンドラインツール",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -60,8 +60,10 @@
|
|
|
60
60
|
},
|
|
61
61
|
"homepage": "https://github.com/yhotamos/enja-cli#readme",
|
|
62
62
|
"dependencies": {
|
|
63
|
+
"@google/genai": "^1.33.0",
|
|
63
64
|
"commander": "^14.0.2",
|
|
64
65
|
"kleur": "^4.1.5",
|
|
66
|
+
"openai": "^6.9.1",
|
|
65
67
|
"ora": "^9.0.0"
|
|
66
68
|
},
|
|
67
69
|
"devDependencies": {
|