Skip to content

Commit

Permalink
Escape special characters in strings to render as expected for json
Browse files Browse the repository at this point in the history
  • Loading branch information
aaroncannoncv committed Oct 22, 2024
1 parent 392fa79 commit aa2fcb0
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 341 deletions.
23 changes: 22 additions & 1 deletion dev-server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,26 @@ ReactDom.render(
{/* Name as colored react component */}
<JsonViewer
collapsed
name={<span style={{color: "red", fontWeight: 800}}>React Element as name</span>}
name={
<span style={{ color: 'red', fontWeight: 800 }}>
React Element as name
</span>
}
src={getExampleJson2()}
/>

{/* String with special escape sequences */}
<JsonViewer
collapsed
name="String with special escape sequences"
src={getExampleWithStringEscapeSequences()}
onEdit={e => {
console.log('edit callback', e);
if (e.new_value == 'error') {
return false;
}
}}
/>
</div>,
document.getElementById('app-container')
);
Expand Down Expand Up @@ -292,3 +309,7 @@ function getExampleArray() {
}
];
}

function getExampleWithStringEscapeSequences() {
return { '\\\n\t\r\f\\n': '\\\n\t\r\f\\n' };
}
4 changes: 3 additions & 1 deletion src/js/components/DataTypes/String.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import DataTypeLabel from './DataTypeLabel';
import { toType } from './../../helpers/util';
import { toType, escapeString } from './../../helpers/util';

//theme
import Theme from './../../themes/getStyle';
Expand Down Expand Up @@ -46,6 +46,8 @@ export default class extends React.PureComponent {
let collapsible = toType(collapseStringsAfterLength) === 'integer';
let style = { style: { cursor: 'default' } };

value = escapeString(value);

if (collapsible && value.length > collapseStringsAfterLength) {
style.style.cursor = 'pointer';
if (this.state.collapsed) {
Expand Down
5 changes: 3 additions & 2 deletions src/js/components/VariableEditor.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import AutosizeTextarea from 'react-textarea-autosize';

import { toType } from './../helpers/util';
import { escapeString, toType } from './../helpers/util';
import dispatcher from './../helpers/dispatcher';
import parseInput from './../helpers/parseInput';
import stringifyVariable from './../helpers/stringifyVariable';
Expand Down Expand Up @@ -59,6 +59,7 @@ class VariableEditor extends React.PureComponent {
keyModifier
} = this.props;
const { editMode } = this.state;

return (
<div
{...Theme(theme, 'objectKeyVal', {
Expand Down Expand Up @@ -94,7 +95,7 @@ class VariableEditor extends React.PureComponent {
<span style={{ verticalAlign: 'top' }}>"</span>
)}
<span style={{ display: 'inline-block' }}>
{variable.name}
{escapeString(variable.name)}
</span>
{!!quotesOnKeys && (
<span style={{ verticalAlign: 'top' }}>"</span>
Expand Down
9 changes: 9 additions & 0 deletions src/js/helpers/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ function getType(obj) {
.toLowerCase();
}

export function escapeString(value) {
return value
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t')
.replace(/\r/g, '\\r')
.replace(/\f/g, '\\f');
}

//validation for base-16 themes
export function isTheme(theme) {
const theme_keys = [
Expand Down
104 changes: 57 additions & 47 deletions test/tests/js/components/DataTypes/String-test.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,80 @@
import React from "react"
import { shallow, mount } from "enzyme"
import { expect } from "chai"
import React from 'react';
import { shallow, mount } from 'enzyme';
import { expect } from 'chai';

import JsonString from "./../../../../../src/js/components/DataTypes/String"
import JsonString from './../../../../../src/js/components/DataTypes/String';

describe("<JsonString />", function() {
it("string component should have a data type label", function() {
const rjvId = 1
describe('<JsonString />', function () {
it('string component should have a data type label', function () {
const rjvId = 1;
const wrapper = mount(
<JsonString
value="test"
rjvId={rjvId}
displayDataTypes={true}
theme="rjv-default"
/>
)
expect(wrapper.find(".data-type-label")).to.have.length(1)
})
);
expect(wrapper.find('.data-type-label')).to.have.length(1);
});

it("string with hidden data type", function() {
const rjvId = 1
it('string with hidden data type', function () {
const rjvId = 1;
const props = {
value: "test",
value: 'test',
rjvId: 1,
theme: "rjv-default",
theme: 'rjv-default',
displayDataTypes: false
}
const component = mount(<JsonString {...props} />).render()
expect(component.find(".data-type-label")).to.have.length(0)
})
};
const component = mount(<JsonString {...props} />).render();
expect(component.find('.data-type-label')).to.have.length(0);
});

//test collapsed string and expand click
it("string displaying data type", function() {
const rjvId = 1
it('string displaying data type', function () {
const rjvId = 1;
const props = {
value: "test",
value: 'test',
rjvId: 1,
displayDataTypes: false,
theme: "rjv-default"
}
const component = mount(<JsonString {...props} />).render()
expect(component.find(".data-type-label")).to.have.length(0)
})
theme: 'rjv-default'
};
const component = mount(<JsonString {...props} />).render();
expect(component.find('.data-type-label')).to.have.length(0);
});

it("collapsed string content", function() {
const rjvId = 1
it('collapsed string content', function () {
const rjvId = 1;
const props = {
value: "123456789",
value: '123456789',
collapseStringsAfterLength: 3,
rjvId: 1,
displayDataTypes: false,
theme: "rjv-default"
}
const component = shallow(<JsonString {...props} />)
expect(
component
.render()
.find(".string-value")
.text()
).to.equal('"123 ..."')
component.find(".string-value").simulate("click")
expect(
component
.render()
.find(".string-value")
.text()
).to.equal('"123456789"')
})
})
theme: 'rjv-default'
};
const component = shallow(<JsonString {...props} />);
expect(component.render().find('.string-value').text()).to.equal(
'"123 ..."'
);
component.find('.string-value').simulate('click');
expect(component.render().find('.string-value').text()).to.equal(
'"123456789"'
);
});

//test rendering strings with special escape sequences

it('string with special escape sequences', function () {
const rjvId = 1;
const props = {
value: '\\\n\t\r\f\\n',
rjvId: 1,
displayDataTypes: false,
theme: 'rjv-default'
};
const component = mount(<JsonString {...props} />).render();
expect(component.find('.string-value').text()).to.equal(
'"\\\\\\n\\t\\r\\f\\\\n"'
);
});
});
Loading

0 comments on commit aa2fcb0

Please sign in to comment.