79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import { CanonicalName } from './name-input-types';
|
|
import { INTL_NAME_TOKENS } from './tokens';
|
|
|
|
export const UNIVERSAL_NAME_PATTERN = 'UNIVERSAL' as const;
|
|
|
|
function initial(value?: string) {
|
|
return (value?.[0] ?? '').toUpperCase();
|
|
}
|
|
function valueOrEmpty(v?: string) {
|
|
return v ?? '';
|
|
}
|
|
|
|
export function formatNameByPattern(pattern: string, ctx: CanonicalName): string {
|
|
if (pattern === UNIVERSAL_NAME_PATTERN) {
|
|
return [ctx.firstName, ctx.lastName, ctx.patronymic].filter(Boolean).join(' ').trim();
|
|
}
|
|
|
|
const TOKEN_REGEX = /(Pr|Su|FF|LL|PP|MM|F|L|P|M)/g;
|
|
|
|
const resolveToken = (token: string): string => {
|
|
switch (token) {
|
|
case INTL_NAME_TOKENS.FIRST.FULL:
|
|
return valueOrEmpty(ctx.firstName);
|
|
case INTL_NAME_TOKENS.FIRST.INITIAL:
|
|
return initial(ctx.firstName);
|
|
|
|
case INTL_NAME_TOKENS.LAST.FULL:
|
|
return valueOrEmpty(ctx.lastName);
|
|
case INTL_NAME_TOKENS.LAST.INITIAL:
|
|
return initial(ctx.lastName);
|
|
|
|
case INTL_NAME_TOKENS.MIDDLE.FULL:
|
|
return valueOrEmpty(ctx.middleName);
|
|
case INTL_NAME_TOKENS.MIDDLE.INITIAL:
|
|
return initial(ctx.middleName);
|
|
|
|
case INTL_NAME_TOKENS.PATRONYMIC.FULL:
|
|
return valueOrEmpty(ctx.patronymic);
|
|
case INTL_NAME_TOKENS.PATRONYMIC.INITIAL:
|
|
return initial(ctx.patronymic);
|
|
|
|
case INTL_NAME_TOKENS.PREFIX:
|
|
return valueOrEmpty(ctx.prefix);
|
|
|
|
case INTL_NAME_TOKENS.SUFFIX:
|
|
return valueOrEmpty(ctx.suffix);
|
|
|
|
default:
|
|
return '';
|
|
}
|
|
};
|
|
|
|
const renderTokensWithPresence = (str: string): { text: string; hasValue: boolean } => {
|
|
let hasValue = false;
|
|
const text = str.replace(TOKEN_REGEX, (token) => {
|
|
const value = resolveToken(token);
|
|
if (value !== '') hasValue = true;
|
|
return value;
|
|
});
|
|
return { text, hasValue };
|
|
};
|
|
|
|
let out = pattern;
|
|
|
|
const blockRe = /\{([^{}]*)\}/g;
|
|
|
|
while (true) {
|
|
const before = out;
|
|
out = out.replace(blockRe, (_, inner: string) => {
|
|
const { text, hasValue } = renderTokensWithPresence(inner);
|
|
return hasValue ? text : '';
|
|
});
|
|
if (out === before) break;
|
|
}
|
|
|
|
out = renderTokensWithPresence(out).text;
|
|
return out.replace(/\s+/g, ' ').trim();
|
|
}
|