# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Anthony Stirling
2025-09-24 15:01:18 +01:00
committed by GitHub
parent 25bedf064f
commit 6441dc1d6f
8 changed files with 255 additions and 22 deletions
+2 -3
View File
@@ -4,7 +4,6 @@ import { useToolWorkflow } from '../../contexts/ToolWorkflowContext';
import { useFileHandler } from '../../hooks/useFileHandler';
import { useFileState } from '../../contexts/FileContext';
import { useNavigationState, useNavigationActions } from '../../contexts/NavigationContext';
import { useToolManagement } from '../../hooks/useToolManagement';
import './Workbench.css';
import TopControls from '../shared/TopControls';
@@ -39,8 +38,8 @@ export default function Workbench() {
// Get navigation state - this is the source of truth
const { selectedTool: selectedToolId } = useNavigationState();
// Get tool registry to look up selected tool
const { toolRegistry } = useToolManagement();
// Get tool registry from context (instead of direct hook call)
const { toolRegistry } = useToolWorkflow();
const selectedTool = selectedToolId ? toolRegistry[selectedToolId] : null;
const { addFiles } = useFileHandler();
@@ -1,5 +1,5 @@
import React, { Suspense } from "react";
import { useToolManagement } from "../../hooks/useToolManagement";
import { useToolWorkflow } from "../../contexts/ToolWorkflowContext";
import { BaseToolProps } from "../../types/tool";
import ToolLoadingFallback from "./ToolLoadingFallback";
@@ -14,8 +14,8 @@ const ToolRenderer = ({
onComplete,
onError,
}: ToolRendererProps) => {
// Get the tool from registry
const { toolRegistry } = useToolManagement();
// Get the tool from context (instead of direct hook call)
const { toolRegistry } = useToolWorkflow();
const selectedTool = toolRegistry[selectedToolKey];
if (!selectedTool || !selectedTool.component) {
@@ -75,6 +75,7 @@ interface ToolWorkflowContextValue extends ToolWorkflowState {
selectedToolKey: string | null;
selectedTool: ToolRegistryEntry | null;
toolRegistry: any; // From useToolManagement
getSelectedTool: (toolId: string | null) => ToolRegistryEntry | null;
// UI Actions
setSidebarsVisible: (visible: boolean) => void;
@@ -247,6 +248,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
selectedToolKey: navigationState.selectedTool,
selectedTool,
toolRegistry,
getSelectedTool,
// Actions
setSidebarsVisible,
@@ -276,6 +278,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
navigationState.selectedTool,
selectedTool,
toolRegistry,
getSelectedTool,
setSidebarsVisible,
setLeftPanelView,
setReaderMode,
+2 -2
View File
@@ -1,6 +1,6 @@
import { useCallback } from 'react';
import { useToolNavigation } from './useToolNavigation';
import { useToolManagement } from './useToolManagement';
import { useToolWorkflow } from '../contexts/ToolWorkflowContext';
import { handleUnlessSpecialClick } from '../utils/clickHandlers';
export interface SidebarNavigationProps {
@@ -19,7 +19,7 @@ export function useSidebarNavigation(): {
getToolNavigation: (toolId: string) => SidebarNavigationProps | null;
} {
const { getToolNavigation: getToolNavProps } = useToolNavigation();
const { getSelectedTool } = useToolManagement();
const { getSelectedTool } = useToolWorkflow();
const defaultNavClick = useCallback((e: React.MouseEvent) => {
handleUnlessSpecialClick(e, () => {
+2 -2
View File
@@ -1,7 +1,7 @@
import { useMemo } from 'react';
import { useNavigationState } from '../contexts/NavigationContext';
import { useToolNavigation } from './useToolNavigation';
import { useToolManagement } from './useToolManagement';
import { useToolWorkflow } from '../contexts/ToolWorkflowContext';
import { ToolId } from '../types/toolId';
// Material UI Icons
@@ -50,7 +50,7 @@ const ALL_SUGGESTED_TOOLS: Omit<SuggestedTool, 'href' | 'onClick'>[] = [
export function useSuggestedTools(): SuggestedTool[] {
const { selectedTool } = useNavigationState();
const { getToolNavigation } = useToolNavigation();
const { getSelectedTool } = useToolManagement();
const { getSelectedTool } = useToolWorkflow();
return useMemo(() => {
// Filter out the current tool
+1 -1
View File
@@ -1,5 +1,5 @@
// Define all possible tool IDs as source of truth
const TOOL_IDS = [
export const TOOL_IDS = [
'certSign',
'sign',
'addPassword',
+100 -9
View File
@@ -2,10 +2,20 @@ import { ToolId } from '../types/toolId';
// Map URL paths to tool keys (multiple URLs can map to same tool)
export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
'/split-pdfs': 'split',
// Basic tools - standard patterns
'/split': 'split',
'/split-pdfs': 'split',
'/merge': 'merge',
'/merge-pdfs': 'merge',
'/compress': 'compress',
'/compress-pdf': 'compress',
'/rotate': 'rotate',
'/rotate-pdf': 'rotate',
'/repair': 'repair',
'/flatten': 'flatten',
'/crop': 'crop',
// Convert tool and all its variants
'/convert': 'convert',
'/convert-pdf': 'convert',
'/file-to-pdf': 'convert',
@@ -18,20 +28,101 @@ export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
'/pdf-to-pdfa': 'convert',
'/pdf-to-word': 'convert',
'/pdf-to-xml': 'convert',
// Security tools
'/add-password': 'addPassword',
'/remove-password': 'removePassword',
'/change-permissions': 'changePermissions',
'/cert-sign': 'certSign',
'/manage-signatures': 'certSign',
'/remove-certificate-sign': 'removeCertSign',
'/remove-cert-sign': 'removeCertSign',
'/unlock-pdf-forms': 'unlockPDFForms',
'/validate-signature': 'validateSignature',
'/manage-certificates': 'manageCertificates',
// Content manipulation
'/sanitize': 'sanitize',
'/sanitize-pdf': 'sanitize',
'/ocr': 'ocr',
'/ocr-pdf': 'ocr',
'/watermark': 'watermark',
'/add-watermark': 'watermark',
'/remove-password': 'removePassword',
'/add-image': 'addImage',
'/add-stamp': 'addStamp',
'/add-page-numbers': 'addPageNumbers',
'/redact': 'redact',
// Page manipulation
'/remove-pages': 'removePages',
'/remove-blanks': 'removeBlanks',
'/extract-pages': 'extractPages',
'/reorganize-pages': 'reorganizePages',
'/single-large-page': 'pdfToSinglePage',
'/repair': 'repair',
'/rotate-pdf': 'rotate',
'/unlock-pdf-forms': 'unlockPDFForms',
'/remove-certificate-sign': 'removeCertSign',
'/remove-cert-sign': 'removeCertSign',
'/cert-sign': 'certSign',
'/manage-signatures': 'certSign',
'/page-layout': 'pageLayout',
'/scale-pages': 'scalePages',
'/booklet-imposition': 'bookletImposition',
// Splitting tools
'/auto-split-pdf': 'autoSplitPDF',
'/auto-size-split-pdf': 'autoSizeSplitPDF',
'/scanner-image-split': 'scannerImageSplit',
// Annotation and content removal
'/remove-annotations': 'removeAnnotations',
'/remove-image': 'removeImage',
// Image and visual tools
'/extract-images': 'extractImages',
'/adjust-contrast': 'adjustContrast',
'/fake-scan': 'fakeScan',
'/replace-color-pdf': 'replaceColorPdf',
// Metadata and info
'/change-metadata': 'changeMetadata',
'/get-pdf-info': 'getPdfInfo',
'/add-attachments': 'addAttachments',
// Advanced tools
'/overlay-pdfs': 'overlayPdfs',
'/edit-table-of-contents': 'editTableOfContents',
'/auto-rename': 'autoRename',
'/compare': 'compare',
'/multi-tool': 'multiTool',
'/show-js': 'showJS',
// Special/utility tools
'/read': 'read',
'/automate': 'automate',
'/sign': 'sign',
// Developer tools
'/dev-api': 'devApi',
'/dev-folder-scanning': 'devFolderScanning',
'/dev-sso-guide': 'devSsoGuide',
'/dev-airgapped': 'devAirgapped',
// Legacy URL mappings from sitemap
'/pdf-organizer': 'reorganizePages',
'/multi-page-layout': 'pageLayout',
'/extract-page': 'extractPages',
'/pdf-to-single-page': 'pdfToSinglePage',
'/img-to-pdf': 'convert',
'/pdf-to-presentation': 'convert',
'/pdf-to-text': 'convert',
'/pdf-to-html': 'convert',
'/auto-redact': 'redact',
'/stamp': 'addStamp',
'/view-pdf': 'read',
'/get-info-on-pdf': 'getPdfInfo',
'/remove-image-pdf': 'removeImage',
'/replace-and-invert-color-pdf': 'replaceColorPdf',
'/pipeline': 'automate',
'/extract-image-scans': 'scannerImageSplit',
'/show-javascript': 'showJS',
'/scanner-effect': 'fakeScan',
'/split-by-size-or-count': 'autoSizeSplitPDF',
'/overlay-pdf': 'overlayPdfs',
'/split-pdf-by-sections': 'autoSplitPDF',
'/split-pdf-by-chapters': 'autoSplitPDF',
};