Stirling-PDF/frontend/src/utils/urlRouting.ts
Anthony Stirling 166f6d2d98
path (#4488)
# 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.
2025-09-24 20:37:51 +01:00

135 lines
4.1 KiB
TypeScript

/**
* URL routing utilities for tool navigation with registry support
*/
import { ToolRoute } from '../types/navigation';
import { ToolId, isValidToolId } from '../types/toolId';
import { getDefaultWorkbench } from '../types/workbench';
import { ToolRegistry, getToolWorkbench, getToolUrlPath } from '../data/toolsTaxonomy';
import { firePixel } from './scarfTracking';
import { URL_TO_TOOL_MAP } from './urlMapping';
import { BASE_PATH, withBasePath } from '../constants/app';
/**
* Parse the current URL to extract tool routing information
*/
export function parseToolRoute(registry: ToolRegistry): ToolRoute {
const fullPath = window.location.pathname;
// Remove base path to get app-relative path
const path = BASE_PATH && fullPath.startsWith(BASE_PATH)
? fullPath.slice(BASE_PATH.length) || '/'
: fullPath;
const searchParams = new URLSearchParams(window.location.search);
// First, check URL mapping for multiple URL aliases
const mappedToolId = URL_TO_TOOL_MAP[path];
if (mappedToolId && registry[mappedToolId]) {
const tool = registry[mappedToolId];
return {
workbench: getToolWorkbench(tool),
toolId: mappedToolId
};
}
// Fallback: Try to find tool by primary URL path in registry
for (const [toolId, tool] of Object.entries(registry)) {
const toolUrlPath = getToolUrlPath(toolId, tool);
if (path === toolUrlPath && isValidToolId(toolId)) {
return {
workbench: getToolWorkbench(tool),
toolId
};
}
}
// Check for query parameter fallback (e.g., ?tool=split)
const toolParam = searchParams.get('tool');
if (toolParam && isValidToolId(toolParam) && registry[toolParam]) {
const tool = registry[toolParam];
return {
workbench: getToolWorkbench(tool),
toolId: toolParam
};
}
// Default to fileEditor workbench for home page
return {
workbench: getDefaultWorkbench(),
toolId: null
};
}
/**
* Update URL and fire analytics pixel
*/
function updateUrl(newPath: string, searchParams: URLSearchParams, replace: boolean = false): void {
const currentPath = window.location.pathname;
const queryString = searchParams.toString();
const fullUrl = newPath + (queryString ? `?${queryString}` : '');
// Only update URL and fire pixel if something actually changed
if (currentPath !== newPath || window.location.search !== (queryString ? `?${queryString}` : '')) {
if (replace) {
window.history.replaceState(null, '', fullUrl);
} else {
window.history.pushState(null, '', fullUrl);
}
firePixel(newPath);
}
}
/**
* Update the URL to reflect the current tool selection
*/
export function updateToolRoute(toolId: ToolId, registry: ToolRegistry, replace: boolean = false): void {
const tool = registry[toolId];
if (!tool) {
console.warn(`Tool ${toolId} not found in registry`);
return;
}
const toolPath = getToolUrlPath(toolId, tool);
const newPath = withBasePath(toolPath);
const searchParams = new URLSearchParams(window.location.search);
// Remove tool query parameter since we're using path-based routing
searchParams.delete('tool');
updateUrl(newPath, searchParams, replace);
}
/**
* Clear tool routing and return to home page
*/
export function clearToolRoute(replace: boolean = false): void {
const searchParams = new URLSearchParams(window.location.search);
searchParams.delete('tool');
updateUrl(withBasePath('/'), searchParams, replace);
}
/**
* Get clean tool name for display purposes using registry
*/
export function getToolDisplayName(toolId: ToolId, registry: ToolRegistry): string {
const tool = registry[toolId];
return tool ? tool.name : toolId;
}
/**
* Generate shareable URL for current tool state using registry
*/
export function generateShareableUrl(toolId: ToolId | null, registry: ToolRegistry): string {
const baseUrl = window.location.origin;
if (!toolId || !registry[toolId]) {
return `${baseUrl}${BASE_PATH || ''}`;
}
const tool = registry[toolId];
const toolPath = getToolUrlPath(toolId, tool);
const fullPath = withBasePath(toolPath);
return `${baseUrl}${fullPath}`;
}