Files
codeql-action/node_modules/@concordance/react/lib/diffShallow.js
2020-05-13 11:13:27 +01:00

240 lines
12 KiB
JavaScript

'use strict'
function diffShallow (api, actual, expected, theme, indent) {
const childBuffer = api.lineBuilder.buffer()
const propertyBuffer = api.lineBuilder.buffer()
return {
append (formatted, origin) {
if (origin.isItem === true) {
childBuffer.append(formatted)
} else {
propertyBuffer.append(formatted)
}
},
finalize: () => {
const namesAreEqual = actual.compareNames(expected)
const actualName = actual.formatName(theme)
const expectedName = expected.formatName(theme)
const openTag = theme.react.openTag
const innerIndentation = indent.increase()
const allChildren = childBuffer.withFirstPrefixed(innerIndentation)
const children = allChildren.decompose()
const allProperties = propertyBuffer.withFirstPrefixed(innerIndentation)
const properties = allProperties.decompose()
// If the first properties are also the last, and either side has no
// children, ensure the properties are treated as being last. This
// leads to a better balanced diff.
if (properties.remaining.isEmpty && (!actual.hasChildren || !expected.hasChildren)) {
properties.last = properties.first
properties.first = {actual: api.lineBuilder.buffer(), expected: api.lineBuilder.buffer()}
}
const result = api.lineBuilder.buffer()
// Create a custom diff that is as neat as possible. It's likely
// there's a generic algorithm that can be used, but for expediency's
// sake handles all possible diffs by brute force instead.
if (actual.hasProperties && expected.hasProperties) {
if (namesAreEqual) {
result
.append(api.lineBuilder.first(openTag.start + actualName))
.append(properties.first.actual.stripFlags())
.append(properties.first.expected.stripFlags())
} else {
result
.append(api.lineBuilder.actual.first(openTag.start + actualName))
.append(properties.first.actual.stripFlags())
.append(api.lineBuilder.expected.first(openTag.start + expectedName))
.append(properties.first.expected.stripFlags())
}
result.append(properties.remaining.stripFlags())
if (actual.hasChildren && expected.hasChildren) {
result
.append(properties.last.actual.stripFlags())
.append(properties.last.expected.stripFlags())
.append(api.lineBuilder.line(indent + openTag.end))
if (namesAreEqual) {
result
.append(allChildren.stripFlags())
.append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
} else {
result
.append(children.first.actual.stripFlags())
.append(children.first.expected.stripFlags())
.append(children.remaining.stripFlags())
.append(children.last.actual.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(children.last.expected.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
}
} else if (actual.hasChildren) {
result
.append(properties.last.actual.stripFlags())
.append(api.lineBuilder.actual.line(indent + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(properties.last.expected.stripFlags())
.append(api.lineBuilder.expected.last(indent + openTag.selfClose + openTag.end))
} else if (expected.hasChildren) {
result
.append(properties.last.actual.stripFlags())
.append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end))
.append(properties.last.expected.stripFlags())
.append(api.lineBuilder.expected.line(indent + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
} else {
result
.append(properties.last.actual.stripFlags())
.append(properties.last.expected.stripFlags())
.append(api.lineBuilder.last(indent + openTag.selfClose + openTag.end))
}
} else if (actual.hasProperties) {
result
.append(api.lineBuilder.actual.first(openTag.start + actualName))
.append(allProperties.stripFlags())
if (actual.hasChildren && expected.hasChildren) {
result
.append(api.lineBuilder.actual.line(indent + openTag.end))
.append(children.first.actual.stripFlags())
.append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end))
.append(children.first.expected.stripFlags())
.append(children.remaining.stripFlags())
if (namesAreEqual) {
result
.append(children.last.actual.stripFlags())
.append(children.last.expected.stripFlags())
.append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
} else {
result
.append(children.last.actual.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(children.last.expected.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
}
} else if (actual.hasChildren) {
result
.append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end))
} else if (expected.hasChildren) {
result
.append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end))
.append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
} else {
result
.append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end))
.append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end))
}
} else if (expected.hasProperties) {
if (actual.hasChildren && expected.hasChildren) {
result
.append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end))
.append(children.first.actual.stripFlags())
.append(api.lineBuilder.expected.first(openTag.start + expectedName))
.append(allProperties.stripFlags())
.append(api.lineBuilder.expected.line(indent + openTag.end))
.append(children.first.expected.stripFlags())
.append(children.remaining.stripFlags())
if (namesAreEqual) {
result
.append(children.last.actual.stripFlags())
.append(children.last.expected.stripFlags())
.append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
} else {
result
.append(children.last.actual.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(children.last.expected.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
}
} else if (actual.hasChildren) {
result
.append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(api.lineBuilder.expected.first(openTag.start + expectedName))
.append(allProperties.stripFlags())
.append(api.lineBuilder.expected.last(indent + openTag.selfClose + openTag.end))
} else if (expected.hasChildren) {
result
.append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end))
.append(api.lineBuilder.expected.first(openTag.start + expectedName))
.append(allProperties.stripFlags())
.append(api.lineBuilder.expected.line(indent + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
} else {
result
.append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end))
.append(api.lineBuilder.expected.first(openTag.start + expectedName))
.append(allProperties.stripFlags())
.append(api.lineBuilder.expected.last(indent + openTag.selfCloseVoid + openTag.end))
}
} else {
if (actual.hasChildren && expected.hasChildren) {
if (namesAreEqual) {
result
.append(api.lineBuilder.first(openTag.start + actualName + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
} else {
result
.append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end))
.append(children.first.actual.stripFlags())
.append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end))
.append(children.first.expected.stripFlags())
.append(children.remaining.stripFlags())
.append(children.last.actual.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(children.last.expected.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName)))
}
} else if (actual.hasChildren) {
result
.append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
.append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end))
} else if (expected.hasChildren) {
result
.append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end))
.append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end))
.append(allChildren.stripFlags())
.append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName)))
} else {
if (namesAreEqual) {
result.append(api.lineBuilder.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end))
} else {
result
.append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end))
.append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end))
}
}
}
return result
},
shouldFormat (subject) {
return subject.isItem === true || subject.isProperty === true
},
increaseIndent: true
}
}
module.exports = diffShallow