Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 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'
Comment thread
weekendfish marked this conversation as resolved.
Outdated
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
Comment thread
weekendfish marked this conversation as resolved.
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
Empty file added ENDFILE
Empty file.
Empty file added EOF
Empty file.
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
74 changes: 74 additions & 0 deletions lib/clientSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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, any> = {}

async function loadIndex(domain: string): Promise<any | null> {
if (cache[domain]) return cache[domain]
const file = REPO_INDEXES[domain]
if (!file) return null
try {
const res = await fetch(file)
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadIndex does not check res.ok before inflating; a 404/500 response body will be passed to pako.inflate and then JSON.parse, producing confusing errors. Add an if (!res.ok) branch (and ideally include status/url in the error) before reading/decompressing.

Suggested change
const res = await fetch(file)
const res = await fetch(file)
if (!res.ok) {
console.error(
'Failed to fetch search index',
{ domain, file, status: res.status, statusText: res.statusText }
)
return null
}

Copilot uses AI. Check for mistakes.
const compressed = await res.arrayBuffer()
const decompressed = pako.inflate(new Uint8Array(compressed), { to: 'string' })
const data = JSON.parse(decompressed)
cache[domain] = data
return data
} catch (e) {
console.error('Failed to load', domain, e)
return null
}
Comment thread
weekendfish marked this conversation as resolved.
Outdated
}

export async function clientSearch(
query: string,
domain?: string,
tag?: string,
year?: string,
region?: string
): Promise<SearchResult[]> {
const domains = domain ? domain.split(',') : Object.keys(REPO_INDEXES)
Comment thread
weekendfish marked this conversation as resolved.
Outdated
const lowerQuery = query.toLowerCase()
const found: SearchResult[] = []
for (const d of domains) {
if (found.length >= 100) break
const index = await loadIndex(d)
Comment thread
weekendfish marked this conversation as resolved.
Outdated
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
Comment thread
weekendfish marked this conversation as resolved.
Outdated
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.
2 changes: 1 addition & 1 deletion scripts/rss.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path'
import { slug } from 'github-slugger'
import { escape } from 'pliny/utils/htmlEscaper.js'
import siteMetadata from '../data/siteMetadata.js'
import tagData from '../app/tag-data.json' assert { type: 'json' }
import tagData from '../app/tag-data.json' with { type: "json" }
Comment thread
weekendfish marked this conversation as resolved.
Outdated
import { allBlogs } from '../.contentlayer/generated/index.mjs'
import { sortPosts } from 'pliny/utils/contentlayer.js'

Expand Down
Binary file added search-index.json.gz
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 = "${CLOUDFLARE_ACCOUNT_ID}"
Comment thread
weekendfish marked this conversation as resolved.
Outdated

[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/sharp-libvips-linuxmusl-x64@1.0.4":
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/sharp-linux-x64@0.33.5":
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/sharp-linuxmusl-x64@0.33.5":
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/swc-linux-x64-musl@15.0.2":
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/fs.scandir@2.1.5":
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/resolver-binding-linux-x64-musl@1.11.1":
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
Loading