DVPageDocumentDiff.between constructor
DVPageDocumentDiff.between(
- DVPageDocument? before,
- DVPageDocument after
What after changes relative to before. A null before is a page
with nothing published: every top-level node is an addition.
Implementation
factory DVPageDocumentDiff.between(
DVPageDocument? before,
DVPageDocument after,
) {
final Map<String, _Placed> old = before == null
? <String, _Placed>{}
: _index(before.root, null, before);
final Map<String, _Placed> next = _index(after.root, null, after);
final List<DVPageNodeChange> changes = <DVPageNodeChange>[];
// Newer version first, in document order, so the list reads top to bottom
// the way the page does.
void walk(DVPageNode node) {
final _Placed here = next[node.id]!;
final _Placed? was = old[node.id];
final bool isRoot = node.id == after.root.id;
if (was == null && !isRoot) {
changes.add(
DVPageNodeChange(
kind: DVPageChangeKind.added,
nodeId: node.id,
label: here.label,
summary: _summary(node),
descendants: _count(node),
),
);
return; // Its children came with it.
}
if (was != null) {
final List<DVPagePropertyChange> properties = _propertyChanges(
was.node,
node,
);
final bool moved = !isRoot && _moved(was, here, old, next);
if (moved) {
changes.add(
DVPageNodeChange(
kind: DVPageChangeKind.moved,
nodeId: node.id,
label: here.label,
summary: _summary(node),
properties: properties,
fromParent: was.parent == null ? null : old[was.parent]!.label,
toParent: here.parent == null ? null : next[here.parent]!.label,
),
);
} else if (properties.isNotEmpty) {
changes.add(
DVPageNodeChange(
kind: DVPageChangeKind.changed,
nodeId: node.id,
label: here.label,
summary: _summary(node),
properties: properties,
),
);
}
}
for (final DVPageNode child in node.children) {
walk(child);
}
}
walk(after.root);
// Then removals, top-most only: a removed container took its children.
if (before != null) {
void removed(DVPageNode node) {
if (!next.containsKey(node.id)) {
changes.add(
DVPageNodeChange(
kind: DVPageChangeKind.removed,
nodeId: node.id,
label: old[node.id]!.label,
summary: _summary(node),
descendants: _count(node),
),
);
return;
}
for (final DVPageNode child in node.children) {
removed(child);
}
}
removed(before.root);
}
return DVPageDocumentDiff._(
title: before == null || before.title == after.title
? null
: DVPagePropertyChange('title', before.title, after.title),
nodes: List<DVPageNodeChange>.unmodifiable(changes),
);
}