github-actions[bot]
commited on
Commit
·
913d114
0
Parent(s):
GitHub deploy: fe3a9c4cecbd9cba7d18b8a7c1f8af7c90bed87d
Browse files- .gitattributes +1 -0
- .github/PULL_REQUEST_TEMPLATE.md +39 -0
- .github/workflows/deploy-to-hf-spaces.yml +60 -0
- .github/workflows/docker-image.yml +42 -0
- .github/workflows/translate-readme.yml +40 -0
- .gitignore +134 -0
- .htaccess +1 -0
- .vscode/launch.json +17 -0
- Dockerfile +24 -0
- README.md +0 -0
- index.html +77 -0
- logo.webp +0 -0
- package-lock.json +494 -0
- package.json +17 -0
- translate.js +204 -0
.gitattributes
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
*.ttf filter=lfs diff=lfs merge=lfs -text
|
.github/PULL_REQUEST_TEMPLATE.md
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!--
|
2 |
+
### Free SaaS Offering Submission
|
3 |
+
|
4 |
+
Thank you for contributing to this list. This list is for **SaaS**
|
5 |
+
services that offer a **free tier** to help developers evaluate and
|
6 |
+
build something that users can later use and get support for.
|
7 |
+
|
8 |
+
The focus of this list is quite broad but we try to keep things
|
9 |
+
limited to that which infrastructure developers, like DevOps Practitioners,
|
10 |
+
would find useful.
|
11 |
+
|
12 |
+
This list is the result of more than a thousand people contributing
|
13 |
+
to make something useful, we appreciate your efforts.
|
14 |
+
|
15 |
+
### Code of Conduct
|
16 |
+
|
17 |
+
We are not here to argue with you. If you are argumentative, abusive,
|
18 |
+
lie or missrepresent your service or are otherwise anti-social we will
|
19 |
+
block you.
|
20 |
+
|
21 |
+
### Services we do not accept
|
22 |
+
|
23 |
+
* cPanel like PHP + MySQL hosting services.
|
24 |
+
* Free dns services that are generic frontends to CloudFlare or similar
|
25 |
+
* Services that are verbatim copy pastes of others while adding no value
|
26 |
+
* Fake / Temporary / Ephemeral email generators, we have enough of those
|
27 |
+
-->
|
28 |
+
|
29 |
+
## Requirements
|
30 |
+
|
31 |
+
<!-- This is only for new submissions -->
|
32 |
+
<!-- Please ensure your submission ticks all of the requirements -->
|
33 |
+
|
34 |
+
* [ ] This is Software as a Service not self hosted
|
35 |
+
* [ ] It has a free tier not just a free trial
|
36 |
+
* [ ] Pricing information is clearly visible without signup or phone calls
|
37 |
+
* [ ] The submission mentions what is free
|
38 |
+
* [ ] The submission is not already present in the list
|
39 |
+
* [ ] The service has contact details of those running it and a privacy policy
|
.github/workflows/deploy-to-hf-spaces.yml
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: 部署到抱抱脸空间
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- dev
|
7 |
+
- main
|
8 |
+
workflow_dispatch:
|
9 |
+
|
10 |
+
jobs:
|
11 |
+
check-secret:
|
12 |
+
runs-on: ubuntu-latest
|
13 |
+
outputs:
|
14 |
+
token-set: ${{ steps.check-key.outputs.defined }}
|
15 |
+
steps:
|
16 |
+
- id: check-key
|
17 |
+
env:
|
18 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
19 |
+
if: "${{ env.HF_TOKEN != '' }}"
|
20 |
+
run: echo "defined=true" >> $GITHUB_OUTPUT
|
21 |
+
|
22 |
+
deploy:
|
23 |
+
runs-on: ubuntu-latest
|
24 |
+
needs: [check-secret]
|
25 |
+
if: needs.check-secret.outputs.token-set == 'true'
|
26 |
+
env:
|
27 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
28 |
+
HF_REPO: ${{ secrets.HF_REPO }}
|
29 |
+
HF_USER: ${{ secrets.HF_USER }}
|
30 |
+
steps:
|
31 |
+
- name: 检测仓库
|
32 |
+
uses: actions/checkout@v4
|
33 |
+
|
34 |
+
- name: 移除git历史记录
|
35 |
+
run: rm -rf .git
|
36 |
+
|
37 |
+
- name: 将YAML前言添加到README.md中
|
38 |
+
run: |
|
39 |
+
echo "---" > temp_readme.md
|
40 |
+
echo "title: Free For Dev" >> temp_readme.md
|
41 |
+
echo "emoji: 🐳" >> temp_readme.md
|
42 |
+
echo "colorFrom: purple" >> temp_readme.md
|
43 |
+
echo "colorTo: gray" >> temp_readme.md
|
44 |
+
echo "sdk: docker" >> temp_readme.md
|
45 |
+
echo "app_port: 8080" >> temp_readme.md
|
46 |
+
echo "---" >> temp_readme.md
|
47 |
+
cat README.md >> temp_readme.md
|
48 |
+
mv temp_readme.md README.md
|
49 |
+
|
50 |
+
- name: 配置git
|
51 |
+
run: |
|
52 |
+
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
53 |
+
git config --global user.name "github-actions[bot]"
|
54 |
+
- name: 设置Git并推送到空间
|
55 |
+
run: |
|
56 |
+
git init --initial-branch=main
|
57 |
+
git lfs track "*.ttf"
|
58 |
+
git add .
|
59 |
+
git commit -m "GitHub deploy: ${{ github.sha }}"
|
60 |
+
git push --force https://${HF_USER}:${HF_TOKEN}@huggingface.co/spaces/${HF_USER}/${HF_REPO} main
|
.github/workflows/docker-image.yml
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: 构建并推送Docker镜像
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- main
|
7 |
+
pull_request:
|
8 |
+
branches:
|
9 |
+
- main
|
10 |
+
workflow_dispatch:
|
11 |
+
|
12 |
+
jobs:
|
13 |
+
build:
|
14 |
+
runs-on: ubuntu-latest
|
15 |
+
|
16 |
+
steps:
|
17 |
+
- name: 检出代码
|
18 |
+
uses: actions/checkout@v3
|
19 |
+
|
20 |
+
- name: 登录到GitHub容器注册表
|
21 |
+
uses: docker/login-action@v2
|
22 |
+
with:
|
23 |
+
registry: ghcr.io
|
24 |
+
username: ${{ github.actor }}
|
25 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
26 |
+
|
27 |
+
- name: 设置小写的用户名和仓库名称
|
28 |
+
run: |
|
29 |
+
REPO_FULL_NAME=${{ github.repository }}
|
30 |
+
REPO_OWNER=$(echo "${REPO_FULL_NAME}" | cut -d'/' -f1 | tr '[:upper:]' '[:lower:]')
|
31 |
+
REPO_NAME=$(echo "${REPO_FULL_NAME}" | cut -d'/' -f2 | tr '[:upper:]' '[:lower:]')
|
32 |
+
echo "REPO_NAME_LOWER=${REPO_OWNER}/${REPO_NAME}" >> $GITHUB_ENV
|
33 |
+
|
34 |
+
- name: 构建Docker镜像
|
35 |
+
run: |
|
36 |
+
docker build . -t ghcr.io/$REPO_NAME_LOWER:latest
|
37 |
+
shell: bash
|
38 |
+
|
39 |
+
- name: 推送Docker镜像
|
40 |
+
run: |
|
41 |
+
docker push ghcr.io/$REPO_NAME_LOWER:latest
|
42 |
+
shell: bash
|
.github/workflows/translate-readme.yml
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Translate README
|
2 |
+
# 注意需要推送..所以要开启写入权限 Settings -> Actions -> General -> Workflow permissions:Read and write permissions
|
3 |
+
|
4 |
+
on:
|
5 |
+
workflow_dispatch:
|
6 |
+
schedule:
|
7 |
+
- cron: '0 1 * * 1' # 每周运行
|
8 |
+
|
9 |
+
jobs:
|
10 |
+
translate:
|
11 |
+
runs-on: ubuntu-latest
|
12 |
+
|
13 |
+
steps:
|
14 |
+
- name: Checkout code
|
15 |
+
uses: actions/checkout@v4
|
16 |
+
with:
|
17 |
+
token: ${{ secrets.GITHUB_TOKEN }}
|
18 |
+
|
19 |
+
- name: Clone ripienaar/free-for-dev
|
20 |
+
run: |
|
21 |
+
git clone https://github.com/zhezzma/free-for-dev-cn.git free-for-dev
|
22 |
+
|
23 |
+
- name: Setup Node.js
|
24 |
+
uses: actions/setup-node@v4
|
25 |
+
with:
|
26 |
+
node-version: '18'
|
27 |
+
|
28 |
+
- name: Install dependencies
|
29 |
+
run: |
|
30 |
+
npm install
|
31 |
+
|
32 |
+
- name: Commit and push if changed
|
33 |
+
env:
|
34 |
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
35 |
+
run: |
|
36 |
+
git config --local user.email "[email protected]"
|
37 |
+
git config --local user.name "GitHub Action"
|
38 |
+
git add README.md
|
39 |
+
git commit -m "Update README.md" || echo "No changes to commit"
|
40 |
+
git push
|
.gitignore
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Logs
|
2 |
+
logs
|
3 |
+
*.log
|
4 |
+
npm-debug.log*
|
5 |
+
yarn-debug.log*
|
6 |
+
yarn-error.log*
|
7 |
+
lerna-debug.log*
|
8 |
+
.pnpm-debug.log*
|
9 |
+
|
10 |
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
11 |
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
12 |
+
|
13 |
+
# Runtime data
|
14 |
+
pids
|
15 |
+
*.pid
|
16 |
+
*.seed
|
17 |
+
*.pid.lock
|
18 |
+
|
19 |
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
20 |
+
lib-cov
|
21 |
+
|
22 |
+
# Coverage directory used by tools like istanbul
|
23 |
+
coverage
|
24 |
+
*.lcov
|
25 |
+
|
26 |
+
# nyc test coverage
|
27 |
+
.nyc_output
|
28 |
+
|
29 |
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
30 |
+
.grunt
|
31 |
+
|
32 |
+
# Bower dependency directory (https://bower.io/)
|
33 |
+
bower_components
|
34 |
+
|
35 |
+
# node-waf configuration
|
36 |
+
.lock-wscript
|
37 |
+
|
38 |
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
39 |
+
build/Release
|
40 |
+
|
41 |
+
# Dependency directories
|
42 |
+
node_modules/
|
43 |
+
jspm_packages/
|
44 |
+
|
45 |
+
# Snowpack dependency directory (https://snowpack.dev/)
|
46 |
+
web_modules/
|
47 |
+
|
48 |
+
# TypeScript cache
|
49 |
+
*.tsbuildinfo
|
50 |
+
|
51 |
+
# Optional npm cache directory
|
52 |
+
.npm
|
53 |
+
|
54 |
+
# Optional eslint cache
|
55 |
+
.eslintcache
|
56 |
+
|
57 |
+
# Optional stylelint cache
|
58 |
+
.stylelintcache
|
59 |
+
|
60 |
+
# Microbundle cache
|
61 |
+
.rpt2_cache/
|
62 |
+
.rts2_cache_cjs/
|
63 |
+
.rts2_cache_es/
|
64 |
+
.rts2_cache_umd/
|
65 |
+
|
66 |
+
# Optional REPL history
|
67 |
+
.node_repl_history
|
68 |
+
|
69 |
+
# Output of 'npm pack'
|
70 |
+
*.tgz
|
71 |
+
|
72 |
+
# Yarn Integrity file
|
73 |
+
.yarn-integrity
|
74 |
+
|
75 |
+
# dotenv environment variable files
|
76 |
+
.env
|
77 |
+
.env.development.local
|
78 |
+
.env.test.local
|
79 |
+
.env.production.local
|
80 |
+
.env.local
|
81 |
+
|
82 |
+
# parcel-bundler cache (https://parceljs.org/)
|
83 |
+
.cache
|
84 |
+
.parcel-cache
|
85 |
+
|
86 |
+
# Next.js build output
|
87 |
+
.next
|
88 |
+
out
|
89 |
+
|
90 |
+
# Nuxt.js build / generate output
|
91 |
+
.nuxt
|
92 |
+
dist
|
93 |
+
|
94 |
+
# Gatsby files
|
95 |
+
.cache/
|
96 |
+
# Comment in the public line in if your project uses Gatsby and not Next.js
|
97 |
+
# https://nextjs.org/blog/next-9-1#public-directory-support
|
98 |
+
# public
|
99 |
+
|
100 |
+
# vuepress build output
|
101 |
+
.vuepress/dist
|
102 |
+
|
103 |
+
# vuepress v2.x temp and cache directory
|
104 |
+
.temp
|
105 |
+
.cache
|
106 |
+
|
107 |
+
# Docusaurus cache and generated files
|
108 |
+
.docusaurus
|
109 |
+
|
110 |
+
# Serverless directories
|
111 |
+
.serverless/
|
112 |
+
|
113 |
+
# FuseBox cache
|
114 |
+
.fusebox/
|
115 |
+
|
116 |
+
# DynamoDB Local files
|
117 |
+
.dynamodb/
|
118 |
+
|
119 |
+
# TernJS port file
|
120 |
+
.tern-port
|
121 |
+
|
122 |
+
# Stores VSCode versions used for testing VSCode extensions
|
123 |
+
.vscode-test
|
124 |
+
|
125 |
+
# yarn v2
|
126 |
+
.yarn/cache
|
127 |
+
.yarn/unplugged
|
128 |
+
.yarn/build-state.yml
|
129 |
+
.yarn/install-state.gz
|
130 |
+
.pnp.*
|
131 |
+
|
132 |
+
|
133 |
+
# app
|
134 |
+
free-for-dev
|
.htaccess
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
.vscode/launch.json
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"version": "0.2.0",
|
3 |
+
"configurations": [
|
4 |
+
{
|
5 |
+
"type": "node",
|
6 |
+
"request": "launch",
|
7 |
+
"name": "test",
|
8 |
+
"runtimeExecutable": "npm",
|
9 |
+
"runtimeArgs": [
|
10 |
+
"run",
|
11 |
+
"test"
|
12 |
+
],
|
13 |
+
"console": "internalConsole",
|
14 |
+
"internalConsoleOptions": "neverOpen",
|
15 |
+
}
|
16 |
+
]
|
17 |
+
}
|
Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM php:8.3-apache
|
2 |
+
|
3 |
+
RUN a2enmod rewrite
|
4 |
+
|
5 |
+
RUN sed -i 's/Listen 80/Listen 8080/' /etc/apache2/ports.conf && \
|
6 |
+
sed -i 's/:80>/:8080>/' /etc/apache2/sites-available/000-default.conf
|
7 |
+
|
8 |
+
RUN echo '<Directory /var/www/html>\n\
|
9 |
+
AllowOverride All\n\
|
10 |
+
</Directory>' >> /etc/apache2/sites-available/000-default.conf
|
11 |
+
|
12 |
+
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
13 |
+
|
14 |
+
WORKDIR /var/www/html
|
15 |
+
|
16 |
+
COPY . /var/www/html
|
17 |
+
|
18 |
+
RUN chmod -R 777 /var/www/html
|
19 |
+
|
20 |
+
COPY .htaccess /var/www/html/.htaccess
|
21 |
+
|
22 |
+
EXPOSE 8080
|
23 |
+
|
24 |
+
CMD ["apache2-foreground"]
|
README.md
ADDED
The diff for this file is too large to render.
See raw diff
|
|
index.html
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
5 |
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6 |
+
<meta charset="UTF-8">
|
7 |
+
|
8 |
+
<!-- HTML Meta Tags -->
|
9 |
+
<title>Free for Developers</title>
|
10 |
+
<meta name="description" content="Developers and Open Source authors now have a massive amount of services offering free tiers, but it can be hard to find them all to make informed decisions.">
|
11 |
+
|
12 |
+
<!-- Google / Search Engine Tags -->
|
13 |
+
<meta itemprop="name" content="Free for Developers">
|
14 |
+
<meta itemprop="description" content="Developers and Open Source authors now have a massive amount of services offering free tiers, but it can be hard to find them all to make informed decisions.">
|
15 |
+
<meta itemprop="image" content="https://raw.githubusercontent.com/foss-android/free-for-dev-cn/main/logo.webp">
|
16 |
+
|
17 |
+
<!-- Facebook Meta Tags -->
|
18 |
+
<meta property="og:url" content="https://free-for.dev">
|
19 |
+
<meta property="og:type" content="website">
|
20 |
+
<meta property="og:title" content="Free for Developers">
|
21 |
+
<meta property="og:description" content="Developers and Open Source authors now have a massive amount of services offering free tiers, but it can be hard to find them all to make informed decisions.">
|
22 |
+
<meta property="og:image" content="https://raw.githubusercontent.com/foss-android/free-for-dev-cn/main/logo.webp">
|
23 |
+
|
24 |
+
<!-- Twitter Meta Tags -->
|
25 |
+
<meta name="twitter:card" content="summary_large_image">
|
26 |
+
<meta name="twitter:title" content="Free for Developers">
|
27 |
+
<meta name="twitter:description" content="Developers and Open Source authors now have a massive amount of services offering free tiers, but it can be hard to find them all to make informed decisions.">
|
28 |
+
<meta name="twitter:image" content="https://raw.githubusercontent.com/foss-android/free-for-dev-cn/main/logo.webp">
|
29 |
+
|
30 |
+
<!-- Stylesheets -->
|
31 |
+
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/vue.css">
|
32 |
+
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/style.min.css" title="docsify-darklight-theme" type="text/css">
|
33 |
+
|
34 |
+
<!-- Favicon -->
|
35 |
+
<link rel="icon" href="logo.webp" type="image/gif">
|
36 |
+
|
37 |
+
<!-- Google Analytics -->
|
38 |
+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DLYKZXPL9J"></script>
|
39 |
+
<script>
|
40 |
+
window.dataLayer = window.dataLayer || [];
|
41 |
+
function gtag(){dataLayer.push(arguments);}
|
42 |
+
gtag('js', new Date());
|
43 |
+
|
44 |
+
gtag('config', 'G-DLYKZXPL9J');
|
45 |
+
</script>
|
46 |
+
</head>
|
47 |
+
|
48 |
+
<body>
|
49 |
+
<noscript>This page requires JavaScript to work, please enable it or read <a href="https://github.com/foss-android/free-for-dev-cn">here</a>.</noscript>
|
50 |
+
|
51 |
+
<div id="app">Loading...</div>
|
52 |
+
|
53 |
+
<script>
|
54 |
+
window.$docsify = {
|
55 |
+
name: "Free for Developers",
|
56 |
+
repo: "zhezzma/free-for-dev-cn",
|
57 |
+
search: ["/"],
|
58 |
+
darklightTheme: {
|
59 |
+
siteFont : "Source Sans Pro, Helvetica Neue",
|
60 |
+
defaultTheme : "light",
|
61 |
+
codeFontFamily : "Roboto Mono, Monaco, courier, monospace",
|
62 |
+
bodyFontSize: "15px"
|
63 |
+
}
|
64 |
+
}
|
65 |
+
</script>
|
66 |
+
|
67 |
+
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
|
68 |
+
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
69 |
+
<script src="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/index.min.js" type="text/javascript"></script>
|
70 |
+
|
71 |
+
<style>
|
72 |
+
blockquote:first-of-type {
|
73 |
+
background-color: rgba(235, 248, 242, 0.363);
|
74 |
+
}
|
75 |
+
</style>
|
76 |
+
</body>
|
77 |
+
</html>
|
logo.webp
ADDED
![]() |
package-lock.json
ADDED
@@ -0,0 +1,494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "free-for-dev-cn",
|
3 |
+
"version": "1.0.0",
|
4 |
+
"lockfileVersion": 3,
|
5 |
+
"requires": true,
|
6 |
+
"packages": {
|
7 |
+
"": {
|
8 |
+
"name": "free-for-dev-cn",
|
9 |
+
"version": "1.0.0",
|
10 |
+
"license": "ISC",
|
11 |
+
"dependencies": {
|
12 |
+
"dotenv": "^16.4.5",
|
13 |
+
"openai": "^4.61.0"
|
14 |
+
}
|
15 |
+
},
|
16 |
+
"node_modules/@types/node": {
|
17 |
+
"version": "18.19.50",
|
18 |
+
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.50.tgz",
|
19 |
+
"integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==",
|
20 |
+
"license": "MIT",
|
21 |
+
"dependencies": {
|
22 |
+
"undici-types": "~5.26.4"
|
23 |
+
}
|
24 |
+
},
|
25 |
+
"node_modules/@types/node-fetch": {
|
26 |
+
"version": "2.6.11",
|
27 |
+
"resolved": "https://registry.npmmirror.com/@types/node-fetch/-/node-fetch-2.6.11.tgz",
|
28 |
+
"integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
|
29 |
+
"license": "MIT",
|
30 |
+
"dependencies": {
|
31 |
+
"@types/node": "*",
|
32 |
+
"form-data": "^4.0.0"
|
33 |
+
}
|
34 |
+
},
|
35 |
+
"node_modules/@types/qs": {
|
36 |
+
"version": "6.9.16",
|
37 |
+
"resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.9.16.tgz",
|
38 |
+
"integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==",
|
39 |
+
"license": "MIT"
|
40 |
+
},
|
41 |
+
"node_modules/abort-controller": {
|
42 |
+
"version": "3.0.0",
|
43 |
+
"resolved": "https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz",
|
44 |
+
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
45 |
+
"license": "MIT",
|
46 |
+
"dependencies": {
|
47 |
+
"event-target-shim": "^5.0.0"
|
48 |
+
},
|
49 |
+
"engines": {
|
50 |
+
"node": ">=6.5"
|
51 |
+
}
|
52 |
+
},
|
53 |
+
"node_modules/agentkeepalive": {
|
54 |
+
"version": "4.5.0",
|
55 |
+
"resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
|
56 |
+
"integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
|
57 |
+
"license": "MIT",
|
58 |
+
"dependencies": {
|
59 |
+
"humanize-ms": "^1.2.1"
|
60 |
+
},
|
61 |
+
"engines": {
|
62 |
+
"node": ">= 8.0.0"
|
63 |
+
}
|
64 |
+
},
|
65 |
+
"node_modules/asynckit": {
|
66 |
+
"version": "0.4.0",
|
67 |
+
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
|
68 |
+
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
69 |
+
"license": "MIT"
|
70 |
+
},
|
71 |
+
"node_modules/call-bind": {
|
72 |
+
"version": "1.0.7",
|
73 |
+
"resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz",
|
74 |
+
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
75 |
+
"license": "MIT",
|
76 |
+
"dependencies": {
|
77 |
+
"es-define-property": "^1.0.0",
|
78 |
+
"es-errors": "^1.3.0",
|
79 |
+
"function-bind": "^1.1.2",
|
80 |
+
"get-intrinsic": "^1.2.4",
|
81 |
+
"set-function-length": "^1.2.1"
|
82 |
+
},
|
83 |
+
"engines": {
|
84 |
+
"node": ">= 0.4"
|
85 |
+
},
|
86 |
+
"funding": {
|
87 |
+
"url": "https://github.com/sponsors/ljharb"
|
88 |
+
}
|
89 |
+
},
|
90 |
+
"node_modules/combined-stream": {
|
91 |
+
"version": "1.0.8",
|
92 |
+
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
|
93 |
+
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
94 |
+
"license": "MIT",
|
95 |
+
"dependencies": {
|
96 |
+
"delayed-stream": "~1.0.0"
|
97 |
+
},
|
98 |
+
"engines": {
|
99 |
+
"node": ">= 0.8"
|
100 |
+
}
|
101 |
+
},
|
102 |
+
"node_modules/define-data-property": {
|
103 |
+
"version": "1.1.4",
|
104 |
+
"resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
|
105 |
+
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
106 |
+
"license": "MIT",
|
107 |
+
"dependencies": {
|
108 |
+
"es-define-property": "^1.0.0",
|
109 |
+
"es-errors": "^1.3.0",
|
110 |
+
"gopd": "^1.0.1"
|
111 |
+
},
|
112 |
+
"engines": {
|
113 |
+
"node": ">= 0.4"
|
114 |
+
},
|
115 |
+
"funding": {
|
116 |
+
"url": "https://github.com/sponsors/ljharb"
|
117 |
+
}
|
118 |
+
},
|
119 |
+
"node_modules/delayed-stream": {
|
120 |
+
"version": "1.0.0",
|
121 |
+
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
122 |
+
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
123 |
+
"license": "MIT",
|
124 |
+
"engines": {
|
125 |
+
"node": ">=0.4.0"
|
126 |
+
}
|
127 |
+
},
|
128 |
+
"node_modules/dotenv": {
|
129 |
+
"version": "16.4.5",
|
130 |
+
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz",
|
131 |
+
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
|
132 |
+
"license": "BSD-2-Clause",
|
133 |
+
"engines": {
|
134 |
+
"node": ">=12"
|
135 |
+
},
|
136 |
+
"funding": {
|
137 |
+
"url": "https://dotenvx.com"
|
138 |
+
}
|
139 |
+
},
|
140 |
+
"node_modules/es-define-property": {
|
141 |
+
"version": "1.0.0",
|
142 |
+
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz",
|
143 |
+
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
144 |
+
"license": "MIT",
|
145 |
+
"dependencies": {
|
146 |
+
"get-intrinsic": "^1.2.4"
|
147 |
+
},
|
148 |
+
"engines": {
|
149 |
+
"node": ">= 0.4"
|
150 |
+
}
|
151 |
+
},
|
152 |
+
"node_modules/es-errors": {
|
153 |
+
"version": "1.3.0",
|
154 |
+
"resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
|
155 |
+
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
156 |
+
"license": "MIT",
|
157 |
+
"engines": {
|
158 |
+
"node": ">= 0.4"
|
159 |
+
}
|
160 |
+
},
|
161 |
+
"node_modules/event-target-shim": {
|
162 |
+
"version": "5.0.1",
|
163 |
+
"resolved": "https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
164 |
+
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
165 |
+
"license": "MIT",
|
166 |
+
"engines": {
|
167 |
+
"node": ">=6"
|
168 |
+
}
|
169 |
+
},
|
170 |
+
"node_modules/form-data": {
|
171 |
+
"version": "4.0.0",
|
172 |
+
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
|
173 |
+
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
174 |
+
"license": "MIT",
|
175 |
+
"dependencies": {
|
176 |
+
"asynckit": "^0.4.0",
|
177 |
+
"combined-stream": "^1.0.8",
|
178 |
+
"mime-types": "^2.1.12"
|
179 |
+
},
|
180 |
+
"engines": {
|
181 |
+
"node": ">= 6"
|
182 |
+
}
|
183 |
+
},
|
184 |
+
"node_modules/form-data-encoder": {
|
185 |
+
"version": "1.7.2",
|
186 |
+
"resolved": "https://registry.npmmirror.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
|
187 |
+
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
|
188 |
+
"license": "MIT"
|
189 |
+
},
|
190 |
+
"node_modules/formdata-node": {
|
191 |
+
"version": "4.4.1",
|
192 |
+
"resolved": "https://registry.npmmirror.com/formdata-node/-/formdata-node-4.4.1.tgz",
|
193 |
+
"integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
|
194 |
+
"license": "MIT",
|
195 |
+
"dependencies": {
|
196 |
+
"node-domexception": "1.0.0",
|
197 |
+
"web-streams-polyfill": "4.0.0-beta.3"
|
198 |
+
},
|
199 |
+
"engines": {
|
200 |
+
"node": ">= 12.20"
|
201 |
+
}
|
202 |
+
},
|
203 |
+
"node_modules/function-bind": {
|
204 |
+
"version": "1.1.2",
|
205 |
+
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
|
206 |
+
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
207 |
+
"license": "MIT",
|
208 |
+
"funding": {
|
209 |
+
"url": "https://github.com/sponsors/ljharb"
|
210 |
+
}
|
211 |
+
},
|
212 |
+
"node_modules/get-intrinsic": {
|
213 |
+
"version": "1.2.4",
|
214 |
+
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
215 |
+
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
216 |
+
"license": "MIT",
|
217 |
+
"dependencies": {
|
218 |
+
"es-errors": "^1.3.0",
|
219 |
+
"function-bind": "^1.1.2",
|
220 |
+
"has-proto": "^1.0.1",
|
221 |
+
"has-symbols": "^1.0.3",
|
222 |
+
"hasown": "^2.0.0"
|
223 |
+
},
|
224 |
+
"engines": {
|
225 |
+
"node": ">= 0.4"
|
226 |
+
},
|
227 |
+
"funding": {
|
228 |
+
"url": "https://github.com/sponsors/ljharb"
|
229 |
+
}
|
230 |
+
},
|
231 |
+
"node_modules/gopd": {
|
232 |
+
"version": "1.0.1",
|
233 |
+
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz",
|
234 |
+
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
235 |
+
"license": "MIT",
|
236 |
+
"dependencies": {
|
237 |
+
"get-intrinsic": "^1.1.3"
|
238 |
+
},
|
239 |
+
"funding": {
|
240 |
+
"url": "https://github.com/sponsors/ljharb"
|
241 |
+
}
|
242 |
+
},
|
243 |
+
"node_modules/has-property-descriptors": {
|
244 |
+
"version": "1.0.2",
|
245 |
+
"resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
246 |
+
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
247 |
+
"license": "MIT",
|
248 |
+
"dependencies": {
|
249 |
+
"es-define-property": "^1.0.0"
|
250 |
+
},
|
251 |
+
"funding": {
|
252 |
+
"url": "https://github.com/sponsors/ljharb"
|
253 |
+
}
|
254 |
+
},
|
255 |
+
"node_modules/has-proto": {
|
256 |
+
"version": "1.0.3",
|
257 |
+
"resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz",
|
258 |
+
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
259 |
+
"license": "MIT",
|
260 |
+
"engines": {
|
261 |
+
"node": ">= 0.4"
|
262 |
+
},
|
263 |
+
"funding": {
|
264 |
+
"url": "https://github.com/sponsors/ljharb"
|
265 |
+
}
|
266 |
+
},
|
267 |
+
"node_modules/has-symbols": {
|
268 |
+
"version": "1.0.3",
|
269 |
+
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
|
270 |
+
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
271 |
+
"license": "MIT",
|
272 |
+
"engines": {
|
273 |
+
"node": ">= 0.4"
|
274 |
+
},
|
275 |
+
"funding": {
|
276 |
+
"url": "https://github.com/sponsors/ljharb"
|
277 |
+
}
|
278 |
+
},
|
279 |
+
"node_modules/hasown": {
|
280 |
+
"version": "2.0.2",
|
281 |
+
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
|
282 |
+
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
283 |
+
"license": "MIT",
|
284 |
+
"dependencies": {
|
285 |
+
"function-bind": "^1.1.2"
|
286 |
+
},
|
287 |
+
"engines": {
|
288 |
+
"node": ">= 0.4"
|
289 |
+
}
|
290 |
+
},
|
291 |
+
"node_modules/humanize-ms": {
|
292 |
+
"version": "1.2.1",
|
293 |
+
"resolved": "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
294 |
+
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
|
295 |
+
"license": "MIT",
|
296 |
+
"dependencies": {
|
297 |
+
"ms": "^2.0.0"
|
298 |
+
}
|
299 |
+
},
|
300 |
+
"node_modules/mime-db": {
|
301 |
+
"version": "1.52.0",
|
302 |
+
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
|
303 |
+
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
304 |
+
"license": "MIT",
|
305 |
+
"engines": {
|
306 |
+
"node": ">= 0.6"
|
307 |
+
}
|
308 |
+
},
|
309 |
+
"node_modules/mime-types": {
|
310 |
+
"version": "2.1.35",
|
311 |
+
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
|
312 |
+
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
313 |
+
"license": "MIT",
|
314 |
+
"dependencies": {
|
315 |
+
"mime-db": "1.52.0"
|
316 |
+
},
|
317 |
+
"engines": {
|
318 |
+
"node": ">= 0.6"
|
319 |
+
}
|
320 |
+
},
|
321 |
+
"node_modules/ms": {
|
322 |
+
"version": "2.1.3",
|
323 |
+
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
324 |
+
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
325 |
+
"license": "MIT"
|
326 |
+
},
|
327 |
+
"node_modules/node-domexception": {
|
328 |
+
"version": "1.0.0",
|
329 |
+
"resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-1.0.0.tgz",
|
330 |
+
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
331 |
+
"funding": [
|
332 |
+
{
|
333 |
+
"type": "github",
|
334 |
+
"url": "https://github.com/sponsors/jimmywarting"
|
335 |
+
},
|
336 |
+
{
|
337 |
+
"type": "github",
|
338 |
+
"url": "https://paypal.me/jimmywarting"
|
339 |
+
}
|
340 |
+
],
|
341 |
+
"license": "MIT",
|
342 |
+
"engines": {
|
343 |
+
"node": ">=10.5.0"
|
344 |
+
}
|
345 |
+
},
|
346 |
+
"node_modules/node-fetch": {
|
347 |
+
"version": "2.7.0",
|
348 |
+
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
|
349 |
+
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
350 |
+
"license": "MIT",
|
351 |
+
"dependencies": {
|
352 |
+
"whatwg-url": "^5.0.0"
|
353 |
+
},
|
354 |
+
"engines": {
|
355 |
+
"node": "4.x || >=6.0.0"
|
356 |
+
},
|
357 |
+
"peerDependencies": {
|
358 |
+
"encoding": "^0.1.0"
|
359 |
+
},
|
360 |
+
"peerDependenciesMeta": {
|
361 |
+
"encoding": {
|
362 |
+
"optional": true
|
363 |
+
}
|
364 |
+
}
|
365 |
+
},
|
366 |
+
"node_modules/object-inspect": {
|
367 |
+
"version": "1.13.2",
|
368 |
+
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.2.tgz",
|
369 |
+
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
|
370 |
+
"license": "MIT",
|
371 |
+
"engines": {
|
372 |
+
"node": ">= 0.4"
|
373 |
+
},
|
374 |
+
"funding": {
|
375 |
+
"url": "https://github.com/sponsors/ljharb"
|
376 |
+
}
|
377 |
+
},
|
378 |
+
"node_modules/openai": {
|
379 |
+
"version": "4.61.0",
|
380 |
+
"resolved": "https://registry.npmmirror.com/openai/-/openai-4.61.0.tgz",
|
381 |
+
"integrity": "sha512-xkygRBRLIUumxzKGb1ug05pWmJROQsHkGuj/N6Jiw2dj0dI19JvbFpErSZKmJ/DA+0IvpcugZqCAyk8iLpyM6Q==",
|
382 |
+
"license": "Apache-2.0",
|
383 |
+
"dependencies": {
|
384 |
+
"@types/node": "^18.11.18",
|
385 |
+
"@types/node-fetch": "^2.6.4",
|
386 |
+
"@types/qs": "^6.9.15",
|
387 |
+
"abort-controller": "^3.0.0",
|
388 |
+
"agentkeepalive": "^4.2.1",
|
389 |
+
"form-data-encoder": "1.7.2",
|
390 |
+
"formdata-node": "^4.3.2",
|
391 |
+
"node-fetch": "^2.6.7",
|
392 |
+
"qs": "^6.10.3"
|
393 |
+
},
|
394 |
+
"bin": {
|
395 |
+
"openai": "bin/cli"
|
396 |
+
},
|
397 |
+
"peerDependencies": {
|
398 |
+
"zod": "^3.23.8"
|
399 |
+
},
|
400 |
+
"peerDependenciesMeta": {
|
401 |
+
"zod": {
|
402 |
+
"optional": true
|
403 |
+
}
|
404 |
+
}
|
405 |
+
},
|
406 |
+
"node_modules/qs": {
|
407 |
+
"version": "6.13.0",
|
408 |
+
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
|
409 |
+
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
|
410 |
+
"license": "BSD-3-Clause",
|
411 |
+
"dependencies": {
|
412 |
+
"side-channel": "^1.0.6"
|
413 |
+
},
|
414 |
+
"engines": {
|
415 |
+
"node": ">=0.6"
|
416 |
+
},
|
417 |
+
"funding": {
|
418 |
+
"url": "https://github.com/sponsors/ljharb"
|
419 |
+
}
|
420 |
+
},
|
421 |
+
"node_modules/set-function-length": {
|
422 |
+
"version": "1.2.2",
|
423 |
+
"resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
|
424 |
+
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
425 |
+
"license": "MIT",
|
426 |
+
"dependencies": {
|
427 |
+
"define-data-property": "^1.1.4",
|
428 |
+
"es-errors": "^1.3.0",
|
429 |
+
"function-bind": "^1.1.2",
|
430 |
+
"get-intrinsic": "^1.2.4",
|
431 |
+
"gopd": "^1.0.1",
|
432 |
+
"has-property-descriptors": "^1.0.2"
|
433 |
+
},
|
434 |
+
"engines": {
|
435 |
+
"node": ">= 0.4"
|
436 |
+
}
|
437 |
+
},
|
438 |
+
"node_modules/side-channel": {
|
439 |
+
"version": "1.0.6",
|
440 |
+
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz",
|
441 |
+
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
442 |
+
"license": "MIT",
|
443 |
+
"dependencies": {
|
444 |
+
"call-bind": "^1.0.7",
|
445 |
+
"es-errors": "^1.3.0",
|
446 |
+
"get-intrinsic": "^1.2.4",
|
447 |
+
"object-inspect": "^1.13.1"
|
448 |
+
},
|
449 |
+
"engines": {
|
450 |
+
"node": ">= 0.4"
|
451 |
+
},
|
452 |
+
"funding": {
|
453 |
+
"url": "https://github.com/sponsors/ljharb"
|
454 |
+
}
|
455 |
+
},
|
456 |
+
"node_modules/tr46": {
|
457 |
+
"version": "0.0.3",
|
458 |
+
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
|
459 |
+
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
460 |
+
"license": "MIT"
|
461 |
+
},
|
462 |
+
"node_modules/undici-types": {
|
463 |
+
"version": "5.26.5",
|
464 |
+
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz",
|
465 |
+
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
466 |
+
"license": "MIT"
|
467 |
+
},
|
468 |
+
"node_modules/web-streams-polyfill": {
|
469 |
+
"version": "4.0.0-beta.3",
|
470 |
+
"resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
|
471 |
+
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
|
472 |
+
"license": "MIT",
|
473 |
+
"engines": {
|
474 |
+
"node": ">= 14"
|
475 |
+
}
|
476 |
+
},
|
477 |
+
"node_modules/webidl-conversions": {
|
478 |
+
"version": "3.0.1",
|
479 |
+
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
480 |
+
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
481 |
+
"license": "BSD-2-Clause"
|
482 |
+
},
|
483 |
+
"node_modules/whatwg-url": {
|
484 |
+
"version": "5.0.0",
|
485 |
+
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
486 |
+
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
487 |
+
"license": "MIT",
|
488 |
+
"dependencies": {
|
489 |
+
"tr46": "~0.0.3",
|
490 |
+
"webidl-conversions": "^3.0.0"
|
491 |
+
}
|
492 |
+
}
|
493 |
+
}
|
494 |
+
}
|
package.json
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "free-for-dev-cn",
|
3 |
+
"version": "1.0.0",
|
4 |
+
"main": "translate.js",
|
5 |
+
"type": "module",
|
6 |
+
"scripts": {
|
7 |
+
"test": "node translate.js free-for-dev/README.md README.md"
|
8 |
+
},
|
9 |
+
"keywords": [],
|
10 |
+
"author": "",
|
11 |
+
"license": "ISC",
|
12 |
+
"description": "",
|
13 |
+
"dependencies": {
|
14 |
+
"dotenv": "^16.4.5",
|
15 |
+
"openai": "^4.61.0"
|
16 |
+
}
|
17 |
+
}
|
translate.js
ADDED
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { readFileSync, writeFileSync } from 'fs';
|
2 |
+
import { OpenAI } from 'openai';
|
3 |
+
import dotenv from 'dotenv';
|
4 |
+
|
5 |
+
dotenv.config();
|
6 |
+
|
7 |
+
function delay(ms) {
|
8 |
+
return new Promise(resolve => setTimeout(resolve, ms));
|
9 |
+
}
|
10 |
+
|
11 |
+
|
12 |
+
const openai = new OpenAI({
|
13 |
+
baseURL: process.env.OPENAI_BASE_URL,
|
14 |
+
apiKey: process.env.OPENAI_API_KEY,
|
15 |
+
});
|
16 |
+
|
17 |
+
|
18 |
+
|
19 |
+
const maxSectionLength = 8000;
|
20 |
+
|
21 |
+
function convertToId(header) {
|
22 |
+
return header.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
23 |
+
}
|
24 |
+
function splitContent(content) {
|
25 |
+
// 首先,统一换行符为 \n
|
26 |
+
content = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
27 |
+
|
28 |
+
const sections = content.split(/^(#{1,2}\s.+(?:\n+|$))/m);
|
29 |
+
let result = [];
|
30 |
+
let currentSection = null;
|
31 |
+
|
32 |
+
for (let i = 1; i < sections.length; i += 2) {
|
33 |
+
const headerWithNewlines = sections[i];
|
34 |
+
const [header, ...newlines] = headerWithNewlines.split('\n');
|
35 |
+
const text = sections[i + 1] || '';
|
36 |
+
|
37 |
+
currentSection = {
|
38 |
+
id: convertToId(header.replace(/^#+\s/, '')),
|
39 |
+
header: header,
|
40 |
+
text: text,
|
41 |
+
sections: [],
|
42 |
+
leadingSpaces: [],
|
43 |
+
translations: []
|
44 |
+
};
|
45 |
+
|
46 |
+
const lines = text.split('\n');
|
47 |
+
let currentSubSection = '';
|
48 |
+
let currentLeadingSpace = '';
|
49 |
+
|
50 |
+
for (let line of lines) {
|
51 |
+
const lineLeadingSpace = line.match(/^(\s*)/)[1];
|
52 |
+
|
53 |
+
if (currentSubSection.length + line.length > maxSectionLength) {
|
54 |
+
currentSection.sections.push(currentSubSection);
|
55 |
+
currentSection.leadingSpaces.push(currentLeadingSpace);
|
56 |
+
currentSubSection = '';
|
57 |
+
currentLeadingSpace = '';
|
58 |
+
continue;
|
59 |
+
}
|
60 |
+
|
61 |
+
if (currentSubSection === '') {
|
62 |
+
currentLeadingSpace = lineLeadingSpace;
|
63 |
+
}
|
64 |
+
|
65 |
+
currentSubSection += line + '\n';
|
66 |
+
}
|
67 |
+
|
68 |
+
if (currentSubSection.trim().length > 0) {
|
69 |
+
currentSection.sections.push(currentSubSection);
|
70 |
+
currentSection.leadingSpaces.push(currentLeadingSpace);
|
71 |
+
}
|
72 |
+
|
73 |
+
result.push(currentSection);
|
74 |
+
}
|
75 |
+
|
76 |
+
return result;
|
77 |
+
}
|
78 |
+
|
79 |
+
async function translateTableOfContents(sections, openai) {
|
80 |
+
const tocSection = sections.find(section => section.id === 'table-of-contents');
|
81 |
+
if (!tocSection) {
|
82 |
+
console.log("Table of Contents not found");
|
83 |
+
return {};
|
84 |
+
}
|
85 |
+
|
86 |
+
const linkRegex = /^\s*\*\s\[(.+)\]\(#(.+)\)\s*$/;
|
87 |
+
const idTextMap = {};
|
88 |
+
|
89 |
+
const translatedSections = await Promise.all(tocSection.sections.map(async (section, index) => {
|
90 |
+
const response = await openai.chat.completions.create({
|
91 |
+
model: process.env.OPENAI_MODEL_ID,
|
92 |
+
messages: [
|
93 |
+
{
|
94 |
+
role: "system",
|
95 |
+
content: `请翻译以下目录项,保持原有的格式:
|
96 |
+
1. 保持星号和缩进不变
|
97 |
+
2. 只翻译方括号[]内的文本
|
98 |
+
3. 保持圆括号()内的链接不变`
|
99 |
+
},
|
100 |
+
{ role: "user", content: section }
|
101 |
+
],
|
102 |
+
});
|
103 |
+
|
104 |
+
const translatedContent = response.choices[0].message.content;
|
105 |
+
console.log(`Translated TOC section ${index + 1} of ${tocSection.sections.length}`);
|
106 |
+
|
107 |
+
const translatedLines = translatedContent.split('\n').map(line => {
|
108 |
+
const match = line.match(linkRegex);
|
109 |
+
if (match) {
|
110 |
+
let [, translatedText, id] = match;
|
111 |
+
translatedText = translatedText.replace(/\s+/g, '');
|
112 |
+
idTextMap[id] = translatedText;
|
113 |
+
return `${tocSection.leadingSpaces[index]}* [${translatedText}](#${translatedText})`;
|
114 |
+
}
|
115 |
+
return line;
|
116 |
+
});
|
117 |
+
|
118 |
+
return translatedLines.join('\n');
|
119 |
+
}));
|
120 |
+
|
121 |
+
tocSection.translations = translatedSections;
|
122 |
+
|
123 |
+
// 替换链接
|
124 |
+
Object.entries(idTextMap).forEach(([id, text]) => {
|
125 |
+
const encodedText = encodeURIComponent(text.toLowerCase().replace(/\s+/g, '-'));
|
126 |
+
tocSection.translations = tocSection.translations.map(translation =>
|
127 |
+
translation.replace(new RegExp(`\\(#${id}\\)`, 'g'), `(#${encodedText})`));
|
128 |
+
});
|
129 |
+
|
130 |
+
return idTextMap;
|
131 |
+
}
|
132 |
+
async function translateToChineseAndSave(inputFile, outputFile) {
|
133 |
+
try {
|
134 |
+
const content = readFileSync(inputFile, 'utf8');
|
135 |
+
const sections = splitContent(content);
|
136 |
+
console.log(`Split into ${sections.length} sections`);
|
137 |
+
|
138 |
+
const idTextMap = await translateTableOfContents(sections, openai);
|
139 |
+
|
140 |
+
// 提取所有需要翻译的部分
|
141 |
+
const allSectionsToTranslate = sections.filter(section => section.id !== 'table-of-contents')
|
142 |
+
.flatMap(section =>
|
143 |
+
section.sections.map((text, index) => ({ sectionId: section.id, index, text }))
|
144 |
+
);
|
145 |
+
|
146 |
+
console.log(`Preparing to translate ${allSectionsToTranslate.length} subsections`);
|
147 |
+
|
148 |
+
// 批��翻译
|
149 |
+
const translatedSections = await Promise.all(allSectionsToTranslate.map(async ({ sectionId, index, text }) => {
|
150 |
+
const response = await openai.chat.completions.create({
|
151 |
+
model: process.env.OPENAI_MODEL_ID,
|
152 |
+
messages: [
|
153 |
+
{
|
154 |
+
role: "system", content: `
|
155 |
+
请将Markdown文本翻译成中文,同时遵守以下规则:
|
156 |
+
1. 严格保持原文的Markdown格式不变,包括但不限于标题、列表、代码块、引用等。
|
157 |
+
2. 专有名词、缩写等可以保留英文,但在首次出现时可在括号内提供中文解释。
|
158 |
+
3. 代码块、命令行指令等技术内容保持原样不翻译。
|
159 |
+
4. 注意调整语序,使翻译后的文本符合中文的表达习惯,同时保持原意。
|
160 |
+
5. 保持原文的链接格式不变,只翻译链接文本。
|
161 |
+
`
|
162 |
+
},
|
163 |
+
{ role: "user", content: text.trim() }
|
164 |
+
],
|
165 |
+
});
|
166 |
+
console.log(`Translated subsection ${index + 1} of section ${sectionId}`);
|
167 |
+
return { sectionId, index, content: response.choices[0].message.content };
|
168 |
+
}));
|
169 |
+
|
170 |
+
// 将翻译结果存储到相应的 section 对象中
|
171 |
+
sections.forEach(section => {
|
172 |
+
if (section.id !== 'table-of-contents') {
|
173 |
+
section.translations = translatedSections
|
174 |
+
.filter(ts => ts.sectionId === section.id)
|
175 |
+
.sort((a, b) => a.index - b.index)
|
176 |
+
.map(ts => section.leadingSpaces[ts.index] + ts.content);
|
177 |
+
}
|
178 |
+
});
|
179 |
+
|
180 |
+
// 替换 header 并组合成完整的翻译结果
|
181 |
+
const translatedContent = sections.map(section => {
|
182 |
+
const headerLevel = section.header.match(/^(#+)/)[1];
|
183 |
+
const newHeader = idTextMap[section.id] ? `${headerLevel} ${idTextMap[section.id]}` : section.header;
|
184 |
+
return [newHeader, ...section.translations].join('\n\n');
|
185 |
+
}).join('\n\n');
|
186 |
+
|
187 |
+
// // 更新链接
|
188 |
+
// const updatedContent = translatedContent.replace(/\[([^\]]+)\]\(#([^)]+)\)/g, (match, linkText, linkId) => {
|
189 |
+
// const translatedLinkText = idTextMap[linkId] || linkText;
|
190 |
+
// const encodedLinkText = encodeURIComponent(translatedLinkText.toLowerCase().replace(/\s+/g, '-'));
|
191 |
+
// return `[${translatedLinkText}](#${encodedLinkText})`;
|
192 |
+
// });
|
193 |
+
|
194 |
+
writeFileSync(outputFile, translatedContent.trim());
|
195 |
+
console.log(`Translation completed and saved to ${outputFile}`);
|
196 |
+
} catch (error) {
|
197 |
+
console.error('Error:', error);
|
198 |
+
}
|
199 |
+
}
|
200 |
+
// 获取命令行参数
|
201 |
+
const inputFile = process.argv[2];
|
202 |
+
const outputFile = process.argv[3] || 'README.md';
|
203 |
+
|
204 |
+
translateToChineseAndSave(inputFile, outputFile);
|