findLogicalContainer function
InlineContainerNode?
findLogicalContainer(
- FNode root,
- String fragmentId, {
- Map<
String, InlineContainerNode?> ? logicalContainerCache,
Finds the first InlineContainerNode (Paragraph/ListItem/FluentCell)
that contains fragmentId as a direct text descendant.
Link is transparent: its fragments belong to the parent container.
If logicalContainerCache is provided (e.g. document's internal cache),
it is used for an O(1) lookup instead of a full DFS traversal.
Implementation
InlineContainerNode? findLogicalContainer(
FNode root,
String fragmentId, {
Map<String, InlineContainerNode?>? logicalContainerCache,
}) {
if (logicalContainerCache != null) {
return logicalContainerCache[fragmentId];
}
InlineContainerNode? search(FNode node, InlineContainerNode? currentContainer) {
// FluentImage atomic:
// - INLINE (inside Paragraph/Link, currentContainer is Paragraph):
// it's a fragment of the Paragraph → return the Paragraph.
// - BLOCK-LEVEL (parent Root/ListItem/FluentCell, currentContainer
// is that "block container"): it's its own logical-line → return
// the image itself.
if (node is FluentImage && node.id == fragmentId) {
if (currentContainer is Paragraph) return currentContainer;
return node as InlineContainerNode;
}
if (node is HorizontalRule && node.id == fragmentId) {
return node as InlineContainerNode;
}
// Link: transparent, doesn't update currentContainer
if (node is Link) {
for (final child in node.getChildren()) {
final found = search(child, currentContainer);
if (found != null) return found;
}
return null;
}
// FluentList / FluentTable: descend without container
if (node is FluentList || node is FluentTable || node is FluentRow) {
for (final child in childrenOf(node)) {
final found = search(child, null);
if (found != null) return found;
}
return null;
}
// InlineContainerNode (Paragraph, ListItem, FluentCell): new container
if (node is InlineContainerNode) {
final container = node as InlineContainerNode;
for (final child in container.getChildren()) {
if (child is FluentList) {
// Sublists: new container scope
final found = search(child, null);
if (found != null) return found;
} else {
final found = search(child, container);
if (found != null) return found;
}
}
return null;
}
// Leaf Fragment: check if it's the one searched for
if (node is Fragment && node.id == fragmentId) {
return currentContainer;
}
return null;
}
return search(root, null);
}