From e32a0c04c45a6e8b4f9443dfff516de492de8212 Mon Sep 17 00:00:00 2001
From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
Date: Thu, 9 Oct 2025 18:20:22 +0100
Subject: [PATCH] docs
---
devGuide/DeveloperGuide.md | 486 ++++++++++++++++----------------
devGuide/HowToAddNewLanguage.md | 176 ++++++++++--
2 files changed, 388 insertions(+), 274 deletions(-)
diff --git a/devGuide/DeveloperGuide.md b/devGuide/DeveloperGuide.md
index fb8911eaf..f197c9e9c 100644
--- a/devGuide/DeveloperGuide.md
+++ b/devGuide/DeveloperGuide.md
@@ -8,14 +8,15 @@ Stirling-PDF is a robust, locally hosted, web-based PDF manipulation tool. This
Stirling-PDF is built using:
-- Spring Boot + Thymeleaf
-- PDFBox
-- LibreOffice
-- qpdf
-- HTML, CSS, JavaScript
+- Spring Boot (Backend API)
+- React + TypeScript + Vite (Frontend V2)
+- Mantine UI + TailwindCSS (UI Framework)
+- PDFBox (PDF manipulation)
+- LibreOffice (Document conversion)
+- qpdf (PDF processing)
+- PDF.js (Client-side PDF rendering)
+- Embedded-PDF (PDF viewer component)
- Docker
-- PDF.js
-- PDF-LIB.js
- Lombok
## 3. Development Environment Setup
@@ -24,8 +25,9 @@ Stirling-PDF is built using:
- Docker
- Git
-- Java JDK 17 or later
+- Java JDK 17 or later (JDK 21 recommended)
- Gradle 7.0 or later (Included within the repo)
+- Node.js 18+ and npm (for frontend development)
### Setup Steps
@@ -38,8 +40,8 @@ Stirling-PDF is built using:
2. Install Docker and JDK17 if not already installed.
-3. Install a recommended Java IDE such as Eclipse, IntelliJ, or VSCode
- 1. Only VSCode
+3. Install a recommended IDE:
+ - **VSCode** (recommended for frontend)
1. Open VS Code.
2. When prompted, install the recommended extensions.
3. Alternatively, open the command palette (`Ctrl + Shift + P` or `Cmd + Shift + P` on macOS) and run:
@@ -49,13 +51,15 @@ Stirling-PDF is built using:
```
4. Install the required extensions from the list.
+ - **IntelliJ IDEA** (recommended for backend)
+ - **Eclipse** (alternative for backend)
4. Lombok Setup
Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, don't support Lombok out of the box. To set up Lombok in your development environment:
Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE.
5. Add environment variable
-For local testing, you should generally be testing the full 'Security' version of Stirling PDF. To do this, you must add the environment flag DISABLE_ADDITIONAL_FEATURES=false to your system and/or IDE build/run step.
+For local testing, you should generally be testing the full 'Security' version of Stirling PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true to your system and/or IDE build/run step.
## 4. Project Structure
@@ -68,10 +72,21 @@ Stirling-PDF/
├── customFiles/ # Custom static files and templates (generated at runtime used to replace existing files)
├── docs/ # Documentation files
├── exampleYmlFiles/ # Example YAML configuration files
+├── frontend/ # React frontend application (V2)
+│ ├── src/
+│ │ ├── components/ # React components
+│ │ ├── tools/ # PDF tool implementations
+│ │ ├── contexts/ # React contexts (FileContext, etc.)
+│ │ ├── hooks/ # Custom React hooks
+│ │ ├── services/ # API and processing services
+│ │ └── i18n.ts # Internationalization config
+│ ├── public/
+│ │ └── locales/ # Translation JSON files
+│ └── package.json
├── images/ # Image assets
├── pipeline/ # Pipeline-related files (generated at runtime)
├── scripts/ # Utility scripts
-├── src/ # Source code
+├── src/ # Backend source code
│ ├── main/
│ │ ├── java/
│ │ │ └── stirling/
@@ -79,16 +94,14 @@ Stirling-PDF/
│ │ │ └── SPDF/
│ │ │ ├── config/
│ │ │ ├── controller/
+│ │ │ │ ├── api/ # REST API endpoints
+│ │ │ │ └── web/ # Web controllers
│ │ │ ├── model/
│ │ │ ├── repository/
│ │ │ ├── service/
│ │ │ └── utils/
│ │ └── resources/
-│ │ ├── static/
-│ │ │ ├── css/
-│ │ │ ├── js/
-│ │ │ └── pdfjs/
-│ │ └── templates/
+│ │ └── static/ # Legacy static assets
│ └── test/
│ └── java/
│ └── stirling/
@@ -141,7 +154,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
- DISABLE_ADDITIONAL_FEATURES: "false"
+ DOCKER_ENABLE_SECURITY: "true"
SECURITY_ENABLELOGIN: "true"
PUID: 1002
PGID: 1002
@@ -170,7 +183,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
1. Set the security environment variable:
```bash
- export DISABLE_ADDITIONAL_FEATURES=true # or false for to enable login and security features for builds
+ export DOCKER_ENABLE_SECURITY=true # or false to disable login and security features for builds
```
2. Build the project with Gradle:
@@ -196,7 +209,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
For the fat version (with login and security features enabled):
```bash
- export DISABLE_ADDITIONAL_FEATURES=false
+ export DOCKER_ENABLE_SECURITY=true
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat .
```
@@ -224,38 +237,50 @@ Note: The `test.sh` script will run automatically when you raise a PR. However,
### Full Testing with Docker
-1. Build and run the Docker container per the above instructions:
+1. Build and run the Docker container per the above instructions
2. Access the application at `http://localhost:8080` and manually test all features developed.
-### Local Testing (Java and UI Components)
+### Local Testing (Frontend and Backend)
-For quick iterations and development of Java backend, JavaScript, and UI components, you can run and test Stirling-PDF locally without Docker. This approach allows you to work on and verify changes to:
+For quick iterations and development, you can run the frontend and backend separately:
-- Java backend logic
-- RESTful API endpoints
-- JavaScript functionality
-- User interface components and styling
-- Thymeleaf templates
+#### Backend Development
-To run Stirling-PDF locally:
-
-1. Compile and run the project using built-in IDE methods or by running:
+1. Run the backend:
```bash
./gradlew bootRun
```
-2. Access the application at `http://localhost:8080` in your web browser.
+2. The backend API will be available at `http://localhost:8080`
-3. Manually test the features you're working on through the UI.
+3. API documentation is available at `http://localhost:8080/swagger-ui/index.html`
-4. For API changes, use tools like Postman or curl to test endpoints directly.
+#### Frontend Development
+
+1. Install dependencies (first time only):
+
+ ```bash
+ cd frontend
+ npm install
+ ```
+
+2. Start the development server:
+
+ ```bash
+ npm run dev
+ ```
+
+3. The frontend will be available at `http://localhost:5173`
+
+4. Vite automatically proxies API calls from `/api/*` to the backend at `localhost:8080`
Important notes:
+- Frontend requires the backend to be running for full functionality
+- Hot module replacement (HMR) enables instant updates during development
- Local testing doesn't include features that depend on external tools like qpdf, LibreOffice, or Python scripts.
-- There are currently no automated unit tests. All testing is done manually through the UI or API calls. (You are welcome to add JUnits!)
- Always verify your changes in the full Docker environment before submitting pull requests, as some integrations and features will only work in the complete setup.
## 7. Contributing
@@ -307,112 +332,170 @@ docker run -p 8080:8080 -e APP_NAME="My PDF Tool" stirling-pdf:full
Refer to the main README for a full list of customization options.
-## 10. Language Translations
+## 10. Frontend Development (V2)
-For managing language translations that affect multiple files, Stirling-PDF provides a helper script:
+### Architecture Overview
-```bash
-/scripts/replace_translation_line.sh
+The V2 frontend is designed for **stateful document processing**:
+- Users upload PDFs once, then chain tools (split → merge → compress → view)
+- File state and processing results persist across tool switches
+- No file reloading between tools - performance critical for large PDFs (up to 100GB+)
+
+### Key Components
+
+#### FileContext - Central State Management
+**Location**: `frontend/src/contexts/FileContext.tsx`
+- **Active files**: Currently loaded PDFs and their variants
+- **Tool navigation**: Current mode (viewer/pageEditor/fileEditor/toolName)
+- **Memory management**: PDF document cleanup, blob URL lifecycle, Web Worker management
+- **IndexedDB persistence**: File storage with thumbnail caching
+- **Preview system**: Tools can preview results without context pollution
+
+**Critical**: All file operations go through FileContext. Don't bypass with direct file handling.
+
+#### Processing Services
+- **enhancedPDFProcessingService**: Background PDF parsing and manipulation
+- **thumbnailGenerationService**: Web Worker-based with main-thread fallback
+- **fileStorage**: IndexedDB with LRU cache management
+
+### Tool Development
+
+**Architecture**: Modular hook-based system with clear separation of concerns:
+
+- **useToolOperation** (`frontend/src/hooks/tools/shared/useToolOperation.ts`): Main orchestrator hook
+ - Coordinates all tool operations with consistent interface
+ - Integrates with FileContext for operation tracking
+ - Handles validation, error handling, and UI state management
+
+- **Supporting Hooks**:
+ - **useToolState**: UI state management (loading, progress, error, files)
+ - **useToolApiCalls**: HTTP requests and file processing
+ - **useToolResources**: Blob URLs, thumbnails, ZIP downloads
+
+- **Utilities**:
+ - **toolErrorHandler**: Standardized error extraction and i18n support
+ - **toolResponseProcessor**: API response handling (single/zip/custom)
+ - **toolOperationTracker**: FileContext integration utilities
+
+**Three Tool Patterns**:
+
+**Pattern 1: Single-File Tools** (Individual processing)
+- Backend processes one file per API call
+- Set `multiFileEndpoint: false`
+- Examples: Compress, Rotate
+
+```typescript
+return useToolOperation({
+ operationType: 'compress',
+ endpoint: '/api/v1/misc/compress-pdf',
+ buildFormData: (params, file: File) => { /* single file */ },
+ multiFileEndpoint: false,
+});
```
-This script helps you make consistent replacements across language files.
+**Pattern 2: Multi-File Tools** (Batch processing)
+- Backend accepts `MultipartFile[]` arrays in single API call
+- Set `multiFileEndpoint: true`
+- Examples: Split, Merge, Overlay
-When contributing translations:
-
-1. Use the helper script for multi-file changes.
-2. Ensure all language files are updated consistently.
-3. The PR checks will verify consistency in language file updates.
-
-Remember to test your changes thoroughly to ensure they don't break any existing functionality.
-
-## Code examples
-
-### Overview of Thymeleaf
-
-Thymeleaf is a server-side Java HTML template engine. It is used in Stirling-PDF to render dynamic web pages. Thymeleaf integrates heavily with Spring Boot.
-
-### Thymeleaf overview
-
-In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `app/core/src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content.
-
-Some examples of this are:
-
-```html
-
{t('myTool.description')}
+Split your PDF into multiple documents
- - -``` - -Remember, never hard-code text in your templates or Java code. Always use translation keys to ensure proper localization. +### General +- Write clear commit messages +- Update documentation for any API changes +- Test in Docker before submitting PRs +- Run `./gradlew spotlessApply` to format code +- Ensure all tests pass with `./test.sh` diff --git a/devGuide/HowToAddNewLanguage.md b/devGuide/HowToAddNewLanguage.md index 6a9ed17f2..282d8a614 100644 --- a/devGuide/HowToAddNewLanguage.md +++ b/devGuide/HowToAddNewLanguage.md @@ -8,36 +8,66 @@ Fork Stirling-PDF and create a new branch out of `main`. -Then add a reference to the language in the navbar by adding a new language entry to the dropdown: +## Add Language to i18n Configuration -- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/core/src/main/resources/templates/fragments/languages.html) +Edit the file: [frontend/src/i18n.ts](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/i18n.ts) +Add your language to the `supportedLanguages` object. For example, to add Polish: -For example, to add Polish, you would add: - -```html - +```typescript +export const supportedLanguages = { + 'en': 'English', + 'en-GB': 'English (UK)', + // ... other languages ... + 'pl-PL': 'Polski', // Add your language here +}; ``` -The `data-bs-language-code` is the code used to reference the file in the next step. +If your language uses right-to-left (RTL) text direction, also add it to the `rtlLanguages` array: -### Add Language Property File +```typescript +export const rtlLanguages = ['ar-AR', 'fa-IR', 'pl-PL']; // Add if RTL +``` -Start by copying the existing English property file: +## Create Translation Directory -- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/core/src/main/resources/messages_en_GB.properties) +Create a new directory for your language in `frontend/public/locales/`. For Polish, this would be: -Copy and rename it to `messages_{your data-bs-language-code here}.properties`. In the Polish example, you would set the name to `messages_pl_PL.properties`. +```bash +mkdir -p frontend/public/locales/pl-PL +``` -Then simply translate all property entries within that file and make a Pull Request (PR) into `main` for others to use! +## Add Translation File -If you do not have a Java IDE, I am happy to verify that the changes work once you raise the PR (but I won't be able to verify the translations themselves). +Start by copying the existing English (UK) translation file: + +- [frontend/public/locales/en-GB/translation.json](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/public/locales/en-GB/translation.json) + +Copy and rename it to `frontend/public/locales/{your-language-code}/translation.json`. In the Polish example: + +```bash +cp frontend/public/locales/en-GB/translation.json frontend/public/locales/pl-PL/translation.json +``` + +Then translate all entries within that JSON file. The file uses nested JSON structure like: + +```json +{ + "addPageNumbers": { + "title": "Add Page Numbers", + "submit": "Add Page Numbers", + "error": { + "failed": "Add page numbers operation failed" + } + } +} +``` ## Handling Untranslatable Strings -Sometimes, certain strings in the properties file may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations. +Sometimes, certain strings may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations. -For example, if the English string `error=Error` does not need translation in Polish, add it to the `ignore_translation.toml` under the Polish section: +For example, if the English string for "error" does not need translation in Polish, add it to the `ignore_translation.toml` under the Polish section: ```toml [pl_PL] @@ -50,27 +80,119 @@ ignore = [ ## Add New Translation Tags > [!IMPORTANT] -> If you add any new translation tags, they must first be added to the `messages_en_GB.properties` file. This ensures consistency across all language files. +> If you add any new translation tags, they must first be added to the `frontend/public/locales/en-GB/translation.json` file. This ensures consistency across all language files. -- New translation tags **must be added** to the `messages_en_GB.properties` file to maintain a reference for other languages. -- After adding the new tags to `messages_en_GB.properties`, add and translate them in the respective language file (e.g., `messages_pl_PL.properties`). +- New translation tags **must be added** to the `en-GB` translation file to maintain a reference for other languages. +- After adding the new tags to the en-GB file, add and translate them in the respective language file (e.g., `pl-PL/translation.json`). Make sure to place the entry under the correct language section. This helps maintain the accuracy of translation progress statistics and ensures that the translation tool or scripts do not misinterpret the completion rate. -### Use this code to perform a local check +## Testing Your Translation -#### Windows command +### Start the development server -```powershell -python .github/scripts/check_language_properties.py --reference-file app\core\src\main\resources\messages_en_GB.properties --branch "" --files app\core\src\main\resources\messages_pl_PL.properties +1. Start the frontend development server: + ```bash + cd frontend + npm run dev + ``` -python .github/scripts/check_language_properties.py --reference-file app\core\src\main\resources\messages_en_GB.properties --branch "" --check-file app\core\src\main\resources\messages_pl_PL.properties -``` +2. The language selector should now include your new language -#### Linux command +3. Select your language from the dropdown and verify all translations appear correctly + +## Summary Checklist + +When adding a new language, you need to update: + +- [ ] `frontend/src/i18n.ts` - Add to supportedLanguages (and rtlLanguages if needed) +- [ ] `frontend/public/locales/{language-code}/translation.json` - Create and translate +- [ ] `scripts/ignore_translation.toml` - Add untranslatable strings if needed + +Then make a Pull Request (PR) into `main` for others to use! + +If you do not have a Node.js environment, we are happy to verify that the changes work once you raise the PR (but we won't be able to verify the translations themselves). + +## Translation Guidelines + +- **Consistency**: Keep terminology consistent throughout the translation +- **Context**: Consider the UI context when translating (e.g., button labels should be concise) +- **Formatting**: Preserve placeholders like `{n}` or `{{count}}` in translations +- **Testing**: Test your translations in the frontend interface +- **RTL Languages**: If your language uses RTL, ensure you add it to the rtlLanguages array + +## Advanced: Translation Management Scripts + +For translators working on large translation files, Python scripts are available in `scripts/translations/` to help manage the workflow. + +### Finding Untranslated Strings + +To see which strings still need translation: ```bash -python3 .github/scripts/check_language_properties.py --reference-file app/core/src/main/resources/messages_en_GB.properties --branch "" --files app/core/src/main/resources/messages_pl_PL.properties +# Check translation status for your language +python scripts/translations/translation_analyzer.py --language pl-PL --summary -python3 .github/scripts/check_language_properties.py --reference-file app/core/src/main/resources/messages_en_GB.properties --branch "" --check-file app/core/src/main/resources/messages_pl_PL.properties +# See detailed list of missing translations +python scripts/translations/translation_analyzer.py --language pl-PL --missing-only ``` + +### Extracting Untranslated Strings + +To extract only the strings that need translation into a separate file: + +```bash +# Extract to a compact JSON file +python scripts/translations/compact_translator.py pl-PL --output to_translate.json +``` + +This creates a file with just the untranslated entries: + +```json +{ + "addPageNumbers.title": "Add Page Numbers", + "compress.header": "Compress PDF", + "merge.submit": "Merge PDFs" +} +``` + +### Translating the Extracted File + +Open `to_translate.json` and translate the values while keeping the keys unchanged: + +```json +{ + "addPageNumbers.title": "Dodaj numery stron", + "compress.header": "Kompresuj PDF", + "merge.submit": "Połącz pliki PDF" +} +``` + +### Merging Translations Back + +After translating, merge your translations back into the main file: + +```bash +# Apply your translations +python scripts/translations/translation_merger.py pl-PL apply-translations --translations-file to_translate.json + +# Verify the result +python scripts/translations/translation_analyzer.py --language pl-PL --summary +``` + +### Validating Your Work + +Before submitting, validate your translation file: + +```bash +# Check for JSON syntax errors +python scripts/translations/json_validator.py frontend/public/locales/pl-PL/translation.json + +# Check for missing placeholders +python scripts/translations/validate_placeholders.py --language pl-PL + +# Check for structural issues +python scripts/translations/validate_json_structure.py --language pl-PL +``` + +**Note**: These scripts require Python 3.7+ to be installed. See `scripts/translations/README.md` for detailed documentation.