Handle invalid json
- fix style
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import * as diff from 'diff'
|
import * as diff from 'diff'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import ShowChart from '@material-ui/icons/ShowChart'
|
import ShowChart from '@material-ui/icons/ShowChart'
|
||||||
import { JsonPropertyLocation, literalsMappedByLines } from '../../../../../backend/src/JsonAstParser'
|
import { JsonPropertyLocation } from '../../../../../backend/src/JsonAstParser'
|
||||||
import { lineChangeStyle, trimNewlineRight } from './util'
|
import { lineChangeStyle, trimNewlineRight } from './util'
|
||||||
import { Theme } from '@material-ui/core'
|
import { Theme } from '@material-ui/core'
|
||||||
import { withStyles } from '@material-ui/styles'
|
import { withStyles } from '@material-ui/styles'
|
||||||
@@ -15,21 +15,39 @@ interface Props {
|
|||||||
const style = (theme: Theme) => {
|
const style = (theme: Theme) => {
|
||||||
return {
|
return {
|
||||||
gutterLine: {
|
gutterLine: {
|
||||||
|
display: 'flex' as 'flex',
|
||||||
textAlign: 'right' as 'right',
|
textAlign: 'right' as 'right',
|
||||||
paddingRight: theme.spacing(0.5),
|
paddingRight: theme.spacing(0.5),
|
||||||
|
height: '16px',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tokensForLine(change: diff.Change, line: number, literalPositions: Array<JsonPropertyLocation>) {
|
||||||
|
let diagram = literalPositions[line] ? <ShowChart style={{ height: '16px' }} /> : ''
|
||||||
|
|
||||||
|
if (change.added) {
|
||||||
|
return [diagram, '+']
|
||||||
|
} else if (change.removed) {
|
||||||
|
return '-'
|
||||||
|
} else {
|
||||||
|
return [diagram, ' ']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Gutters(props: Props) {
|
function Gutters(props: Props) {
|
||||||
|
let currentLine = -1
|
||||||
const gutters = props.changes.map((change, key) => {
|
const gutters = props.changes.map((change, key) => {
|
||||||
return trimNewlineRight(change.value)
|
return trimNewlineRight(change.value)
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map((_, idx) => (
|
.map((_, idx) => {
|
||||||
|
currentLine = !change.removed ? currentLine + 1 : currentLine
|
||||||
|
return (
|
||||||
<div key={`${key}-${idx}`} style={lineChangeStyle(change)} className={props.classes.gutterLine}>
|
<div key={`${key}-${idx}`} style={lineChangeStyle(change)} className={props.classes.gutterLine}>
|
||||||
{change.added ? '+' : null}{change.removed ? '-' : null}{!change.added && !change.removed ? ' ' : null}
|
{tokensForLine(change, currentLine, props.literalPositions)}
|
||||||
</div>
|
</div>
|
||||||
))
|
)
|
||||||
|
})
|
||||||
}).reduce((a, b) => a.concat(b), [])
|
}).reduce((a, b) => a.concat(b), [])
|
||||||
|
|
||||||
return <div>{gutters}</div>
|
return <div>{gutters}</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import * as Prism from 'prismjs'
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import DiffCount from './DiffCount'
|
import DiffCount from './DiffCount'
|
||||||
import { CodeBlockColors, CodeBlockColorsBraceMonokai } from '../CodeBlockColors'
|
import { CodeBlockColors, CodeBlockColorsBraceMonokai } from '../CodeBlockColors'
|
||||||
import { literalsMappedByLines, parseJson } from '../../../../../backend/src/JsonAstParser'
|
import { literalsMappedByLines } from '../../../../../backend/src/JsonAstParser'
|
||||||
import { selectTextWithCtrlA } from '../../../utils/handleTextSelectWithCtrlA'
|
import { selectTextWithCtrlA } from '../../../utils/handleTextSelectWithCtrlA'
|
||||||
import { Theme, withStyles } from '@material-ui/core'
|
import { Theme, withStyles } from '@material-ui/core'
|
||||||
import 'prismjs/components/prism-json'
|
import 'prismjs/components/prism-json'
|
||||||
@@ -28,7 +28,7 @@ class CodeDiff extends React.Component<Props, {}> {
|
|||||||
public render() {
|
public render() {
|
||||||
const changes = diff.diffLines(this.props.previous, this.props.current)
|
const changes = diff.diffLines(this.props.previous, this.props.current)
|
||||||
const styledLines = Prism.highlight(this.props.current, Prism.languages.json, 'json').split('\n')
|
const styledLines = Prism.highlight(this.props.current, Prism.languages.json, 'json').split('\n')
|
||||||
const literalPositions = literalsMappedByLines(this.props.current)
|
const literalPositions = literalsMappedByLines(this.props.current) || []
|
||||||
|
|
||||||
let lineNumber = 0
|
let lineNumber = 0
|
||||||
const code = changes.map((change, key) => {
|
const code = changes.map((change, key) => {
|
||||||
@@ -78,6 +78,7 @@ const style = (theme: Theme) => {
|
|||||||
lineHeight: 'normal' as 'normal',
|
lineHeight: 'normal' as 'normal',
|
||||||
paddingLeft: '4px',
|
paddingLeft: '4px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
height: '16px',
|
||||||
},
|
},
|
||||||
codeWrapper: {
|
codeWrapper: {
|
||||||
maxHeight: '15em',
|
maxHeight: '15em',
|
||||||
|
|||||||
@@ -74,16 +74,24 @@ function jsonToPropertyPaths(ast: JsonAst, previousPath: Array<string> = []): Ar
|
|||||||
return children.reduce((a, b) => a.concat(b), [])
|
return children.reduce((a, b) => a.concat(b), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for testing only
|
||||||
export function parseJson(formattedJson: string): Array<JsonPropertyLocation> {
|
export function parseJson(formattedJson: string): Array<JsonPropertyLocation> {
|
||||||
return jsonToPropertyPaths((parse(formattedJson) as JsonAst), [])
|
const parsedJson = parse(formattedJson) as JsonAst
|
||||||
|
|
||||||
|
return jsonToPropertyPaths(parsedJson, [])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function literalsMappedByLines(formattedJson: string): Array<JsonPropertyLocation> {
|
export function literalsMappedByLines(formattedJson: string): Array<JsonPropertyLocation> | undefined {
|
||||||
const literals = jsonToPropertyPaths((parse(formattedJson) as JsonAst), [])
|
try {
|
||||||
|
const parsedJson = parse(formattedJson) as JsonAst
|
||||||
|
const literals = jsonToPropertyPaths(parsedJson, [])
|
||||||
const lines = []
|
const lines = []
|
||||||
for (const literal of literals) {
|
for (const literal of literals) {
|
||||||
lines[literal.line - 1] = literal
|
lines[literal.line - 1] = literal
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
} catch (error) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import 'mocha'
|
|
||||||
|
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { parseJson } from '../JsonAstParser'
|
import { parseJson } from '../JsonAstParser'
|
||||||
|
import 'mocha'
|
||||||
|
|
||||||
const dotProp = require('dot-prop')
|
const dotProp = require('dot-prop')
|
||||||
|
|
||||||
describe('access JSON values via dot property paths', () => {
|
describe('access JSON values via dot property paths', () => {
|
||||||
it('object with literal', () => {
|
it('object with literal', () => {
|
||||||
let data = {
|
const data = {
|
||||||
foo: 4,
|
foo: 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = parseJson(JSON.stringify(data, undefined, 2))
|
const result = parseJson(JSON.stringify(data, undefined, 2))
|
||||||
expect(result[0].path).to.eq('foo')
|
expect(result[0].path).to.eq('foo')
|
||||||
expect(result[0].line).to.eq(2)
|
expect(result[0].line).to.eq(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('nested object', () => {
|
it('nested object', () => {
|
||||||
let data = {
|
const data = {
|
||||||
foo: {
|
foo: {
|
||||||
bar: 4
|
bar: 4,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = parseJson(JSON.stringify(data, undefined, 2))
|
const result = parseJson(JSON.stringify(data, undefined, 2))
|
||||||
expect(result[0].path).to.eq('foo.bar')
|
expect(result[0].path).to.eq('foo.bar')
|
||||||
expect(result[0].line).to.eq(3)
|
expect(result[0].line).to.eq(3)
|
||||||
expect(dotProp.get(data, result[0].path)).to.eq(4)
|
expect(dotProp.get(data, result[0].path)).to.eq(4)
|
||||||
@@ -30,7 +30,7 @@ describe('access JSON values via dot property paths', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('array path', () => {
|
it('array path', () => {
|
||||||
let data = {
|
const data = {
|
||||||
foo: [
|
foo: [
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
@@ -38,11 +38,17 @@ describe('access JSON values via dot property paths', () => {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = parseJson(JSON.stringify(data, undefined, 2))
|
const result = parseJson(JSON.stringify(data, undefined, 2))
|
||||||
expect(result.length).to.eq(3)
|
expect(result.length).to.eq(3)
|
||||||
|
|
||||||
expect(result[2].path).to.eq('foo.2')
|
expect(result[2].path).to.eq('foo.2')
|
||||||
expect(result[2].line).to.eq(5)
|
expect(result[2].line).to.eq(5)
|
||||||
expect(dotProp.get(data, result[2].path)).to.eq(3)
|
expect(dotProp.get(data, result[2].path)).to.eq(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should fail parsing invalid json', () => {
|
||||||
|
expect(() => {
|
||||||
|
const result = parseJson("BLE2MQTT-8C48")
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user