From b18823e88f383cafd28b332f93a5a070ef855dc0 Mon Sep 17 00:00:00 2001 From: DominikDoom Date: Sat, 22 Apr 2023 22:33:48 +0200 Subject: [PATCH] Sliding window search, fix double replacement --- javascript/_utils.js | 8 ++++++++ javascript/tagAutocomplete.js | 37 +++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/javascript/_utils.js b/javascript/_utils.js index 863b4d3..0804f5e 100644 --- a/javascript/_utils.js +++ b/javascript/_utils.js @@ -89,6 +89,14 @@ function difference(a, b) { )].reduce((acc, [v, count]) => acc.concat(Array(Math.abs(count)).fill(v)), []); } +// Sliding window function to get possible combination groups of an array +function toWindows(inputArray, size) { + return Array.from( + {length: inputArray.length - (size - 1)}, //get the appropriate length + (_, index) => inputArray.slice(index, index+size) //create the windows + ) + } + function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } diff --git a/javascript/tagAutocomplete.js b/javascript/tagAutocomplete.js index 158304a..9f3b545 100644 --- a/javascript/tagAutocomplete.js +++ b/javascript/tagAutocomplete.js @@ -611,8 +611,41 @@ async function updateRuby(textArea, prompt) { } escapedTag = escapeRegExp(escapedTag); - if (translation) - ruby.innerHTML = ruby.innerHTML.replaceAll(new RegExp(`${escapedTag}(?:\\)|\\b)`, "g"), `${translation}${tag}`); + if (translation) { + ruby.innerHTML = ruby.innerHTML.replaceAll(new RegExp(`(?)${escapedTag}(?:\\)|\\b)(?!)`, "g"), `${tag}${translation}`); + } else { + // No direct match, but we can try to find matches in 2 or 1 word windows + let subTags = tag.split(" "); + // Return if there is only one word + if (subTags.length === 1) return; + + const translateWindows = function (windows) { + windows.forEach(window => { + let windowTag = window.join(" "); + let unsanitizedWindowTag = windowTag + .replaceAll(" ", "_") + .replaceAll("\\(", "(") + .replaceAll("\\)", ")"); + + let translation = translations?.get(windowTag) || translations?.get(unsanitizedWindowTag); + + let escapedWindowTag = windowTag; + if (windowTag.endsWith("\\)")) { + escapedWindowTag = escapedWindowTag.substring(0, escapedWindowTag.length - 1); + } + escapedWindowTag = escapeRegExp(escapedWindowTag); + + if (translation) { + ruby.innerHTML = ruby.innerHTML.replaceAll(new RegExp(`(?)${escapedWindowTag}(?:\\)|\\b)(?!)`, "g"), `${windowTag}${translation}`); + subTags = subTags.filter(tag => !window.includes(tag)); + } + }); + } + + // Get sliding windows of 2 words and each word individually + translateWindows(toWindows(subTags, 2), subTags); + translateWindows(toWindows(subTags, 1), subTags); + } }); }