String (@NotNull String line, @NotNull List<TextRange> skipRanges) { Matcher matcher = TAG_START_OR_CLOSE_PATTERN.matcher(line); StringBuilder builder = new StringBuilder(line); int diff = 0; l: while (matcher.find()) { final String tagName = matcher.group(2); if (ACCEPTABLE_TAGS.contains(StringUtil.toLowerCase(tagName))) continue; int startOfTag = matcher.start(2); for (TextRange range : skipRanges) { if (range.contains(startOfTag)) { continue l; } } var start = matcher.start(1) + diff; if (StringUtil.toLowerCase(tagName).equals("div")) { boolean isOpenTag = !matcher.group(0).contains("/"); var end = start + (isOpenTag ? 5 : 6); String replacement = isOpenTag ? "<span>" : "</span>"; builder.replace(start, end, replacement); diff += 1; } else { builder.replace(start, start + 1, "&lt;"); diff += 3; } } return builder.toString(); }