|
|
@@ -71,6 +71,8 @@ func NewBasicFormatter(left interface{}) *BasicFormatter {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Format takes the diff of two JSON documents, and returns the difference
|
|
|
+// between them summarized in an HTML document.
|
|
|
func (b *BasicFormatter) Format(d diff.Diff) ([]byte, error) {
|
|
|
// calling jsonDiff.Format(d) populates the JSON diff's "Lines" value,
|
|
|
// which we use to compute the basic dif
|
|
|
@@ -90,23 +92,40 @@ func (b *BasicFormatter) Format(d diff.Diff) ([]byte, error) {
|
|
|
return buf.Bytes(), nil
|
|
|
}
|
|
|
|
|
|
-// Basic is V2 of the basic diff
|
|
|
+// Basic transforms a slice of JSONLines into a slice of BasicBlocks.
|
|
|
func (b *BasicDiff) Basic(lines []*JSONLine) []*BasicBlock {
|
|
|
// init an array you can append to for the basic "blocks"
|
|
|
blocks := make([]*BasicBlock, 0)
|
|
|
|
|
|
- // iterate through each line
|
|
|
for _, line := range lines {
|
|
|
- // TODO: this condition needs an explaination? what does it mean?
|
|
|
+ // In order to produce distinct "blocks" when rendering the basic diff,
|
|
|
+ // we need a way to distinguish between differnt sections of data.
|
|
|
+ // To do this, we consider the value(s) of each top-level JSON key to
|
|
|
+ // represent a distinct block for Grafana's JSON data structure, so
|
|
|
+ // we perform this check to see if we've entered a new "block". If we
|
|
|
+ // have, we simply append the existing block to the array of blocks.
|
|
|
if b.LastIndent == 2 && line.Indent == 1 && line.Change == ChangeNil {
|
|
|
if b.Block != nil {
|
|
|
blocks = append(blocks, b.Block)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Record the last indent level at each pass in case we need to
|
|
|
+ // check for a change in depth inside the JSON data structures.
|
|
|
b.LastIndent = line.Indent
|
|
|
|
|
|
// TODO: why special handling for indent 2?
|
|
|
+ // Here we
|
|
|
+ // If the line's indentation is at level 1, then we know it's a top
|
|
|
+ // level key in the JSON document. As mentioned earlier, we treat these
|
|
|
+ // specially as they indicate their values belong to distinct blocks.
|
|
|
+ //
|
|
|
+ // At level 1, we only record single-line changes, ie, the "added",
|
|
|
+ // "deleted", "old" or "new" cases, since we know those values aren't
|
|
|
+ // arrays or maps. We only handle these cases at level 2 or deeper,
|
|
|
+ // since for those we either output a "change" or "summary". This is
|
|
|
+ // done for formatting reasons only, so we have logical "blocks" to
|
|
|
+ // display.
|
|
|
if line.Indent == 1 {
|
|
|
switch line.Change {
|
|
|
case ChangeNil:
|
|
|
@@ -139,17 +158,31 @@ func (b *BasicDiff) Basic(lines []*JSONLine) []*BasicBlock {
|
|
|
b.Block.New = line.Val
|
|
|
b.Block.LineEnd = line.LineNum
|
|
|
|
|
|
- // then write out the change
|
|
|
+ // For every "old" change there is a corresponding "new", which
|
|
|
+ // is why we wait until we detect the "new" change before
|
|
|
+ // appending the change.
|
|
|
blocks = append(blocks, b.Block)
|
|
|
default:
|
|
|
// ok
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // TODO: why special handling for indent > 2 ?
|
|
|
- // Other Lines
|
|
|
+ // Here is where we handle changes for all types, appending each change
|
|
|
+ // to the current block based on the value.
|
|
|
+ //
|
|
|
+ // Values which only occupy a single line in JSON (like a string or
|
|
|
+ // int, for example) are treated as "Basic Changes" that we append to
|
|
|
+ // the current block as soon as they're detected.
|
|
|
+ //
|
|
|
+ // Values which occupy multiple lines (either slices or maps) are
|
|
|
+ // treated as "Basic Summaries". When we detect the "ChangeNil" type,
|
|
|
+ // we know we've encountered one of these types, so we record the
|
|
|
+ // starting position as well the type of the change, and stop
|
|
|
+ // performing comparisons until we find the end of that change. Upon
|
|
|
+ // finding the change, we append it to the current block, and begin
|
|
|
+ // performing comparisons again.
|
|
|
if line.Indent > 1 {
|
|
|
- // Ensure single line change
|
|
|
+ // Ensure a single line change
|
|
|
if line.Key != "" && line.Val != nil && !b.writing {
|
|
|
switch line.Change {
|
|
|
case ChangeAdded, ChangeDeleted:
|