Skip to content

Commit d78bd9f

Browse files
committed
fest: first blood, should just work
1 parent 2cbf4f0 commit d78bd9f

File tree

13 files changed

+376
-0
lines changed

13 files changed

+376
-0
lines changed

.editorconfig

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
root=true
2+
3+
[*]
4+
indent_style=space
5+
indent_size=2
6+
tab_width=2
7+
end_of_line=lf
8+
charset=utf-8
9+
trim_trailing_whitespace=true
10+
insert_final_newline=true

.github/workflows/ci.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: CI
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
cancel-in-progress: true
10+
11+
jobs:
12+
ci:
13+
name: ${{ matrix.os }}
14+
strategy:
15+
matrix:
16+
os:
17+
- macOS-latest
18+
- ubuntu-latest
19+
- windows-latest
20+
runs-on: ${{ matrix.os }}
21+
steps:
22+
- name: Checkout Repo
23+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
24+
25+
- name: Setup Deno
26+
uses: denoland/setup-deno@v2
27+
with:
28+
deno-version: v2.x
29+
30+
- name: Lint
31+
run: |
32+
deno fmt --check
33+
deno lint

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!.vscode/settings.json

.renovaterc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"extends": [
3+
"github>1stG/configs"
4+
]
5+
}

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"editor.defaultFormatter": "denoland.vscode-deno"
3+
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# deeplx
2+
23
Running [deeplx](https://github.com/un-ts/deeplx) on Deno Deploy

deno.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"noUnusedLocals": true,
4+
"noUnusedParameters": true
5+
},
6+
"tasks": {
7+
"build": "deno run --allow-env --allow-read --allow-write --allow-net scripts/build.ts",
8+
"dev": "deno run --allow-ffi --allow-read --allow-net --watch main.ts",
9+
"start": "deno run --allow-ffi --allow-read --allow-net main.ts"
10+
},
11+
"fmt": {
12+
"semiColons": false,
13+
"singleQuote": true,
14+
"exclude": ["public/index.html"]
15+
}
16+
}

deno.lock

+90
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

main.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { translate } from './mod.ts'
2+
3+
Deno.serve(translate)

mod.ts

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import {
2+
abbreviateLanguage,
3+
HTTP_STATUS_BAD_REQUEST,
4+
HTTP_STATUS_INTERNAL_ERROR,
5+
HTTP_STATUS_NOT_ALLOWED,
6+
HTTP_STATUS_NOT_FOUND,
7+
HTTP_STATUS_OK,
8+
type SourceLanguage,
9+
type TargetLanguage,
10+
translate as translate_,
11+
} from 'npm:@deeplx/core'
12+
13+
export interface RequestBody {
14+
text: string
15+
source_lang?: SourceLanguage
16+
target_lang: TargetLanguage
17+
}
18+
19+
async function extractBodyText(body: ReadableStream) {
20+
const reader = body.getReader()
21+
const decoder = new TextDecoder()
22+
23+
let text = ''
24+
25+
while (true) {
26+
const { done, value } = await reader.read()
27+
if (done) {
28+
return text
29+
}
30+
text += decoder.decode(value)
31+
}
32+
}
33+
34+
export const translate = async (
35+
req: Request,
36+
): Promise<Response> => {
37+
let url = new URL(req.url).pathname
38+
39+
if (!url || url === '/') {
40+
url = '/index.html'
41+
}
42+
43+
if (/\.[a-z]+[a-z\d]*$/.test(url)) {
44+
if (req.method !== 'GET') {
45+
return Response.json({
46+
code: HTTP_STATUS_NOT_ALLOWED,
47+
message: 'Not Allowed',
48+
}, { status: HTTP_STATUS_NOT_ALLOWED })
49+
}
50+
return new Response(await Deno.readFile(`./public${url}`))
51+
}
52+
53+
if (url !== '/translate') {
54+
return Response.json({
55+
code: HTTP_STATUS_NOT_FOUND,
56+
message: 'Not Found',
57+
}, {
58+
status: HTTP_STATUS_NOT_FOUND,
59+
})
60+
}
61+
62+
const body = req.body
63+
64+
if (!body || req.method !== 'POST') {
65+
return new Response(`DeepL Translate Api
66+
67+
POST {"text": "have a try", "source_lang": "auto", "target_lang": "ZH"} to /translate
68+
69+
https://github.com/devno-js/deeplx
70+
71+
powered by https://github.com/un-ts/deeplx`)
72+
}
73+
74+
const bodyText = await extractBodyText(body)
75+
76+
const { text, source_lang: sourceLang, target_lang: targetLang } = JSON.parse(
77+
bodyText,
78+
) as RequestBody
79+
80+
if (!text) {
81+
return Response.json({
82+
code: HTTP_STATUS_BAD_REQUEST,
83+
data: 'Text is required',
84+
}, {
85+
status: HTTP_STATUS_BAD_REQUEST,
86+
})
87+
}
88+
89+
if (!abbreviateLanguage(targetLang)) {
90+
return Response.json({
91+
code: HTTP_STATUS_BAD_REQUEST,
92+
data: 'Invalid target language',
93+
}, {
94+
status: HTTP_STATUS_BAD_REQUEST,
95+
})
96+
}
97+
98+
try {
99+
const translation = await translate_(text, targetLang, sourceLang)
100+
return Response.json({
101+
code: HTTP_STATUS_OK,
102+
data: translation,
103+
})
104+
} catch (err) {
105+
return Response.json({
106+
code: HTTP_STATUS_INTERNAL_ERROR,
107+
data: err instanceof Error ? err.message : String(err),
108+
}, {
109+
status: HTTP_STATUS_INTERNAL_ERROR,
110+
})
111+
}
112+
}

