deduplication
This commit is contained in:
parent
050774ad99
commit
9ce2098439
20110
data/embeddings.json
20110
data/embeddings.json
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,6 @@
|
||||
// src/components/AIQueryInterface.astro
|
||||
|
||||
import { getToolsData } from '../utils/dataService.js';
|
||||
import { isToolHosted } from '../utils/toolHelpers.js';
|
||||
|
||||
const data = await getToolsData();
|
||||
const tools = data.tools;
|
||||
|
@ -22,36 +22,26 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
|
||||
<script>
|
||||
function createToolSlug(toolName) {
|
||||
if (!toolName || typeof toolName !== 'string') {
|
||||
console.warn('[toolHelpers] Invalid toolName provided to createToolSlug:', toolName);
|
||||
return '';
|
||||
// Import utility functions from shared client module instead of duplicating
|
||||
async function loadUtilityFunctions() {
|
||||
try {
|
||||
const { createToolSlug, findToolByIdentifier, isToolHosted } = await import('../utils/clientUtils.js');
|
||||
|
||||
// Make functions available globally for backward compatibility
|
||||
(window as any).createToolSlug = createToolSlug;
|
||||
(window as any).findToolByIdentifier = findToolByIdentifier;
|
||||
(window as any).isToolHosted = isToolHosted;
|
||||
} catch (error) {
|
||||
console.error('Failed to load utility functions:', error);
|
||||
// Minimal fallback for critical functionality only
|
||||
(window as any).createToolSlug = (toolName: string) => {
|
||||
if (!toolName || typeof toolName !== 'string') return '';
|
||||
return toolName.toLowerCase().replace(/[^a-z0-9\s-]/g, '').replace(/\s+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
||||
};
|
||||
}
|
||||
|
||||
return toolName.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '') // Remove special characters
|
||||
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
||||
.replace(/-+/g, '-') // Remove duplicate hyphens
|
||||
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
|
||||
}
|
||||
|
||||
function findToolByIdentifier(tools, identifier) {
|
||||
if (!identifier || !Array.isArray(tools)) return undefined;
|
||||
|
||||
return tools.find(tool =>
|
||||
tool.name === identifier ||
|
||||
createToolSlug(tool.name) === identifier.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
function isToolHosted(tool) {
|
||||
return tool.projectUrl !== undefined &&
|
||||
tool.projectUrl !== null &&
|
||||
tool.projectUrl !== "" &&
|
||||
tool.projectUrl.trim() !== "";
|
||||
}
|
||||
|
||||
function scrollToElement(element, options = {}) {
|
||||
function scrollToElement(element: Element | null, options = {}) {
|
||||
if (!element) return;
|
||||
|
||||
setTimeout(() => {
|
||||
@ -67,17 +57,21 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function scrollToElementById(elementId, options = {}) {
|
||||
function scrollToElementById(elementId: string, options = {}) {
|
||||
const element = document.getElementById(elementId);
|
||||
scrollToElement(element, options);
|
||||
if (element) {
|
||||
scrollToElement(element, options);
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToElementBySelector(selector, options = {}) {
|
||||
function scrollToElementBySelector(selector: string, options = {}) {
|
||||
const element = document.querySelector(selector);
|
||||
scrollToElement(element, options);
|
||||
if (element) {
|
||||
scrollToElement(element, options);
|
||||
}
|
||||
}
|
||||
|
||||
function prioritizeSearchResults(tools, searchTerm) {
|
||||
function prioritizeSearchResults(tools: any[], searchTerm: string) {
|
||||
if (!searchTerm || !searchTerm.trim()) {
|
||||
return tools;
|
||||
}
|
||||
@ -85,8 +79,8 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
const lowerSearchTerm = searchTerm.toLowerCase().trim();
|
||||
|
||||
return tools.sort((a, b) => {
|
||||
const aTagsLower = (a.tags || []).map(tag => tag.toLowerCase());
|
||||
const bTagsLower = (b.tags || []).map(tag => tag.toLowerCase());
|
||||
const aTagsLower = (a.tags || []).map((tag: string) => tag.toLowerCase());
|
||||
const bTagsLower = (b.tags || []).map((tag: string) => tag.toLowerCase());
|
||||
|
||||
const aExactTag = aTagsLower.includes(lowerSearchTerm);
|
||||
const bExactTag = bTagsLower.includes(lowerSearchTerm);
|
||||
@ -98,15 +92,16 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
});
|
||||
}
|
||||
|
||||
(window as any).createToolSlug = createToolSlug;
|
||||
(window as any).findToolByIdentifier = findToolByIdentifier;
|
||||
(window as any).isToolHosted = isToolHosted;
|
||||
// Set non-duplicated functions on window
|
||||
(window as any).scrollToElement = scrollToElement;
|
||||
(window as any).scrollToElementById = scrollToElementById;
|
||||
(window as any).scrollToElementBySelector = scrollToElementBySelector;
|
||||
(window as any).prioritizeSearchResults = prioritizeSearchResults;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Load utility functions first
|
||||
loadUtilityFunctions();
|
||||
|
||||
const THEME_KEY = 'dfir-theme';
|
||||
|
||||
function getSystemTheme() {
|
||||
@ -117,12 +112,12 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
return localStorage.getItem(THEME_KEY) || 'auto';
|
||||
}
|
||||
|
||||
function applyTheme(theme) {
|
||||
function applyTheme(theme: string) {
|
||||
const effectiveTheme = theme === 'auto' ? getSystemTheme() : theme;
|
||||
document.documentElement.setAttribute('data-theme', effectiveTheme);
|
||||
}
|
||||
|
||||
function updateThemeToggle(theme) {
|
||||
function updateThemeToggle(theme: string) {
|
||||
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
|
||||
button.setAttribute('data-current-theme', theme);
|
||||
});
|
||||
@ -192,7 +187,7 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
}
|
||||
}
|
||||
|
||||
async function requireClientAuth(callback, returnUrl, context = 'general') {
|
||||
async function requireClientAuth(callback: () => void, returnUrl: string, context = 'general') {
|
||||
const authStatus = await checkClientAuth(context);
|
||||
|
||||
if (authStatus.authRequired && !authStatus.authenticated) {
|
||||
@ -207,12 +202,12 @@ const { title, description = 'ForensicPathways - A comprehensive directory of di
|
||||
}
|
||||
}
|
||||
|
||||
async function showIfAuthenticated(selector, context = 'general') {
|
||||
async function showIfAuthenticated(selector: string, context = 'general') {
|
||||
const authStatus = await checkClientAuth(context);
|
||||
const element = document.querySelector(selector);
|
||||
|
||||
if (element) {
|
||||
element.style.display = (!authStatus.authRequired || authStatus.authenticated)
|
||||
(element as HTMLElement).style.display = (!authStatus.authRequired || authStatus.authenticated)
|
||||
? 'inline-flex'
|
||||
: 'none';
|
||||
}
|
||||
|
31
src/utils/clientUtils.ts
Normal file
31
src/utils/clientUtils.ts
Normal file
@ -0,0 +1,31 @@
|
||||
// src/utils/clientUtils.js
|
||||
// Client-side utilities that mirror server-side toolHelpers.ts
|
||||
|
||||
export function createToolSlug(toolName) {
|
||||
if (!toolName || typeof toolName !== 'string') {
|
||||
console.warn('[toolHelpers] Invalid toolName provided to createToolSlug:', toolName);
|
||||
return '';
|
||||
}
|
||||
|
||||
return toolName.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '') // Remove special characters
|
||||
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
||||
.replace(/-+/g, '-') // Remove duplicate hyphens
|
||||
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
|
||||
}
|
||||
|
||||
export function findToolByIdentifier(tools, identifier) {
|
||||
if (!identifier || !Array.isArray(tools)) return undefined;
|
||||
|
||||
return tools.find(tool =>
|
||||
tool.name === identifier ||
|
||||
createToolSlug(tool.name) === identifier.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
export function isToolHosted(tool) {
|
||||
return tool.projectUrl !== undefined &&
|
||||
tool.projectUrl !== null &&
|
||||
tool.projectUrl !== "" &&
|
||||
tool.projectUrl.trim() !== "";
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user