1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-25 03:20:23 +01:00
metamask-extension/ui/pages/confirmation/util.ts
2023-07-12 09:29:54 +01:00

151 lines
3.9 KiB
TypeScript

import { ResultComponent } from '@metamask/approval-controller';
type TemplateRendererComponent = {
key: string;
element: string;
props?: Record<string, unknown>;
children?:
| string
| TemplateRendererComponent
| (string | TemplateRendererComponent)[];
};
/**
* Processes an error message or ResultComponent and returns a TemplateRendererComponent
* or an array of strings | TemplateRendererComponents.
*
* @param input - The message or component to process.
* @param fallback - The fallback message to use when the input is not valid.
* @returns The processed error component.
*/
export function processError(
input: undefined | string | ResultComponent | ResultComponent[],
fallback: string,
): TemplateRendererComponent | (string | TemplateRendererComponent)[] {
const currentInput = convertResultComponents(input) || fallback;
if (typeof currentInput !== 'string') {
return currentInput;
}
return {
key: 'error',
element: 'ActionableMessage',
props: { type: 'danger', message: currentInput },
};
}
/**
* Processes a string or ResultComponent and returns a string or TemplateRendererComponent
* or an array of strings | TemplateRendererComponents.
*
* @param input - The message or component to process.
* @param fallback - The fallback string to use when the input is not valid.
* @returns The processed message.
*/
export function processString(
input: undefined | string | ResultComponent | ResultComponent[],
fallback: string,
): string | TemplateRendererComponent | (string | TemplateRendererComponent)[] {
const currentInput = convertResultComponents(input) || fallback;
if (typeof currentInput !== 'string') {
return currentInput;
}
return applyBold(currentInput);
}
/**
* Applies bold formatting to the message.
*
* @param message - The input message to apply bold formatting to.
* @returns The formatted message.
*/
function applyBold(message: string): (string | TemplateRendererComponent)[] {
const boldPattern = /\*\*(.+?)\*\*/gu;
return findMarkdown(message, boldPattern, (formattedText, index) => ({
key: `bold-${index}`,
element: 'b',
children: formattedText,
}));
}
/**
* Finds and formats markdown elements in the given text.
*
* @param text - The input text to search for markdown elements.
* @param pattern - The pattern to match the markdown elements.
* @param getElement - The callback function to create the formatted elements.
* @returns The array of formatted elements.
*/
function findMarkdown(
text: string,
pattern: RegExp,
getElement: (
formattedText: string,
index: number,
) => TemplateRendererComponent,
): (string | TemplateRendererComponent)[] {
let position = 0;
let index = 0;
const matches = Array.from(text.matchAll(pattern));
const elements = [];
for (const match of matches) {
const rawText = text.substring(position, match.index);
if (rawText.length) {
elements.push(rawText);
}
const formattedText = match[1];
const formattedElement = getElement(formattedText, index);
elements.push(formattedElement);
position = (match.index as number) + match[0].length;
index += 1;
}
const finalRawText = text.substring(position);
if (finalRawText.length) {
elements.push(finalRawText);
}
return elements;
}
function convertResultComponents(
input: undefined | string | ResultComponent | (string | ResultComponent)[],
):
| undefined
| string
| TemplateRendererComponent
| (string | TemplateRendererComponent)[] {
if (input === undefined) {
return undefined;
}
if (typeof input === 'string') {
return input;
}
if (Array.isArray(input)) {
return input.map(convertResultComponents) as (
| string
| TemplateRendererComponent
)[];
}
return {
key: input.key,
element: input.name,
props: input.properties,
children: convertResultComponents(input.children),
};
}