progress
This commit is contained in:
parent
921abfb5b9
commit
47eb5ad72a
21
package-lock.json
generated
21
package-lock.json
generated
@ -8,9 +8,11 @@
|
||||
"name": "dfir-tools-hub",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"astro": "^4.0.0"
|
||||
"astro": "^4.0.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.13",
|
||||
"terser": "^5.27.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -1673,6 +1675,16 @@
|
||||
"@types/unist": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz",
|
||||
"integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||
@ -5044,6 +5056,13 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
|
||||
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unified": {
|
||||
"version": "11.0.5",
|
||||
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
|
||||
|
@ -11,9 +11,11 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.0.0"
|
||||
"astro": "^4.0.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.13",
|
||||
"terser": "^5.27.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -5,6 +5,7 @@
|
||||
<button
|
||||
class="btn-icon"
|
||||
data-theme-toggle
|
||||
data-current-theme="auto"
|
||||
onclick="window.themeUtils.toggleTheme()"
|
||||
title="Toggle theme"
|
||||
>
|
||||
@ -39,12 +40,26 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Default to auto icon if no attribute is set */
|
||||
[data-theme-toggle] .theme-icon-auto {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[data-current-theme="light"] .theme-icon-light,
|
||||
[data-current-theme="dark"] .theme-icon-dark,
|
||||
[data-current-theme="auto"] .theme-icon-auto {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[data-current-theme="light"] .theme-icon-dark,
|
||||
[data-current-theme="light"] .theme-icon-auto,
|
||||
[data-current-theme="dark"] .theme-icon-light,
|
||||
[data-current-theme="dark"] .theme-icon-auto,
|
||||
[data-current-theme="auto"] .theme-icon-light,
|
||||
[data-current-theme="auto"] .theme-icon-dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-current-theme="auto"] path {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
27
src/env.d.ts
vendored
27
src/env.d.ts
vendored
@ -1 +1,28 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
|
||||
// Extend the Window interface to include custom properties
|
||||
declare global {
|
||||
interface Window {
|
||||
themeUtils: {
|
||||
initTheme: () => void;
|
||||
toggleTheme: () => void;
|
||||
getStoredTheme: () => string;
|
||||
};
|
||||
toolsData: any[];
|
||||
showToolDetails: (toolName: string) => void;
|
||||
hideToolDetails: () => void;
|
||||
}
|
||||
|
||||
// Custom event types
|
||||
interface WindowEventMap {
|
||||
'toolsFiltered': CustomEvent<any[]>;
|
||||
'viewChanged': CustomEvent<string>;
|
||||
}
|
||||
}
|
||||
|
||||
// Also declare the modules that might not be recognized
|
||||
declare module 'js-yaml' {
|
||||
export function load(str: string): any;
|
||||
}
|
||||
|
||||
export {};
|
@ -22,7 +22,7 @@ const { title, description = 'DFIR Tools Hub - A comprehensive directory of digi
|
||||
<script src="/src/scripts/theme.js"></script>
|
||||
<script>
|
||||
// Initialize theme immediately to prevent flash
|
||||
window.themeUtils.initTheme();
|
||||
(window as any).themeUtils?.initTheme();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -54,12 +54,19 @@ const tools = data.tools;
|
||||
const matrixContainer = document.getElementById('matrix-container');
|
||||
const noResults = document.getElementById('no-results');
|
||||
|
||||
// Guard against null elements
|
||||
if (!toolsContainer || !toolsGrid || !matrixContainer || !noResults) {
|
||||
console.error('Required DOM elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Initial tools HTML
|
||||
const initialToolsHTML = toolsContainer.innerHTML;
|
||||
|
||||
// Handle filtered results
|
||||
window.addEventListener('toolsFiltered', (event) => {
|
||||
const filtered = event.detail;
|
||||
window.addEventListener('toolsFiltered', (event: Event) => {
|
||||
const customEvent = event as CustomEvent;
|
||||
const filtered = customEvent.detail;
|
||||
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
|
||||
|
||||
if (currentView === 'matrix') {
|
||||
@ -76,7 +83,7 @@ const tools = data.tools;
|
||||
noResults.style.display = 'none';
|
||||
|
||||
// Render filtered tools
|
||||
filtered.forEach(tool => {
|
||||
filtered.forEach((tool: any) => {
|
||||
const toolCard = createToolCard(tool);
|
||||
toolsContainer.appendChild(toolCard);
|
||||
});
|
||||
@ -84,8 +91,9 @@ const tools = data.tools;
|
||||
});
|
||||
|
||||
// Handle view changes
|
||||
window.addEventListener('viewChanged', (event) => {
|
||||
const view = event.detail;
|
||||
window.addEventListener('viewChanged', (event: Event) => {
|
||||
const customEvent = event as CustomEvent;
|
||||
const view = customEvent.detail;
|
||||
|
||||
if (view === 'matrix') {
|
||||
toolsGrid.style.display = 'none';
|
||||
@ -97,7 +105,7 @@ const tools = data.tools;
|
||||
});
|
||||
|
||||
// Create tool card element
|
||||
function createToolCard(tool) {
|
||||
function createToolCard(tool: any): HTMLElement {
|
||||
const cardDiv = document.createElement('div');
|
||||
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
|
||||
cardDiv.className = cardClass;
|
||||
@ -149,7 +157,7 @@ const tools = data.tools;
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem;">
|
||||
${tool.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
||||
${tool.tags.map((tag: string) => `<span class="tag">${tag}</span>`).join('')}
|
||||
</div>
|
||||
|
||||
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||
|
@ -17,15 +17,20 @@ function applyTheme(theme) {
|
||||
document.documentElement.setAttribute('data-theme', effectiveTheme);
|
||||
}
|
||||
|
||||
// Update theme toggle button state
|
||||
function updateThemeToggle(theme) {
|
||||
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
|
||||
button.setAttribute('data-current-theme', theme);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize theme on page load
|
||||
function initTheme() {
|
||||
const storedTheme = getStoredTheme();
|
||||
applyTheme(storedTheme);
|
||||
|
||||
// Update theme toggle buttons
|
||||
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
|
||||
button.setAttribute('data-current-theme', storedTheme);
|
||||
});
|
||||
// Update theme toggle buttons immediately
|
||||
updateThemeToggle(storedTheme);
|
||||
}
|
||||
|
||||
// Handle theme toggle
|
||||
@ -38,11 +43,7 @@ function toggleTheme() {
|
||||
|
||||
localStorage.setItem(THEME_KEY, nextTheme);
|
||||
applyTheme(nextTheme);
|
||||
|
||||
// Update all theme toggle buttons
|
||||
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
|
||||
button.setAttribute('data-current-theme', nextTheme);
|
||||
});
|
||||
updateThemeToggle(nextTheme);
|
||||
}
|
||||
|
||||
// Listen for system theme changes
|
||||
@ -52,6 +53,12 @@ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ()
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize immediately when script loads
|
||||
initTheme();
|
||||
|
||||
// Also initialize when DOM is ready (for safety)
|
||||
document.addEventListener('DOMContentLoaded', initTheme);
|
||||
|
||||
// Export functions for use in Astro components
|
||||
window.themeUtils = {
|
||||
initTheme,
|
||||
|
Reference in New Issue
Block a user