Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions .github/workflows/cf-pages-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ name: Build and Deploy to CF Pages
on:
workflow_dispatch:
push:
branches: [main, master]
branches: [main]
pull_request:
branches: [main]

jobs:
build:
Expand All @@ -30,21 +32,42 @@ jobs:
name: build-output
path: out/

deploy:
deploy-preview:
needs: build
runs-on: ubuntu-latest
if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) || github.event_name == 'workflow_dispatch'
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: build-output
path: out/

- name: Deploy to Cloudflare Pages
- name: Deploy to Cloudflare Pages (Preview)
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: transchinese-test
directory: out
gitHubToken: ${{ secrets.GITHUB_TOKEN }}

deploy-production:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: build-output
path: out/

- name: Deploy to Cloudflare Pages (Production)
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: transchinese-org
directory: out
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
7 changes: 2 additions & 5 deletions app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useRouter, useSearchParams } from 'next/navigation'
import SearchForm from '@/components/search/SearchForm'
import SearchResults from '@/components/search/SearchResults'
import { SearchResult } from '@/components/search/SearchResult'
import { clientSearch } from '@/lib/clientSearch'

// Loading component
const SearchLoading = () => (
Expand Down Expand Up @@ -82,11 +83,7 @@ function SearchContent() {

router.push(`?${params.toString()}`, { scroll: false })

const response = await fetch(`/api/search?${params.toString()}`)
if (!response.ok) {
throw new Error('Search failed')
}
const data: SearchResult[] = await response.json()
const data = await clientSearch(query, domain || undefined, tag || undefined, year || undefined, region || undefined)
setResults(data)
} catch (err) {
setError('Search failed. Please try again.')
Expand Down
90 changes: 90 additions & 0 deletions lib/clientSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import pako from 'pako'
import { SearchResult } from '@/components/search/SearchResult'

const REPO_INDEXES: Record<string, string> = {
"digital.transchinese.org": "/search-index/repo-digital-transchinese-org.json.gz",
"novel.transchinese.org": "/search-index/repo-novel-transchinese-org.json.gz",
"comic.transchinese.org": "/search-index/repo-comic-transchinese-org.json.gz",
"archive.cdtsf.com": "/search-index/repo-archive-cdtsf-com.json.gz",
"news.transchinese.org": "/search-index/repo-news-transchinese-org.json.gz",
"enovel.cdtsf.com": "/search-index/repo-enovel-cdtsf-com.json.gz",
"fnovel.cdtsf.com": "/search-index/repo-fnovel-cdtsf-com.json.gz",
"snovel.cdtsf.com": "/search-index/repo-snovel-cdtsf-com.json.gz",
"unovel.transchinese.org": "/search-index/repo-unovel-transchinese-org.json.gz",
"xnovel.transchinese.org": "/search-index/repo-xnovel-transchinese-org.json.gz",
}

const cache: Record<string, Promise<any | null>> = {}

async function loadIndex(domain: string): Promise<any | null> {
if (domain in cache) {
return cache[domain]
}
const file = REPO_INDEXES[domain]
if (!file) return null
const promise: Promise<any | null> = (async () => {
try {
const res = await fetch(file)
const compressed = await res.arrayBuffer()
const decompressed = pako.inflate(new Uint8Array(compressed), { to: 'string' })
const data = JSON.parse(decompressed)
return data
} catch (e) {
console.error('Failed to load', domain, e)
return null
}
})()
cache[domain] = promise
return promise
}

export async function clientSearch(
query: string,
domain?: string,
tag?: string,
year?: string,
region?: string
): Promise<SearchResult[]> {
const domains = domain
? domain.split(',').map(d => d.trim()).filter(Boolean)
: Object.keys(REPO_INDEXES)
const lowerQuery = query.toLowerCase()
const found: SearchResult[] = []

// Load all requested domain indexes in parallel to reduce overall latency.
const indexResults = await Promise.all(
domains.map(async (d) => {
const index = await loadIndex(d)
return { domain: d, index }
})
)

for (const { domain: d, index } of indexResults) {
if (found.length >= 100) break
if (!index) continue
for (const [key, doc] of Object.entries(index)) {
if (found.length >= 100) break
const docAny = doc as any
const keyLower = key.toLowerCase()
const descLower = (docAny.description || '').toLowerCase()
if (lowerQuery && !keyLower.includes(lowerQuery) && !descLower.includes(lowerQuery)) continue
if (tag && (!docAny.tags || !docAny.tags.includes(tag))) continue
if (year && (!docAny.date || !docAny.date.includes(year))) continue
if (region && docAny.region !== region) continue
found.push({
url: 'https://' + d + '/' + key.replace(/\.[^/.]+$/, ''),
description: docAny.description || '',
tags: docAny.tags || [],
type: docAny.type || '',
author: docAny.author || '',
date: docAny.date || '',
region: docAny.region || '',
format: docAny.format || '',
size: docAny.size || 0,
link: 'https://' + d + '/' + key.replace(/\.[^/.]+$/, ''),
})
}
}
return found
}
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"next-contentlayer2": "0.5.3",
"next-themes": "^0.3.0",
"openai": "^4.72.0",
"pako": "^2.1.0",
"pliny": "^0.4.0",
"postcss": "^8.4.24",
"react": "rc",
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added public/search-index/repo-snovel-cdtsf-com.json.gz
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@/data/*": ["data/*"],
"@/layouts/*": ["layouts/*"],
"@/css/*": ["css/*"],
"@/lib/*": ["lib/*"],
"contentlayer/generated": ["./.contentlayer/generated"]
},
"plugins": [
Expand Down
6 changes: 6 additions & 0 deletions wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name = "transchinese-test"
compatibility_date = "2024-01-01"
account_id = "${CLOUDFLARE_ACCOUNT_ID}"

[site]
bucket = "./out"
6 changes: 6 additions & 0 deletions wrangler.toml.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name = "transchinese-org"
compatibility_date = "2024-01-01"
account_id = "bc82e687de1803b47adc1dfe23aca0a4"

[site]
bucket = "./out"
27 changes: 27 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1510,13 +1510,25 @@
resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz"
integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==

"@img/[email protected]":
version "1.0.4"
resolved "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz"
integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==

"@img/[email protected]":
version "0.33.5"
resolved "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz"
integrity sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==
optionalDependencies:
"@img/sharp-libvips-linux-x64" "1.0.4"

"@img/[email protected]":
version "0.33.5"
resolved "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz"
integrity sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==
optionalDependencies:
"@img/sharp-libvips-linuxmusl-x64" "1.0.4"

"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz"
Expand Down Expand Up @@ -2023,6 +2035,11 @@
resolved "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.2.tgz"
integrity sha512-i3U2TcHgo26sIhcwX/Rshz6avM6nizrZPvrDVDY1bXcLH1ndjbO8zuC7RoHp0NSK7wjJMPYzm7NYL1ksSKFreA==

"@next/[email protected]":
version "15.0.2"
resolved "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.2.tgz"
integrity sha512-AMfZfSVOIR8fa+TXlAooByEF4OB00wqnms1sJ1v+iu8ivwvtPvnkwdzzFMpsK5jA2S9oNeeQ04egIWVb4QWmtQ==

"@nodelib/[email protected]":
version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
Expand Down Expand Up @@ -2996,6 +3013,11 @@
resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz"
integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==

"@unrs/[email protected]":
version "1.11.1"
resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz"
integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==

abab@^2.0.6:
version "2.0.6"
resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz"
Expand Down Expand Up @@ -8002,6 +8024,11 @@ p-try@^2.0.0:
resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==

pako@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz"
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==

parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
Expand Down