Improve docs, responsive, add Material Icons

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-04-12 16:42:19 +02:00
parent 72c382bb07
commit 302166c87d
37 changed files with 176 additions and 110 deletions
+10 -8
View File
@@ -60,17 +60,19 @@
{#each filtered as sheet}
<a
href={`/cheatsheets/${sheet.id}`}
class="card bg-base-200 hover:bg-base-300 transition-colors p-4 flex flex-row items-center gap-4"
class="card bg-base-200 hover:bg-base-300 transition-colors p-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4"
>
<div class="size-2 rounded-full bg-primary shrink-0"></div>
<div class="flex-1 min-w-0">
<div class="font-semibold text-sm">{sheet.title}</div>
{#if sheet.description}
<div class="text-base-content/50 text-xs mt-0.5">{sheet.description}</div>
{/if}
<div class="flex items-center gap-4 flex-1 min-w-0">
<div class="size-2 rounded-full bg-primary shrink-0"></div>
<div class="min-w-0">
<div class="font-semibold text-sm">{sheet.title}</div>
{#if sheet.description}
<div class="text-base-content/50 text-xs mt-0.5">{sheet.description}</div>
{/if}
</div>
</div>
{#if sheet.tags && sheet.tags.length > 0}
<div class="flex gap-1 shrink-0">
<div class="flex flex-wrap gap-1 sm:justify-end">
{#each sheet.tags as tag}
<span class="badge badge-xs badge-ghost">{tag}</span>
{/each}
+1 -1
View File
@@ -19,6 +19,6 @@
{#if demo}
<div class="w-full bg-warning/15 border-b border-warning/30 py-1.5 px-4 flex items-center justify-center gap-2 text-xs text-warning">
<FlaskConical size={13} class="shrink-0" />
<span>Demo mode searches and configuration changes are disabled</span>
<span>Demo mode: searches and configuration changes are disabled</span>
</div>
{/if}
+4 -4
View File
@@ -158,8 +158,8 @@
if (s === "found") return "Found";
if (s === "not_found") return "Not found";
if (s === "maybe") return "Maybe";
if (s === "checking") return "Checking";
return "";
if (s === "checking") return "Checking...";
return "-";
}
</script>
@@ -296,7 +296,7 @@
{#if !userScannerAvailable}
<div class="alert alert-warning text-sm gap-2">
<TriangleAlert size={15} class="shrink-0" />
<span><span class="font-mono">user-scanner</span> is not installed email and username checking will be unavailable.</span>
<span><span class="font-mono">user-scanner</span> is not installed, email and username checking will be unavailable.</span>
</div>
{/if}
@@ -414,7 +414,7 @@
<HelpCircle size={13} /> Maybe
</span>
{:else}
<span class="text-xs text-base-content/30"></span>
<span class="text-xs text-base-content/30">-</span>
{/if}
</td>
<td class="text-right">
+33 -12
View File
@@ -13,6 +13,15 @@
} from "@lucide/svelte";
import type { Snippet } from "svelte";
let mobileMenuOpen = $state(false);
function onDocumentClick(e: MouseEvent) {
if (!mobileMenuOpen) return;
if (!(e.target as HTMLElement).closest("[data-mobile-nav]")) {
mobileMenuOpen = false;
}
}
let {
action,
}: {
@@ -46,17 +55,20 @@
];
</script>
<svelte:document onclick={onDocumentClick} />
<div class="bg-base-200">
<div class="navbar max-w-5xl m-auto">
<div class="navbar-start">
<div class="dropdown">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
<Menu size={20} />
</div>
<ul
tabindex="-1"
class="menu menu-sm dropdown-content bg-base-300 rounded-box z-50 mt-3 w-52 p-2"
<div class="relative" data-mobile-nav>
<button
class="btn btn-ghost lg:hidden"
onclick={(e) => { e.stopPropagation(); mobileMenuOpen = !mobileMenuOpen; }}
>
<Menu size={20} />
</button>
{#if mobileMenuOpen}
<ul class="menu menu-sm absolute bg-base-300 rounded-box z-50 mt-1 w-52 p-2">
{#each navLinks as link}
<li>
{#if link.children}
@@ -64,7 +76,11 @@
<ul class="p-2">
{#each link.children as sublink}
<li>
<a href={sublink.href} class="flex items-center gap-2">
<a
href={sublink.href}
class="flex items-center gap-2"
onclick={() => (mobileMenuOpen = false)}
>
{#if sublink.icon}
{@const Icon = sublink.icon}
<Icon size={12} />
@@ -75,7 +91,11 @@
{/each}
</ul>
{:else}
<a href={link.href} class="flex items-center gap-2">
<a
href={link.href}
class="flex items-center gap-2"
onclick={() => (mobileMenuOpen = false)}
>
{#if link.icon}
{@const Icon = link.icon}
<Icon size={12} />
@@ -86,8 +106,9 @@
</li>
{/each}
</ul>
{/if}
</div>
<!-- Logo à gauche sur écran moyen et grand -->
<!-- Logo on medium/large screens -->
<a
href="/"
class="btn btn-ghost text-xl hidden sm:flex justify-center gap-2 items-center"
@@ -98,7 +119,7 @@
</div>
<div class="navbar-center lg:flex">
<!-- Logo centré sur petit écran (mobile) -->
<!-- Logo centered on mobile -->
<a
href="/"
class="btn btn-ghost text-xl flex sm:hidden justify-center gap-2 items-center"
@@ -106,7 +127,7 @@
<img src="/logo.svg" class="m-auto h-4" alt="iky logo" />
<img src="/logo-large.svg" class="m-auto h-4" alt="iky logo large" />
</a>
<!-- Nav links sur grand écran -->
<!-- Nav links on large screens -->
<ul class="menu menu-horizontal px-1 hidden lg:flex">
{#each navLinks as link}
<li>
+2 -2
View File
@@ -141,7 +141,7 @@
<div class="flex flex-col gap-2">
{#if proxies.length === 0}
<p class="text-sm text-base-content/40">
No proxies configured tools will connect directly.
No proxies configured, tools will connect directly.
</p>
{:else}
{#each proxies as proxy, i}
@@ -191,7 +191,7 @@
<p class="text-xs text-base-content/40">
Supported: <span class="font-mono">socks5://</span>,
<span class="font-mono">socks4://</span>,
<span class="font-mono">http://</span> — on failure, the next proxy is tried automatically.
<span class="font-mono">http://</span>. On failure, the next proxy is tried automatically.
</p>
</div>
{/if}
+3 -3
View File
@@ -8,7 +8,7 @@
const DETECTORS = {
email: (_raw, v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),
phone: (_raw, v) => /^\+\d{1,4} \d{4,}$/.test(v),
ip: (_raw, v) => /^(\d{1,3}\.){3}\d{1,3}$/.test(v) || /^[0-9a-fA-F:]{3,39}$/.test(v),
ip: (_raw, v) => /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/.test(v) || (/^[0-9a-fA-F:]{3,39}$/.test(v) && v.includes(':')),
domain: (raw, v) => /^https?:\/\//.test(raw) || /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(v),
name: (_raw, v) => /^[a-zA--ÿ'-]+(?: [a-zA-ZÀ-ÿ'-]+){1,2}$/.test(v),
};
@@ -16,8 +16,8 @@
const VALIDATORS = {
email: { test: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v), msg: "Invalid email address" },
username: { test: (v) => /^[a-zA-Z0-9._-]+$/.test(v), msg: "Username may only contain a-z, 0-9, . - _" },
phone: { test: (v) => /^\+\d{1,4} \d{4,}$/.test(v), msg: "Format: +INDICATIF NUMERO (ex: +33 0612345678)" },
ip: { test: (v) => /^(\d{1,3}\.){3}\d{1,3}$/.test(v) || /^[0-9a-fA-F:]{3,39}$/.test(v), msg: "Invalid IP address" },
phone: { test: (v) => /^\+\d{1,4} \d{4,}$/.test(v), msg: "Format: +COUNTRYCODE NUMBER (e.g. +1 2025550147)" },
ip: { test: (v) => /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/.test(v) || (/^[0-9a-fA-F:]{3,39}$/.test(v) && v.includes(':')), msg: "Invalid IP address" },
domain: { test: (v) => /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(v), msg: "Invalid domain name" },
};
+1 -1
View File
@@ -230,7 +230,7 @@
</details>
{#if demo}
<p class="text-xs text-base-content/40 italic">Results shown are not exhaustive demo mode only displays a subset of what the tools can find.</p>
<p class="text-xs text-base-content/40 italic">Results shown are not exhaustive: demo mode only displays a subset of what the tools can find.</p>
{/if}
</div>
+2 -2
View File
@@ -406,7 +406,7 @@
<div class="alert alert-warning py-2 px-3 text-sm gap-2">
<AlertTriangle size={15} class="shrink-0" />
<span>
<strong>proxychains4</strong> not found in PATH external binary tools
<strong>proxychains4</strong> not found in PATH, external binary tools
(maigret, ghunt, etc.) will <strong>not</strong> be proxied.
Only HTTP-based tools are affected by the proxy config.
</span>
@@ -418,7 +418,7 @@
{#if proxies.length === 0}
<div class="border border-dashed border-base-300 rounded-box py-8 text-center">
<Shield size={24} class="mx-auto mb-2 text-base-content/20" />
<p class="text-sm text-base-content/40">No proxies tools connect directly.</p>
<p class="text-sm text-base-content/40">No proxies, tools connect directly.</p>
</div>
{:else}
{#each proxies as proxy, i}
+27 -24
View File
@@ -1,29 +1,32 @@
<script lang="ts">
const { iconName = "", size=16 }: { iconName: string , size: number} = $props();
const { iconName = "", size = 16 }: { iconName: string; size: number } = $props();
const genericFallbackUrl = "/Wrench.svg";
function resolveUrl(name: string): string {
if (name.startsWith("mdi:")) {
return `https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${name.slice(4)}.svg`;
}
if (name.startsWith("sh:")) {
return `https://cdn.jsdelivr.net/gh/selfhst/icons/svg/${name.slice(3)}.svg`;
}
// si: prefix or no prefix, default to Simple Icons
const slug = name.startsWith("si:") ? name.slice(3) : name;
return `https://cdn.simpleicons.org/${slug}`;
}
const src = $derived(iconName ? resolveUrl(iconName) : genericFallbackUrl);
</script>
{#if iconName}
<img
src="https://cdn.simpleicons.org/{iconName}"
alt={iconName + " icon"}
class="opacity-50"
width={size}
height={size}
style="filter: brightness(0) invert(1);"
onerror={(e) => {
const target = e.currentTarget as HTMLImageElement;
target.src = genericFallbackUrl;
}}
/>
{:else}
<img
src={genericFallbackUrl}
alt={"Tool icon"}
class="opacity-50"
width={size}
height={size}
style="filter: brightness(0) invert(1);"
/>
{/if}
<img
{src}
alt={iconName ? iconName + " icon" : "Tool icon"}
class="opacity-50"
width={size}
height={size}
style="filter: brightness(0) invert(1);"
onerror={(e) => {
const target = e.currentTarget as HTMLImageElement;
target.src = genericFallbackUrl;
}}
/>
@@ -97,7 +97,7 @@ Once you have a **name**, an **email**, or a **unique username**, its time to
If you want to move from manual investigation to automated intelligence, check out [Github-Recon](https://github.com/anotherhadi/github-recon).
Written in Go, this powerful CLI tool aggregates public OSINT data by automating the techniques mentioned above and more. Whether you start with a username or a single email address, it can retrieve SSH/GPG keys, enumerate social accounts, and find "close friends" based on interactions.
Its standout features include a **Deep Scan** mode-which clones repositories to perform regex searches and TruffleHog secret detectionand an automated **Email Spoofing** engine that instantly identifies the account linked to any primary email address.
Its standout features include a **Deep Scan** mode (clones repositories for regex searches and TruffleHog secret detection) and an automated **Email Spoofing** engine that identifies the account linked to any primary email address.
<a href="https://github.com/anotherhadi/github-recon" class="link-card" target="_blank">
<span>
+1 -1
View File
@@ -141,7 +141,7 @@ import Layout from "@src/layouts/Layout.astro";
</li>
</ul>
<p class="text-base-content/70 text-sm leading-relaxed">
If no proxies are configured, tools connect directly — behaviour is identical to before.
If no proxies are configured, tools connect directly.
</p>
</section>