HtmlChunk (@NotNull @Nls String template, Map.Entry<@NotNull @NonNls String, @NotNull HtmlChunk>... substitutions) { String[] parts = template.split("\\$", -1); if (parts.length % 2 != 1) { throw new IllegalArgumentException("Invalid template (must have even number of '$' characters): " + template); } HtmlBuilder builder = new HtmlBuilder(); Map<String, HtmlChunk> chunkMap = Stream.of(substitutions).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); for (int i = 0; i < parts.length; i++) { String part = parts[i]; if (i % 2 == 0) { builder.append(part); } else if (part.isEmpty()) { builder.append("$"); } else { builder.append(Objects.requireNonNull(chunkMap.get(part), part)); } } return builder.toFragment(); }