public static List<IntRange> flatten(StyleSpans<Collection<String>> styleSpans) {
		// Map the style spans (which only know their own length) into ranges that know their absolute positions.
		List<StyledRange> styledRanges = new ArrayList<>();
		int position = 0;
		for (StyleSpan<Collection<String>> span : styleSpans) {
			int length = span.getLength();
			styledRanges.add(new StyledRange(new IntRange(position, position + length), span.getStyle()));
			position += length;
		}

		// Flatten the ranges together where possible.
		// For example, where each line represents a range, and letters are classes:
		//
		// This sample will be merged into one range of A:
		//
		//  A
		//  AB
		//  A
		int i = 0;
		while (i < styledRanges.size() - 1) {
			StyledRange current = styledRanges.get(i);
			StyledRange next = styledRanges.get(i + 1);
			if (current.canMergeInto(next)) {
				current.merge(next);
				styledRanges.remove(next);
			} else {
				i++;
			}
		}

		// Map back to regular ranges.
		return styledRanges.stream()
				.map(StyledRange::getRange)
				.filter(range -> !range.empty())
				.toList();
	}
The {@link StyleSpans} of RichTextFX are not a tree-like structure. If you have something you wish to style in
the middle of another block, you have to create three blocks instead of having a sub-range in the parent span.
<br>
Having to deal with this layout is kind of annoying when regenerating styles. To deal with that, we flatten cases
as described prior into a single range. If it were ideally represented as a tree, we are stripping all but the
base layer.
<br>
Usage of this can be seen in {@link #getRangeForRestyle(String, StyleSpans, SyntaxHighlighter, PlainTextChange)}.

@param styleSpans
		Collection of {@link StyleSpan}.

@return Flat representation of ranges.
recaf-ui/src/main/java/software/coley/recaf/ui/control/richtext/syntax/SyntaxUtil.java