public List<Text> getTextNodes(int paragraph) {
		// Get the cell from the given paragraph. It should exist since we're
		// initializing a paragraph graphic for it.
		Cell<?, ?> cell = virtualCellList.get(paragraph);
		if (cell == null) return Collections.emptyList();

		// ParagraphBox is private in RichTextFX, but we just need to get the children so
		// casting to region suffices.
		Region paragraphBox = (Region) cell.getNode();
		ObservableList<Node> paragraphBoxChildren = paragraphBox.getChildrenUnmodifiable();

		if (paragraphBoxChildren.isEmpty())
			return Collections.emptyList();

		// The text flow is always the first child of the box.
		Region textFlow = (Region) paragraphBoxChildren.getFirst();

		// In the text flow, we want the first 'Text' child. This should be the first one with empty spaces.
		ObservableList<Node> flowChildren = textFlow.getChildrenUnmodifiable();
		return Unchecked.cast(flowChildren.stream()
				.filter(c -> c instanceof Text)
				.toList());
	}
Get text nodes on a paragraph
<p>
Be <b>very aware</b> of when you call this. You may encounter unexpected values if invoked during early
layout of your node / scene.
<p/>
This method is why we have to do the {@link FxThreadUtil#delayedRun(long, Runnable)} call above.
Normally when you use {@code virtualFlow.getCellIfVisible(paragraph)} it lays out the nodes for
you so that you don't run into this problem. The problem is it lays out the whole {@code ParagraphBox}
class, which includes the graphic factory we're currently populating the content of.
This means using that method will cause a {@link StackOverflowError}.
Thus, we have the hacky delayed run instead.

@param paragraph
		Paragraph index to get the text nodes of.

@return List of text nodes in the paragraph.
recaf-ui/src/main/java/software/coley/recaf/ui/control/richtext/Editor.java