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 "action@github.com"
|
| 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);
|