goja-core/src/main/java/goja/core/kits/StrTemplateKit.java
public String parse(String template, MacroResolver macroResolver) {
        StringBuilder result = new StringBuilder(template.length());

        int i = 0;
        int len = template.length();

        int startLen = macroStart.length();
        int endLen = macroEnd.length();

        while (i < len) {
            int ndx = template.indexOf(macroStart, i);
            if (ndx == -1) {
                result.append(i == 0 ? template : template.substring(i));
                break;
            }

            // check escaped
            int j = ndx - 1;
            boolean escape = false;
            int count = 0;

            while ((j >= 0) && (template.charAt(j) == escapeChar)) {
                escape = !escape;
                if (escape) {
                    count++;
                }
                j--;
            }
            if (resolveEscapes) {
                result.append(template.substring(i, ndx - count));
            } else {
                result.append(template.substring(i, ndx));
            }
            if (escape) {
                result.append(macroStart);
                i = ndx + startLen;
                continue;
            }

            // find macros end
            ndx += startLen;
            int ndx2 = template.indexOf(macroEnd, ndx);
            if (ndx2 == -1) {
                throw new IllegalArgumentException(
                        "Invalid template, unclosed macro at: " + (ndx - startLen));
            }

            // detect inner macros, there is no escaping
            int ndx1 = ndx;
            while (ndx1 < ndx2) {
                int n = indexOf(template, macroStart, ndx1, ndx2);
                if (n == -1) {
                    break;
                }
                ndx1 = n + startLen;
            }

            String name = template.substring(ndx1, ndx2);

            // find value and append
            Object value;
            if (missingKeyReplacement != null || !replaceMissingKey) {
                try {
                    value = macroResolver.resolve(name);
                } catch (Exception ignore) {
                    value = null;
                }

                if (value == null) {
                    if (replaceMissingKey) {
                        value = missingKeyReplacement;
                    } else {
                        value = template.substring(ndx1 - startLen, ndx2 + 1);
                    }
                }
            } else {
                value = macroResolver.resolve(name);
                if (value == null) {
                    value = StringPool.EMPTY;
                }
            }

            if (ndx == ndx1) {
                String stringValue = value.toString();
                if (parseValues) {
                    if (stringValue.contains(macroStart)) {
                        stringValue = parse(stringValue, macroResolver);
                    }
                }
                result.append(stringValue);
                i = ndx2 + endLen;
            } else {
                // inner macro
                template = template.substring(0, ndx1 - startLen) + value.toString() + template.substring(
                        ndx2 + endLen);
                len = template.length();
                i = ndx - startLen;
            }
        }
        return result.toString();
    }
public String parse(String template, MacroResolver macroResolver) {
        StringBuilder result = new StringBuilder(template.length());

        int i = 0;
        int len = template.length();

        int startLen = macroStart.length();
        int endLen = macroEnd.length();

        while (i < len) {
            int ndx = template.indexOf(macroStart, i);
            if (ndx == -1) {
                result.append(i == 0 ? template : template.substring(i));
                break;
            }

            // check escaped
            int j = ndx - 1;
            boolean escape = false;
            int count = 0;

            while ((j >= 0) && (template.charAt(j) == escapeChar)) {
                escape = !escape;
                if (escape) {
                    count++;
                }
                j--;
            }
            if (resolveEscapes) {
                result.append(template.substring(i, ndx - count));
            } else {
                result.append(template.substring(i, ndx));
            }
            if (escape) {
                result.append(macroStart);
                i = ndx + startLen;
                continue;
            }

            // find macros end
            ndx += startLen;
            int ndx2 = template.indexOf(macroEnd, ndx);
            if (ndx2 == -1) {
                throw new IllegalArgumentException(
                        "Invalid template, unclosed macro at: " + (ndx - startLen));
            }

            // detect inner macros, there is no escaping
            int ndx1 = ndx;
            while (ndx1 < ndx2) {
                int n = indexOf(template, macroStart, ndx1, ndx2);
                if (n == -1) {
                    break;
                }
                ndx1 = n + startLen;
            }

            String name = template.substring(ndx1, ndx2);

            // find value and append
            Object value;
            if (missingKeyReplacement != null || !replaceMissingKey) {
                try {
                    value = macroResolver.resolve(name);
                } catch (Exception ignore) {
                    value = null;
                }

                if (value == null) {
                    if (replaceMissingKey) {
                        value = missingKeyReplacement;
                    } else {
                        value = template.substring(ndx1 - startLen, ndx2 + 1);
                    }
                }
            } else {
                value = macroResolver.resolve(name);
                if (value == null) {
                    value = StringPool.EMPTY;
                }
            }

            if (ndx == ndx1) {
                String stringValue = value.toString();
                if (parseValues) {
                    if (stringValue.contains(macroStart)) {
                        stringValue = parse(stringValue, macroResolver);
                    }
                }
                result.append(stringValue);
                i = ndx2 + endLen;
            } else {
                // inner macro
                template = template.substring(0, ndx1 - startLen) + value.toString() + template.substring(
                        ndx2 + endLen);
                len = template.length();
                i = ndx - startLen;
            }
        }
        return result.toString();
    }
Parses string template and replaces macros with resolved values.