Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Migrate the whole project from cjs to esm #137

Merged
merged 20 commits into from
Sep 24, 2024
14 changes: 7 additions & 7 deletions index.js → bin/fanyi.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { Groq } = require('groq-sdk');
const print = require('./lib/print');
const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
const { XMLParser } = require('fast-xml-parser');
const ora = require('ora');
const gradient = require('gradient-string');
import { Groq } from 'groq-sdk';
import print from '../lib/print.mjs';
import fetch from 'node-fetch';
import { XMLParser } from 'fast-xml-parser';
afc163 marked this conversation as resolved.
Show resolved Hide resolved
import ora from 'ora';
import gradient from 'gradient-string';

const gradients = [
'cristal',
Expand All @@ -21,7 +21,7 @@ const gradients = [
'rainbow',
];

module.exports = async (word, options) => {
export default async (word, options) => {
console.log('');
const { iciba, groq, GROQ_API_KEY } = options;
const endcodedWord = encodeURIComponent(word);
Expand Down
125 changes: 125 additions & 0 deletions index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Groq } from 'groq-sdk';
import print from './lib/print.mjs';
import fetch from 'node-fetch';
afc163 marked this conversation as resolved.
Show resolved Hide resolved
import { XMLParser } from 'fast-xml-parser';
import ora from 'ora';
import gradient from 'gradient-string';

const gradients = [
'cristal',
'teen',
'mind',
'morning',
'vice',
'passion',
'fruit',
'instagram',
'atlas',
'retro',
'summer',
'pastel',
'rainbow',
];

export default async (word, options) => {
console.log('');
const { iciba, groq, GROQ_API_KEY } = options;
const endcodedWord = encodeURIComponent(word);

// iciba
if (isTrueOrUndefined(iciba)) {
const ICIBA_URL =
'http://dict-co.iciba.com/api/dictionary.php?key=D191EBD014295E913574E1EAF8E06666&w=';
const spinner = ora('正在请教 iciba...').start();
try {
const response = await fetch(`${ICIBA_URL}${endcodedWord}`);
const xml = await response.text();
const parser = new XMLParser();
const result = parser.parse(xml);
spinner.stop();
print.iciba(result.dict, options);
} catch (error) {
spinner.fail('访问 iciba 失败,请检查网络');
}
}

// groq ai
if (isTrueOrUndefined(groq)) {
const groqClient = new Groq({
apiKey: GROQ_API_KEY || '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',
afc163 marked this conversation as resolved.
Show resolved Hide resolved
});
const model = 'llama-3.1-70b-versatile';
const spinner = ora(`正在请教 ${model}...`).start();
try {
const chatCompletion = await groqClient.chat.completions.create({
messages: [
{
role: 'system',
content: `
你是一本专业的中英文双语词典。请按照以下要求提供翻译和解释:

1. 格式要求:
[原词] [音标] ~ [翻译] [拼音] ~ [EMOJI]

- [词性] [释义1]
- [词性] [释义2]
...

例句:
1. [原文例句]
[翻译]
2. [原文例句]
[翻译]
...

[EMOJI] [座右铭]
-----

2. 翻译规则:
- 英文输入翻译为中文,中文输入翻译为英文
- 提供准确的音标(英文)或拼音(中文)
- 列出所有常见词性及其对应的释义
- 释义应简洁明了,涵盖词语的主要含义,使用中文
- 提供2-3个地道的例句,体现词语的不同用法和语境

3. 内容质量:
- 确保翻译和释义的准确性和权威性
- 例句应当实用、常见,并能体现词语的典型用法
- 注意词语的语体色彩,如正式、口语、书面语等
- 对于多义词,按照使用频率由高到低排列释义

4. 特殊情况:
- 对于习语、谚语或特殊表达,提供对应的解释和等效表达
- 注明词语的使用范围,如地域、行业特定用语等
- 对于缩写词,提供完整形式和解释

5. 格式中的 [EMOJI] 指的是一个 emoji 表情符号,请根据词性、释义、例句等选择合适的表情符号。

请基于以上要求,为用户提供简洁、专业、全面且易于理解的词语翻译和解释。

---
最后使用这个词写一句简短的积极向上令人深思的英文座右铭,并提供中文翻译。但回复中不要包含"座右铭"三个字
`,
},
{
role: 'user',
content: `请翻译:${word}`,
},
],
model,
temperature: 0.3,
max_tokens: 1024,
top_p: 0.8,
});
spinner.stop();
const randomGradient = gradients[Math.floor(Math.random() * gradients.length)];
console.log(gradient[randomGradient](chatCompletion.choices[0].message.content));
} catch (error) {
spinner.fail(`访问 ${model} 失败,请检查网络或 API 密钥`);
}
}
};

function isTrueOrUndefined(val) {
return val === true || val === undefined;
}
12 changes: 7 additions & 5 deletions lib/config.js → lib/config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const homedir = process.env.HOME || require('node:os').homedir();
const path = require('node:path');
const fs = require('node:fs');
const chalk = require('chalk');
import { homedir as getHomedir } from 'node:os';
import path from 'node:path';
afc163 marked this conversation as resolved.
Show resolved Hide resolved
import fs from 'node:fs';
import chalk from 'chalk';

const homedir = process.env.HOME || getHomedir();
const configDir = path.resolve(homedir, '.config', 'fanyi');
const configPath = path.resolve(configDir, '.fanyirc');

Expand Down Expand Up @@ -40,4 +42,4 @@ const config = {
},
};

module.exports = config;
export default config;
6 changes: 3 additions & 3 deletions lib/print.js → lib/print.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { saveHistory } = require('./searchHistory');
let chalk = require('chalk');
import { saveHistory } from './searchHistory';
import chalk from 'chalk';

exports.iciba = (data, options = {}) => {
export const iciba = (data, options = {}) => {
if (options.color === false) {
chalk = initChalkWithNoColor();
}
afc163 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
15 changes: 8 additions & 7 deletions lib/searchHistory.js → lib/searchHistory.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const fs = require('fs-extra');
const path = require('node:path');
const chalk = require('chalk');
const dayjs = require('dayjs');
import fs from 'fs-extra';
import path from 'node:path';
import chalk from 'chalk';
import dayjs from 'dayjs';
import os from 'node:os';

afc163 marked this conversation as resolved.
Show resolved Hide resolved
const homedir = process.env.HOME || require('node:os').homedir();
const homedir = process.env.HOME || os.homedir();
const searchFilePath = path.resolve(homedir, '.config', 'fanyi', 'searchHistory.txt');

const DAY_SPLIT = 'day-';
Expand Down Expand Up @@ -35,7 +36,7 @@ function getDaySplit(someDay) {
return `${DAY_SPLIT}${someDay}:`;
}

exports.searchList = (args) => {
export const searchList = (args) => {
const { someDay, recentDays, showFile } = args;
console.log();
console.log(chalk.gray('fanyi history:'));
Expand Down Expand Up @@ -97,7 +98,7 @@ exports.searchList = (args) => {
}
};

exports.saveHistory = (word, means) => {
export const saveHistory = (word, means) => {
try {
fs.ensureFileSync(searchFilePath);

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@
"prepublishOnly": "np --no-cleanup --no-publish",
"lint-staged": "lint-staged",
"prepare": "husky"
}
},
"type": "module"
}
2 changes: 1 addition & 1 deletion tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { fork } from 'node:child_process';
import path from 'node:path';
import { describe, expect, it } from 'vitest';

const scriptPath = path.resolve(__dirname, '../bin/fanyi.js');
const scriptPath = path.resolve(__dirname, '../bin/fanyi.mjs');

const runScript = (args: string[] = []): Promise<{ stdout: string; stderr: string }> => {
return new Promise((resolve, reject) => {
afc163 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading