chore: enforce prettier, ignore submodules and vendor files (#3018)

* chore: enforce prettier, ignore submodules and vendor files

* chore: add format check in CI

---------

Co-authored-by: Huang Xin <chrox.huang@gmail.com>
This commit is contained in:
xijibomi-coffee 2026-01-21 14:53:02 +01:00 committed by GitHub
parent ea811c90c6
commit d1d0d2d59c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 114 additions and 83 deletions

View file

@ -8,6 +8,6 @@ updates:
groups:
github-actions:
patterns:
- "*" # Group all Actions updates into a single larger pull request
- '*' # Group all Actions updates into a single larger pull request
schedule:
interval: weekly

View file

@ -68,6 +68,10 @@ jobs:
run: |
pnpm install && pnpm setup-vendors
- name: run format check
run: |
pnpm format:check || (pnpm format && git diff && exit 1)
- name: run tests
working-directory: apps/readest-app
run: |

View file

@ -1 +1,34 @@
packages/foliate-js/
# Dependencies
node_modules
pnpm-lock.yaml
# Build Artifacts (Web & Rust)
.next
.open-next
.build
.tauri
out
build
dist
target
fastlane
.wrangler
# Autogenerated Tauri files
gen
**/autogenerated
**/schemas
# Submodules (External Repos)
packages
# Vendored Assets (Generated/External Code)
apps/readest-app/public/*.js
apps/readest-app/public/vendor
# Environment & Editor
.env
.env.*
.vscode
.idea
*.log

17
.vscode/settings.json vendored
View file

@ -13,4 +13,19 @@
"javascript.validate.enable": false,
"javascript.format.enable": false,
"typescript.format.enable": false,
}
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"prettier.requireConfig": true,
"prettier.documentSelectors": ["**/*.{js,jsx,ts,tsx,css,json,md,html,yml}"]
}

View file

@ -12,28 +12,31 @@ This crate provides Windows Explorer thumbnail support for eBook files when Read
## Supported Formats
| Format | Extension | Cover Source |
|--------|-----------|--------------|
| EPUB | `.epub` | OPF manifest cover reference |
| MOBI/AZW | `.mobi`, `.azw`, `.prc` | EXTH cover offset |
| AZW3/KF8 | `.azw3`, `.kf8` | KF8 format cover |
| FB2 | `.fb2` | `<binary>` coverpage element |
| Comic Book | `.cbz`, `.cbr` | First image in archive |
| Plain Text | `.txt` | Generated placeholder |
| Format | Extension | Cover Source |
| ---------- | ----------------------- | ---------------------------- |
| EPUB | `.epub` | OPF manifest cover reference |
| MOBI/AZW | `.mobi`, `.azw`, `.prc` | EXTH cover offset |
| AZW3/KF8 | `.azw3`, `.kf8` | KF8 format cover |
| FB2 | `.fb2` | `<binary>` coverpage element |
| Comic Book | `.cbz`, `.cbr` | First image in archive |
| Plain Text | `.txt` | Generated placeholder |
## Building
### Library Only
```bash
cargo build --release
```
### COM DLL (for Windows Explorer integration)
```bash
cargo build --release --features com
```
### CLI Tool
```bash
cargo build --release --features cli
```

View file

@ -15,6 +15,8 @@
"test": "dotenv -e .env -e .env.test.local vitest",
"tauri": "tauri",
"clippy": "cargo clippy -p Readest --no-deps -- -D warnings",
"format": "pnpm -w format",
"format:check": "pnpm -w format:check",
"prepare-public-vendor": "mkdirp ./public/vendor/pdfjs ./public/vendor/simplecc",
"copy-pdfjs-js": "cpx \"../../packages/foliate-js/node_modules/pdfjs-dist/legacy/build/{pdf.worker.min.mjs,pdf.min.mjs,pdf.d.mts}\" ./public/vendor/pdfjs",
"copy-pdfjs-wasm": "cpx \"../../packages/foliate-js/node_modules/pdfjs-dist/wasm/{openjpeg.wasm,qcms_bg.wasm}\" ./public/vendor/pdfjs",

View file

@ -103,14 +103,7 @@ export function useBooknotesNav(bookKey: string, toc: TOCItem[]) {
getView(bookKey)?.goTo(sorted[0]!.cfi);
}
},
[
allBooknotes,
bookKey,
setActiveBooknoteType,
setBooknoteResults,
setBooknoteIndex,
getView,
],
[allBooknotes, bookKey, setActiveBooknoteType, setBooknoteResults, setBooknoteIndex, getView],
);
const handleShowResults = useCallback(() => {

View file

@ -24,27 +24,26 @@ async function translateSingleTextForService(
lang: lang,
service: service,
text: text,
})
}),
};
const response = await fetchImpl(url, request);
if (!response.ok) {
const response_json = JSON.stringify(await response.json());
throw new Error(`${service} failed with status ${response.status}\n${text.length}\n${JSON.stringify(request)}\n${response_json}`);
throw new Error(
`${service} failed with status ${response.status}\n${text.length}\n${JSON.stringify(request)}\n${response_json}`,
);
}
const data = await response.json();
if (
data &&
Array.isArray(data.translations)
) {
if (data && Array.isArray(data.translations)) {
return data.translations;
} else {
// fallback: return original texts if translation failed
return [text];
}
};
}
export const yandexProvider: TranslationProvider = {
name: 'yandex',
@ -60,18 +59,21 @@ export const yandexProvider: TranslationProvider = {
- yandextranslate
- yandexbrowser
*/
const service = "yandexgpt";
const service = 'yandexgpt';
// Yandex does not accept "auto" language
const source_lang = sourceLang == "AUTO" ? "en" : normalizeToShortLang(sourceLang).toLowerCase();
const source_lang =
sourceLang == 'AUTO' ? 'en' : normalizeToShortLang(sourceLang).toLowerCase();
const target_lang = normalizeToShortLang(targetLang).toLowerCase();
const lang = `${source_lang}-${target_lang}`;
const responses = await Promise.all(texts.map(async text => {
return await translateSingleTextForService(text, lang, service)
}));
const responses = await Promise.all(
texts.map(async (text) => {
return await translateSingleTextForService(text, lang, service);
}),
);
const translatedTexts = responses.flat();
return translatedTexts;
}
},
};

View file

@ -322,7 +322,11 @@ export class WebAppService extends BaseAppService {
throw new Error('selectFiles is not supported in browser');
}
async saveFile(filename: string, content: string | ArrayBuffer, mimeType?: string): Promise<boolean> {
async saveFile(
filename: string,
content: string | ArrayBuffer,
mimeType?: string,
): Promise<boolean> {
try {
const blob = new Blob([content], { type: mimeType || 'application/octet-stream' });
const url = URL.createObjectURL(blob);

View file

@ -1 +0,0 @@

View file

@ -15,18 +15,18 @@ export const r2Storage = {
return `https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`;
},
getDownloadSignedUrl: async (
bucketName: string,
fileKey: string,
expiresIn: number,
) => {
getDownloadSignedUrl: async (bucketName: string, fileKey: string, expiresIn: number) => {
return (
await r2Storage.getR2Client().sign(
new Request(`${r2Storage.getR2Url()}/${bucketName}/${fileKey}?X-Amz-Expires=${expiresIn}`),
{
aws: { signQuery: true },
},
)
await r2Storage
.getR2Client()
.sign(
new Request(
`${r2Storage.getR2Url()}/${bucketName}/${fileKey}?X-Amz-Expires=${expiresIn}`,
),
{
aws: { signQuery: true },
},
)
).url.toString();
},

View file

@ -17,7 +17,6 @@ export const s3Client = new S3Client({
},
});
export const s3Storage = {
getClient: () => {
return new S3Client({
@ -31,12 +30,7 @@ export const s3Storage = {
});
},
getDownloadSignedUrl: async (
bucketName: string,
fileKey: string,
expiresIn: number,
) => {
getDownloadSignedUrl: async (bucketName: string, fileKey: string, expiresIn: number) => {
const getCommand = new GetObjectCommand({
Bucket: bucketName,
Key: fileKey,
@ -53,7 +47,6 @@ export const s3Storage = {
contentLength: number,
expiresIn: number,
) => {
const signableHeaders = new Set<string>();
signableHeaders.add('content-length');
const putCommand = new PutObjectCommand({

View file

@ -2,12 +2,7 @@
"extends": "@sindresorhus/tsconfig",
"compilerOptions": {
"target": "ES2022",
"lib": [
"dom",
"dom.iterable",
"webworker",
"esnext"
],
"lib": ["dom", "dom.iterable", "webworker", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@ -25,25 +20,11 @@
}
],
"paths": {
"@/*": [
"./src/*"
],
"@pdfjs/*": [
"./public/vendor/pdfjs/*"
],
"@simplecc/*": [
"./public/vendor/simplecc/*"
]
"@/*": ["./src/*"],
"@pdfjs/*": ["./public/vendor/pdfjs/*"],
"@simplecc/*": ["./public/vendor/simplecc/*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"raw-loader.d.ts",
".next/types/**/*.ts"
],
"exclude": [
"node_modules",
]
}
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "raw-loader.d.ts", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

View file

@ -5,7 +5,9 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"tauri": "pnpm --filter @readest/readest-app tauri",
"dev-web": "pnpm --filter @readest/readest-app dev-web"
"dev-web": "pnpm --filter @readest/readest-app dev-web",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,css,json,md,html,yml}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,css,json,md,html,yml}\""
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",

View file

@ -8,12 +8,12 @@
"strict": true,
"moduleResolution": "bundler",
"esModuleInterop": true,
"skipLibCheck": true,
"skipLibCheck": true
},
"files": [],
"references": [
{
"path": "./apps/readest-app"
},
}
]
}
}