fix: preserve placeholder case when restoring project text
This commit is contained in:
17
src/lib/restore-case.ts
Normal file
17
src/lib/restore-case.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/** Keep the saved spelling for the canonical placeholder and adapt edited case variants. */
|
||||
export function restoreOriginalCase(match: string, key: string, original: string): string {
|
||||
if (match === key) return original;
|
||||
const letters = match.replace(/[^\p{L}]/gu, "");
|
||||
if (!letters) return original;
|
||||
if (letters === letters.toLocaleLowerCase("de")) return original.toLocaleLowerCase("de");
|
||||
if (letters === letters.toLocaleUpperCase("de")) return original.toLocaleUpperCase("de");
|
||||
if (/^\p{Lu}\p{Ll}+$/u.test(letters)) {
|
||||
const originalLetters = original.replace(/[^\p{L}]/gu, "");
|
||||
if (originalLetters && (originalLetters === originalLetters.toLocaleLowerCase("de")
|
||||
|| originalLetters === originalLetters.toLocaleUpperCase("de"))) {
|
||||
return original.toLocaleLowerCase("de").replace(/(^|[^\p{L}])(\p{L})/gu,
|
||||
(_, prefix: string, letter: string) => prefix + letter.toLocaleUpperCase("de"));
|
||||
}
|
||||
}
|
||||
return original;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { PlaceholderMapping } from "../types";
|
||||
import type { ProjectRun } from "./velum-project";
|
||||
import { restoreOriginalCase } from "./restore-case";
|
||||
|
||||
function escapeRegExp(value: string): string {
|
||||
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
@@ -98,6 +99,13 @@ function replaceNode(
|
||||
session: boolean,
|
||||
): { value: string; count: number } {
|
||||
const candidates: Match[] = [];
|
||||
const foldedCounts = new Map<string, number>();
|
||||
if (!session) {
|
||||
for (const key of Object.keys(mapping)) {
|
||||
const folded = key.toUpperCase();
|
||||
foldedCounts.set(folded, (foldedCounts.get(folded) ?? 0) + 1);
|
||||
}
|
||||
}
|
||||
for (const [key, entry] of Object.entries(mapping)) {
|
||||
const stripped = key.replace(/[<>]/g, "");
|
||||
const bare = session ? stripped : key;
|
||||
@@ -105,7 +113,7 @@ function replaceNode(
|
||||
matchModes?.[key] === "anywhere"
|
||||
? escapeRegExp(bare)
|
||||
: `(?<![\\p{L}\\p{N}])${escapeRegExp(bare)}(?![\\p{L}\\p{N}])`;
|
||||
const patterns = [new RegExp(boundary, "gu")];
|
||||
const patterns = [new RegExp(boundary, session ? "gu" : "giu")];
|
||||
if (session) {
|
||||
patterns.unshift(
|
||||
new RegExp(
|
||||
@@ -116,10 +124,12 @@ function replaceNode(
|
||||
}
|
||||
for (const pattern of patterns) {
|
||||
for (const match of value.matchAll(pattern)) {
|
||||
if (!session && match[0] !== key && (Object.prototype.hasOwnProperty.call(mapping, match[0])
|
||||
|| foldedCounts.get(key.toUpperCase()) !== 1)) continue;
|
||||
candidates.push({
|
||||
start: match.index,
|
||||
end: match.index + match[0].length,
|
||||
replacement: escapeHtml(entry.original),
|
||||
replacement: escapeHtml(session ? entry.original : restoreOriginalCase(match[0], key, entry.original)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { environment } from "@raycast/api";
|
||||
import type { EntityType, PlaceholderMapping } from "../types";
|
||||
import { whitelistKey } from "./project-whitelist";
|
||||
import type { ProjectWhitelistEntry } from "./project-whitelist";
|
||||
import { restoreOriginalCase } from "./restore-case";
|
||||
|
||||
export { whitelistKey } from "./project-whitelist";
|
||||
export type { ProjectWhitelistEntry } from "./project-whitelist";
|
||||
@@ -265,7 +266,7 @@ function restorePattern(mapping: PlaceholderMapping, matchModes: ProjectRun["mat
|
||||
originalFor: (match) => {
|
||||
const key = Object.prototype.hasOwnProperty.call(mapping, match)
|
||||
? match : foldedKeys.get(match.toUpperCase());
|
||||
return key ? mapping[key].original : undefined;
|
||||
return key ? restoreOriginalCase(match, key, mapping[key].original) : undefined;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user