File size: 1,535 Bytes
d9494a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { isDefined } from '@/utils/validation';
import { evalFromContext } from './evalFromContext';

const VARIABLE_TAG_PATTERN =
  /\{"type":"variableTag","attrs":\{"variable":"(\{\{[^{}]+\}\})"\}\}|\{"attrs":\{"variable":"(\{\{[^{}]+\}\})"\},"type":"variableTag"\}/g;

const escapeJsonString = (text: string): string => {
  return JSON.stringify(text).slice(1, -1);
};

const buildTextNodesWithLineBreaks = (text: string): string => {
  const lines = text.split('\n');

  if (lines.length === 1) {
    return `{"type":"text","text":"${escapeJsonString(text)}"}`;
  }

  return lines
    .map((line, index) => {
      const textNode = `{"type":"text","text":"${escapeJsonString(line)}"}`;

      if (index < lines.length - 1) {
        return `${textNode},{"type":"hardBreak"}`;
      }

      return textNode;
    })
    .join(',');
};

export const resolveRichTextVariables = (
  input: string | null | undefined,
  context: Record<string, unknown>,
): string | undefined => {
  if (!isDefined(input)) {
    return undefined;
  }

  return input.replace(
    VARIABLE_TAG_PATTERN,
    (_, variableTypeFirst: string, variableAttrsFirst: string) => {
      const variable = variableTypeFirst ?? variableAttrsFirst;
      const resolvedValue = evalFromContext(variable, context);
      const textValue = !isDefined(resolvedValue)
        ? ''
        : typeof resolvedValue === 'object'
          ? JSON.stringify(resolvedValue)
          : String(resolvedValue);

      return buildTextNodesWithLineBreaks(textValue);
    },
  );
};