TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1/** Text normalisation helpers shared by entity resolution, search and connectors. */23export function slugify(input: string, maxLength = 96): string {4 const s = input5 .normalize('NFKD')6 .replace(/[̀-ͯ]/g, '')7 .toLowerCase()8 .replace(/&/g, ' and ')9 .replace(/[^a-z0-9]+/g, '-')10 .replace(/^-+|-+$/g, '');11 return s.length > maxLength ? s.slice(0, maxLength).replace(/-+$/g, '') : s;12}1314/** Aggressive normalisation for matching: lowercase, ASCII, punctuation removed, common noise words dropped. */15const NOISE = new Set(['the', 'a', 'an', 'of', 'and', '&', 'card', 'cards', 'lot', 'rare', 'mint', 'nm', 'lp', 'mp', 'hp', 'wow', 'look', 'nice', 'beautiful', 'gorgeous', 'pop', 'gem', 'mt', 'l@@k']);16export function normalizeForMatch(input: string): string {17 return input18 .normalize('NFKD')19 .replace(/[̀-ͯ]/g, '')20 .toLowerCase()21 .replace(/[#№]/g, ' ')22 .replace(/[^a-z0-9./\- ]+/g, ' ')23 .split(/\s+/)24 .filter((t) => t && !NOISE.has(t))25 .join(' ')26 .trim();27}2829export function tokens(input: string): string[] {30 return normalizeForMatch(input).split(' ').filter(Boolean);31}3233/** Jaccard similarity of token sets (0–1). */34export function jaccard(a: string, b: string): number {35 const A = new Set(tokens(a));36 const B = new Set(tokens(b));37 if (A.size === 0 && B.size === 0) return 1;38 let inter = 0;39 for (const t of A) if (B.has(t)) inter++;40 return inter / (A.size + B.size - inter);41}4243export function truncate(s: string, n: number): string {44 return s.length <= n ? s : `${s.slice(0, n - 1)}…`;45}4647export function compactWhitespace(s: string): string {48 return s.replace(/\s+/g, ' ').trim();49}5051/** Extract a 4-digit year plausible for collectibles (1800–current+1). */52export function extractYear(s: string): number | null {53 const now = new Date().getUTCFullYear() + 1;54 const m = s.match(/\b(1[89]\d{2}|20\d{2})\b/g);55 if (!m) return null;56 for (const y of m) {57 const n = Number(y);58 if (n >= 1800 && n <= now) return n;59 }60 return null;61}62