diff --git a/scripts/qa.mjs b/scripts/qa.mjs index 4df3842..b7e502a 100644 --- a/scripts/qa.mjs +++ b/scripts/qa.mjs @@ -150,7 +150,7 @@ const PATTERNS = [ ['slack-token', /\bxox[baprs]-[A-Za-z0-9-]{10,}/], ['jwt', /\beyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/], ['url-credentials', /\bhttps?:\/\/[^\s/:@'"]+:[^\s/@'"]{3,}@[^\s'"]+/], - ['generic-secret', /\b(?:api[_-]?key|secret|token|passw(?:or)?d)\b['"]?\s*[:=]\s*['"][A-Za-z0-9_\-+/=]{20,}['"]/i], + ['generic-secret', /\b(?:api[_-]?key|secret|token|passw(?:or)?d)\b['"]?\s*[:=]\s*['"][a-z0-9_\-+/=]{20,}['"]/i], ]; function secretScan() { let hits = 0; diff --git a/static/js/library-characters.js b/static/js/library-characters.js index 38d02f7..f7121d3 100644 --- a/static/js/library-characters.js +++ b/static/js/library-characters.js @@ -3330,7 +3330,7 @@ function _charRealLine(rec) { const sources = Array.isArray(rec.sheet && rec.sheet.sources) ? rec.sheet.sources : []; const quotes = sources.map(function (s) { return s && s.quote ? String(s.quote).trim() : ''; }) .filter(function (q) { return q.length >= 20 && q.length <= 240; }); - const spoken = quotes.find(function (q) { return /[""„"]/.test(q); }); + const spoken = quotes.find(function (q) { return /["„]/.test(q); }); if (spoken) return spoken; if (quotes.length) return quotes[0]; return null; diff --git a/static/js/magazine.js b/static/js/magazine.js index e6f0afc..2c9b8c7 100644 --- a/static/js/magazine.js +++ b/static/js/magazine.js @@ -4873,7 +4873,7 @@ function clearWordHighlight() { function estimateWordTimings(words, totalSeconds) { if (!words.length || !totalSeconds) return []; const FIXED = 0.6; // arbitrary units, shifts weight toward evening out short words - const weights = words.map((w) => Math.max(1, w.replace(/[.,!?;:"'()«»„"]/g, '').length) + FIXED); + const weights = words.map((w) => Math.max(1, w.replace(/[.,!?;:"'()«»„]/g, '').length) + FIXED); const total = weights.reduce((a, b) => a + b, 0); let t = 0; return weights.map((w) => { diff --git a/static/js/reader.js b/static/js/reader.js index 7f5a7d1..362ea8b 100644 --- a/static/js/reader.js +++ b/static/js/reader.js @@ -464,7 +464,7 @@ async function readerOcrPageHeading(page, base, pageIdx, gapPx) { // clean "3.Kapitel" recognition also produced a trailing "|" token, // which broke chapter-detection's stricter "nothing after the heading // but a number/subtitle" check by leaving that stray symbol behind it. - const tokens = text.split(' ').filter(t => t && /[a-zäöüßàâçéèêëîïôûùüÿñæœ0-9]/i.test(t)); + const tokens = text.split(' ').filter(t => t && /[a-zäöüßàâçéèêëîïôûùÿñæœ0-9]/i.test(t)); if (!tokens.length) return []; const bandH = Math.max(gapPx - 4, 10); const avgCharW = Math.max((base.width - 16) / text.length, 4); diff --git a/static/js/rehearser-train.js b/static/js/rehearser-train.js index e54a4d4..44e7daa 100644 --- a/static/js/rehearser-train.js +++ b/static/js/rehearser-train.js @@ -4,7 +4,7 @@ (function (root) { function _trainNormWords(str) { - return (str || '').toLowerCase().replace(/[^a-zäöüàáâãèéêëìíîïòóôõùúûüýÿæœßа-яёА-ЯЁ0-9\s]/g, '').trim().split(/\s+/).filter(Boolean); + return (str || '').toLowerCase().replace(/[^a-zäöüàáâãèéêëìíîïòóôõùúûýÿæœßа-яёА-ЯЁ0-9\s]/g, '').trim().split(/\s+/).filter(Boolean); } function _trainLcs(a, b) {