h1k.sh/l1TGF0   [ home ]   [ history ]   [ rev 1 ]   [ rev 2 ]

--- rev 1  2026-05-04 14:23 UTC
+++ rev 2  2026-05-04 14:24 UTC

@@ -1,3 +1,40 @@
-#lang:python
+#lang:ts
+const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+const SLUG_LEN = 6;
 
-print("hello world")
+export function randomSlug(): string {
+  const bytes = new Uint8Array(SLUG_LEN);
+  crypto.getRandomValues(bytes);
+  let out = '';
+  for (let i = 0; i < SLUG_LEN; i++) {
+    out += ALPHABET[bytes[i]! % 62];
+  }
+  return out;
+}
+
+export function isValidSlug(s: string): boolean {
+  if (s.length < 1 || s.length > 32) return false;
+  return /^[a-zA-Z0-9][a-zA-Z0-9-]*$|^[a-zA-Z0-9]$/.test(s);
+}
+
+export function normalizeSlug(s: string): string {
+  return s.trim().toLowerCase();
+}
+
+const RESERVED = new Set([
+  'new', 'published', 'api', 'admin', 'e', 'feed', 'raw',
+  'stats', 'canary', 'health', 'robots', 'sitemap', 'install',
+  'random', 'search', 'help', 'about', 'legal', 'privacy',
+  'terms', 'contact', 'login', 'logout', 'register', 'account',
+  'settings', 'dashboard', 'profile', 'upload', 'download',
+]);
+
+export function isValidCustomSlug(s: string): boolean {
+  if (s.length < 1 || s.length > 32) return false;
+  if (s.startsWith('-') || s.endsWith('-')) return false;
+  if (s.includes('--')) return false;
+  if (!(/^[a-z0-9-]+$/.test(s))) return false;
+  if (RESERVED.has(s)) return false;
+  return true;
+}
+