feat: pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization

Lands five integrated branches: pipeline templates (#355), analytics opt-out (#354), 83 conversion presets bringing the catalog to 240 tools (#356), self-hosted positioning (#353), and e2e modernization (#351).

Integration fixes: aligned stale web analytics tests with the opt-out/allow-list model, closed 3 CodeQL incomplete-sanitization alerts in the i18n generator, resolved settings/index/docs/format-matrix conflicts, and corrected tool counts to 240.
This commit is contained in:
SnapOtter
2026-06-28 18:57:53 +08:00
committed by GitHub
parent 88af8d46fb
commit 63a03d26f2
421 changed files with 17308 additions and 2540 deletions
+35
View File
@@ -0,0 +1,35 @@
import { normalizeSearchQuery } from "@snapotter/shared/search/format-aliases.js";
/** Bounded Levenshtein: returns edit distance, short-circuiting above `max`. */
function editDistance(a: string, b: string, max: number): number {
if (Math.abs(a.length - b.length) > max) return max + 1;
const dp = Array.from({ length: b.length + 1 }, (_, i) => i);
for (let i = 1; i <= a.length; i++) {
let prev = dp[0];
dp[0] = i;
let rowMin = dp[0];
for (let j = 1; j <= b.length; j++) {
const tmp = dp[j];
dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
prev = tmp;
if (dp[j] < rowMin) rowMin = dp[j];
}
if (rowMin > max) return max + 1;
}
return dp[b.length];
}
/** True if every normalized query token appears in the haystack (substring), or matches a haystack word within a small edit distance. */
export function matchTool(rawQuery: string, haystack: string): boolean {
const q = normalizeSearchQuery(rawQuery);
if (!q) return true;
const hay = haystack.toLowerCase();
const hayWords = hay.split(/\s+/);
const tokens = q.split(/\s+/).filter(Boolean);
return tokens.every((tok) => {
if (tok === "to") return true;
if (hay.indexOf(tok) !== -1) return true;
const max = tok.length <= 4 ? 1 : 2;
return hayWords.some((w) => editDistance(tok, w, max) <= max);
});
}