Skip to content

Commit ad86f7a

Browse files
xitij2000farhaanbukhsh
authored andcommitted
fix: add handling for alt text with quotes and escaping in propsString
1 parent 27db8f6 commit ad86f7a

4 files changed

Lines changed: 28 additions & 11 deletions

File tree

src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ describe('ImageSettingsModal', () => {
7070
expect(screen.queryByText(messages.altTextError.defaultMessage)).not.toBeInTheDocument();
7171
expect(props.saveToEditor).toHaveBeenCalled();
7272
});
73+
test('It passes alt text containing quotes through to saveToEditor', async () => {
74+
render(<ImageSettingsModal {...props} />);
75+
const altTextBox = screen.getByRole('textbox', { name: /alt text/i });
76+
await user.clear(altTextBox);
77+
await user.type(altTextBox, 'some text that "has quotes"');
78+
await user.click(screen.getByRole('button', { name: 'Save' }));
79+
expect(props.saveToEditor).toHaveBeenCalledWith(
80+
expect.objectContaining({ altText: 'some text that "has quotes"' }),
81+
);
82+
});
7383
});
7484
describe('Image Dimensions Editing', () => {
7585
function mockImageLoad(naturalWidth, naturalHeight) {

src/editors/sharedComponents/ImageUploadModal/index.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import * as module from '.';
1212
import { updateImageDimensions } from '../TinyMceWidget/hooks';
1313

1414
export const propsString = (props) => (
15-
Object.keys(props).map((key) => `${key}="${props[key]}"`).join(' ')
15+
Object.keys(props)
16+
.map((key) => `${key}="${String(props[key]).replace(/"/g, '&quot;')}"`)
17+
.join(' ')
1618
);
1719

1820
export const imgProps = ({

src/editors/sharedComponents/ImageUploadModal/index.test.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ describe('ImageUploadModal', () => {
5757
alt: settings.altText,
5858
width: settings.dimensions.width,
5959
height: settings.dimensions.height,
60-
class: ''
60+
class: '',
6161
};
62-
const testImgTag = ({expected, settings}) => {
62+
const testImgTag = ({ expected, settings }) => {
6363
const output = hooks.imgTag({
6464
settings,
6565
selection,
@@ -70,13 +70,13 @@ describe('ImageUploadModal', () => {
7070
expect(output).toEqual(`<img ${propsString(expected)} />`);
7171
};
7272
test.each([
73-
[ settings, expected ],
74-
[ {...settings, isDecorative: true}, {...expected, alt: ''} ],
75-
[ {...settings, classList: []}, {...expected} ],
76-
[ {...settings, classList: null}, {...expected} ],
77-
[ {...settings, classList: undefined}, {...expected} ],
78-
[ {...settings, classList: ['class1', 'class2']}, {...expected, class: 'class1 class2'} ],
79-
[ {...settings, title: "some title"}, {...expected, title: 'some title'} ],
73+
[settings, expected],
74+
[{ ...settings, isDecorative: true }, { ...expected, alt: '' }],
75+
[{ ...settings, classList: [] }, { ...expected }],
76+
[{ ...settings, classList: null }, { ...expected }],
77+
[{ ...settings, classList: undefined }, { ...expected }],
78+
[{ ...settings, classList: ['class1', 'class2'] }, { ...expected, class: 'class1 class2' }],
79+
[{ ...settings, title: 'some title' }, { ...expected, title: 'some title' }],
8080
])('It returns a html string which matches an image tag', (settings, expected) => {
8181
testImgTag({ settings, expected });
8282
});
@@ -195,4 +195,9 @@ describe('ImageUploadModal', () => {
195195
expect(container.querySelector('SelectImageModal')).toBeInTheDocument();
196196
});
197197
});
198+
describe('propsString', () => {
199+
it('escapes double quotes in attribute values', () => {
200+
expect(propsString({ alt: 'some "quoted" text' })).toEqual('alt="some &quot;quoted&quot; text"');
201+
});
202+
});
198203
});

src/editors/sharedComponents/TinyMceWidget/hooks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import pluginConfig from './pluginConfig';
1414

1515
import * as tinyMCE from '../../data/constants/tinyMCE';
1616
import { getRelativeUrl, getStaticUrl, parseAssetName } from './utils';
17-
import { isLibraryKey } from '../../../generic/key-utils';
17+
import { isLibraryKey } from '@src/generic/key-utils';
1818

1919
export const state = StrictDict({
2020
// eslint-disable-next-line react-hooks/rules-of-hooks

0 commit comments

Comments
 (0)