public/favicon.ico

98.8 KB
Binary file not shown.

public/index.html

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>App Center</title>
7+
<link
8+
rel="stylesheet"
9+
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css"
10+
/>
11+
<style>
12+
@media (prefers-color-scheme: dark) {
13+
:root {
14+
background-color: #0d1117;
15+
}
16+
}
17+
18+
body {
19+
margin: 0;
20+
}
21+
22+
.markdown-body {
23+
box-sizing: border-box;
24+
min-width: 200px;
25+
max-width: 980px;
26+
margin: 0 auto;
27+
padding: 45px;
28+
}
29+
30+
@media (max-width: 767px) {
31+
.markdown-body {
32+
padding: 15px;
33+
}
34+
}
35+
</style>
36+
</head>
37+
<body>
38+
<article class="markdown-body"><div class="markdown-heading"><h1 class="heading-element">deeplx</h1><a id="user-content-deeplx" class="anchor" aria-label="Permalink: deeplx" href="#deeplx"><span aria-hidden="true" class="octicon octicon-link"></span></a></div>
39+
<p>Running <a href="https://github.com/un-ts/deeplx">deeplx</a> on Deno Deploy</p>
40+
</article>
41+
</body>
42+
</html>

scripts/build.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @link https://github.com/sindresorhus/github-markdown-css
3+
*/
4+
5+
const text = await Deno.readTextFile('README.md')
6+
7+
const content = await fetch('https://api.github.com/markdown', {
8+
method: 'POST',
9+
body: JSON.stringify({ text }),
10+
headers: {
11+
Accept: 'application/vnd.github.v3+json',
12+
Authorization: `Bearer ${Deno.env.get('GITHUB_TOKEN')}`,
13+
},
14+
}).then((res) => res.text())
15+
16+
await Deno.writeTextFile(
17+
'public/index.html',
18+
/* HTML */ `
19+
<!DOCTYPE html>
20+
<html lang="en">
21+
<head>
22+
<meta charset="UTF-8" />
23+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
24+
<title>App Center</title>
25+
<link
26+
rel="stylesheet"
27+
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css"
28+
/>
29+
<style>
30+
@media (prefers-color-scheme: dark) {
31+
:root {
32+
background-color: #0d1117;
33+
}
34+
}
35+
36+
body {
37+
margin: 0;
38+
}
39+
40+
.markdown-body {
41+
box-sizing: border-box;
42+
min-width: 200px;
43+
max-width: 980px;
44+
margin: 0 auto;
45+
padding: 45px;
46+
}
47+
48+
@media (max-width: 767px) {
49+
.markdown-body {
50+
padding: 15px;
51+
}
52+
}
53+
</style>
54+
</head>
55+
<body>
56+
<article class="markdown-body">${content}</article>
57+
</body>
58+
</html>
59+
`.trim(),
60+
)

0 commit comments

Comments
 (0)