[visual] Escape special characters in pasted URLs (#14789)

GitOrigin-RevId: 58e0b4b9b902301dbcb34f918ebbfdad0c8a763f
This commit is contained in:
Alf Eaton 2023-09-14 09:17:18 +01:00 committed by Copybot
parent 496b30e18e
commit 875ea723ca
3 changed files with 34 additions and 3 deletions

View file

@ -102,6 +102,7 @@ export const HrefTooltipContent: FC = () => {
bsStyle="link"
className="ol-cm-command-tooltip-link"
onClick={() => {
// TODO: unescape content
window.open(url, '_blank')
}}
>

View file

@ -217,6 +217,25 @@ const matchingParents = (element: HTMLElement, selector: string) => {
return matches
}
const urlCharacterReplacements = new Map<string, string>([
['\\', '\\\\'],
['#', '\\#'],
['%', '\\%'],
['{', '%7B'],
['}', '%7D'],
])
const protectUrlCharacters = (url: string) => {
// NOTE: add new characters to both this regex and urlCharacterReplacements
return url.replaceAll(/[\\#%{}]/g, match => {
const replacement = urlCharacterReplacements.get(match)
if (!replacement) {
throw new Error(`No replacement found for ${match}`)
}
return replacement
})
}
const processLists = (element: HTMLElement) => {
for (const list of element.querySelectorAll('ol,ul')) {
// if the list has only one item, replace the list with an element containing the contents of the item
@ -519,8 +538,11 @@ const selectors = [
createSelector({
selector: 'a',
match: element => !!element.href && hasContent(element),
start: (element: HTMLAnchorElement) => `\\href{${element.href}}{`,
end: element => `}`,
start: (element: HTMLAnchorElement) => {
const url = protectUrlCharacters(element.href)
return `\\href{${url}}{`
},
end: () => `}`,
}),
createSelector({
selector: 'h1',

View file

@ -277,7 +277,8 @@ describe('<CodeMirrorEditor/> paste HTML in Visual mode', function () {
it('handles a pasted link', function () {
mountEditor()
const data = '<a href="https://example.com/">foo</a>'
const data =
'<a href="https://example.com/?q=$foo_~bar&x=\\bar#fragment{y}%2">foo</a>'
const clipboardData = new DataTransfer()
clipboardData.setData('text/html', data)
@ -285,6 +286,13 @@ describe('<CodeMirrorEditor/> paste HTML in Visual mode', function () {
cy.get('@content').should('have.text', '{foo}')
cy.get('.ol-cm-command-href').should('have.length', 1)
cy.get('.cm-line').eq(0).type('{leftArrow}')
cy.findByLabelText('URL').should(
'have.value',
'https://example.com/?q=$foo_~bar&x=\\\\bar\\#fragment%7By%7D\\%2'
)
// TODO: assert that the "Go to page" link has been unescaped
})
it('handles a pasted code block', function () {