element-vir
Version:
Heroic. Reactive. Declarative. Type safe. Web components without compromise.
103 lines (102 loc) • 4.6 kB
JavaScript
import { insertAndRemoveValues } from '../util/array.js';
import { getAlreadyMappedTemplate, setMappedTemplate } from './nested-mapped-templates.js';
export function getTransformedTemplate(templateStringsKey, values, fallbackTransform) {
const alreadyTransformedTemplateStrings = getAlreadyMappedTemplate(templateStringsKey, values);
const templateTransform = alreadyTransformedTemplateStrings ?? fallbackTransform();
if (!alreadyTransformedTemplateStrings) {
const result = setMappedTemplate(templateStringsKey, values, templateTransform);
if (!result.result) {
throw new Error(`Failed to set template transform: ${result.reason}`);
}
}
const valueTransforms = templateTransform.valuesTransform(values);
const transformedValuesArray = insertAndRemoveValues(values, valueTransforms.valueInsertions, valueTransforms.valueIndexDeletions);
return {
strings: templateTransform.templateStrings,
values: transformedValuesArray,
};
}
export function transformTemplate(inputTemplateStrings, inputValues, transformValue, assertValidString) {
const newStrings = [];
const newRaws = [];
const valueIndexDeletions = [];
const valueTransforms = [];
inputTemplateStrings.forEach((currentTemplateString, currentTemplateStringIndex) => {
const lastNewStringsIndex = newStrings.length - 1;
const lastNewString = newStrings[lastNewStringsIndex];
const currentValueIndex = currentTemplateStringIndex - 1;
const currentValue = inputValues[currentValueIndex];
if (assertValidString) {
assertValidString(currentTemplateString);
}
let transformOutput = undefined;
let extraValues = [];
if (typeof lastNewString === 'string') {
transformOutput = transformValue(lastNewString, currentTemplateString, currentValue);
if (transformOutput) {
newStrings[lastNewStringsIndex] = [
lastNewString,
transformOutput.replacement,
].join('');
valueIndexDeletions.push(currentValueIndex);
const getExtraValuesCallback = transformOutput.getExtraValues;
extraValues = getExtraValuesCallback ? getExtraValuesCallback(currentValue) : [];
if (extraValues.length && getExtraValuesCallback) {
newStrings[lastNewStringsIndex] += ' ';
extraValues.forEach((value, index) => {
// don't insert the first time, we need n-1 inserts
if (index) {
newStrings.push(' ');
}
});
valueTransforms.push((values) => {
const latestCurrentValue = values[currentValueIndex];
const insertions = getExtraValuesCallback(latestCurrentValue);
return {
index: currentValueIndex,
values: insertions,
};
});
newStrings.push(currentTemplateString);
}
else {
newStrings[lastNewStringsIndex] += currentTemplateString;
}
}
}
if (!transformOutput) {
newStrings.push(currentTemplateString);
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const currentRawLitString = inputTemplateStrings.raw[currentTemplateStringIndex];
if (transformOutput) {
newRaws[lastNewStringsIndex] = [
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
newRaws[lastNewStringsIndex],
transformOutput.replacement,
currentRawLitString,
].join('');
if (extraValues.length) {
extraValues.forEach(() => {
newRaws.push('');
});
}
}
else {
newRaws.push(currentRawLitString);
}
});
const newTemplateStrings = Object.assign([], newStrings, {
raw: newRaws,
});
return {
templateStrings: newTemplateStrings,
valuesTransform(values) {
const insertions = valueTransforms.flatMap((transformCallback) => transformCallback(values));
return {
valueIndexDeletions,
valueInsertions: insertions,
};
},
};
}