← back to CelebritySignatures
scripts/tm-normalize.mjs
35 lines
// Shared name/mark normalizer for the trademark-clearance subsystem.
// Used by build-tm-index.mjs (index side) and build-tm-clearance.mjs + the
// server (query side) so both sides normalize identically — the match only
// works if "Andy Warhol" and a mark "ANDY WARHOL" collapse to the same key.
const SUFFIXES = new Set(['jr', 'sr', 'ii', 'iii', 'iv', 'phd', 'md', 'esq']);
// Fold accents, lowercase, drop punctuation, drop honorific/generational
// suffixes, collapse whitespace. Returns '' for empty/garbage input.
export function normName(raw) {
if (!raw) return '';
let s = String(raw)
.normalize('NFKD').replace(/[̀-ͯ]/g, '') // strip diacritics
.toLowerCase()
.replace(/&/g, ' and ')
.replace(/[^a-z0-9\s]/g, ' ') // punctuation -> space
.replace(/\s+/g, ' ')
.trim();
const toks = s.split(' ').filter(t => t && !SUFFIXES.has(t));
return toks.join(' ');
}
// Token set for subset/overlap matching (a mark that is a person's full name,
// or vice-versa, is a flag even if not an exact string match).
export function tokens(raw) {
return new Set(normName(raw).split(' ').filter(Boolean));
}
// Is set `a` a subset of set `b`? (all of a's tokens appear in b)
export function isSubset(a, b) {
if (!a.size) return false;
for (const t of a) if (!b.has(t)) return false;
return true;
}