@ui5/task-adaptation
Version:
Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment
111 lines • 5.07 kB
JavaScript
import { getLogger } from "@ui5/logger";
const log = getLogger("@ui5/task-adaptation::RenamingUtil");
export function rename(content, references, replacement) {
return renameMap(content, new Map(references.map(ref => [ref, replacement])), [replacement]);
}
export function renameMap(content, references, ignoreInStrings) {
const ignoredReferenceKeys = [];
for (const [key, value] of references) {
if (value.includes(".") !== key.includes(".")) {
ignoredReferenceKeys.push(key);
references.delete(key);
}
}
if (ignoredReferenceKeys.length > 0) {
log.info(`Ignored renaming: ${ignoredReferenceKeys.join(", ")}`);
}
const searchTerms = [...references.keys()];
if (!content || !searchTerms || searchTerms.length === 0) {
return content;
}
const dotToSlash = (str) => str.replaceAll(".", "\/");
// We don't want to replace in adaptation project ids
ignoreInStrings.push(...ignoreInStrings, ...ignoreInStrings.map(dotToSlash));
let start = 0;
while (true) {
// If we don't replace some strings in the content - we find all of them
// and then don't replace inside their start and end indices.
const ignoredStrings = ignoreInStrings.map(string => {
return findAllOccurrences(content, string, start).map(i => ({ start: i, end: i + string.length }));
}).filter(arr => arr.length > 0) || [];
// We find the next search index with dots and slashes. Then we replace
// the nearest one and start search again in the next loop step.
const indices = new Array();
for (const searchTerm of searchTerms) {
const searchTermSlash = dotToSlash(searchTerm);
indices.push({
i: content.indexOf(searchTerm, start),
replacement: references.get(searchTerm),
searchTerm
}, {
i: content.indexOf(searchTermSlash, start),
replacement: dotToSlash(references.get(searchTerm)),
searchTerm: searchTermSlash
});
}
const found = indices.filter(({ i }) => i > -1);
if (found.length === 0) {
return content;
}
const inBetween = (intervals, i) => {
for (const interval of intervals) {
for (const { start, end } of interval) {
if (i >= start && i <= end) {
return { start, end };
}
}
}
};
// If we found two strings with the same index, we take the longest one
// to replace, e.g.: app.variant and app.variant2 has the same index,
// but we don't want to replace the first one with customer.app.variant,
// otherwise we get customer.app.variant2, which we don't need. We need
// to replace the whole app.variant2 with customer.app.variant.
const findCurrentReplace = (found) => {
const result = new Map();
for (const entry of found) {
const existing = result.get(entry.i);
if (!existing || entry.searchTerm.length >= existing.searchTerm.length) {
result.set(entry.i, entry);
}
}
return [...result.values()].sort((a, b) => a.i - b.i)[0];
};
// Ignore if search is in i18n key: replace "id" in "{{id.key}}" with
// "customer.id" and we need only the next one in string
found.forEach(index => index.inBetween = inBetween(ignoredStrings, index.i));
// There might be a situation when we found something in ignored
// substrings and the index could be the nearest, but after that the
// next index might be the actual find to replace, so we first of all
// ignore all the ignored substring findings and get the next actual
// replacement. But if there are only ignored substrings found, we take
// the first one just to skip it and go further.
const currentReplace = findCurrentReplace(found);
if (currentReplace.inBetween) {
start = currentReplace.inBetween.end;
}
else {
content = content.substring(0, currentReplace.i)
+ currentReplace.replacement
+ content.substring(currentReplace.i + currentReplace.searchTerm.length);
start = currentReplace.i + currentReplace.replacement.length;
}
}
}
export function renameResources(files, search, replacement) {
return new Map([...files].map(([filepath, content]) => [filepath, rename(content, search, replacement)]));
}
function findAllOccurrences(string, substring, start) {
if (!substring) {
return [];
}
const indices = [];
let index = start;
while ((index = string.indexOf(substring, index)) !== -1) {
indices.push(index);
index += substring.length; // shift from current finding
}
return indices;
}
;
//# sourceMappingURL=renamingUtil.js.map