pr_18393.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. diff --git a/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx b/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx
  2. index a0d681d9cb5..2f9a4333cd6 100644
  3. --- a/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx
  4. +++ b/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx
  5. @@ -17,6 +17,7 @@ import {
  6. import { Button, ControlLabel, FormControl, FormGroup } from 'react-bootstrap'
  7. import Icon from '../../../../shared/components/icon'
  8. import { EditorState } from '@codemirror/state'
  9. +import { openURL } from '@/features/source-editor/utils/url'
  10. export const HrefTooltipContent: FC = () => {
  11. const state = useCodeMirrorStateContext()
  12. @@ -108,7 +109,7 @@ export const HrefTooltipContent: FC = () => {
  13. className="ol-cm-command-tooltip-link"
  14. onClick={() => {
  15. // TODO: unescape content
  16. - window.open(url, '_blank')
  17. + openURL(url)
  18. }}
  19. >
  20. <Icon type="external-link" fw />
  21. diff --git a/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx b/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx
  22. index c51b497de01..632d71dd031 100644
  23. --- a/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx
  24. +++ b/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx
  25. @@ -9,6 +9,7 @@ import {
  26. } from '../../lezer-latex/latex.terms.mjs'
  27. import Icon from '../../../../shared/components/icon'
  28. import { EditorState } from '@codemirror/state'
  29. +import { openURL } from '@/features/source-editor/utils/url'
  30. export const UrlTooltipContent: FC = () => {
  31. const { t } = useTranslation()
  32. @@ -23,7 +24,7 @@ export const UrlTooltipContent: FC = () => {
  33. onClick={() => {
  34. const url = readUrl(state)
  35. if (url) {
  36. - window.open(url, '_blank')
  37. + openURL(url)
  38. }
  39. }}
  40. >
  41. diff --git a/services/web/frontend/js/features/source-editor/utils/url.ts b/services/web/frontend/js/features/source-editor/utils/url.ts
  42. new file mode 100644
  43. index 00000000000..8bfc9bdeab8
  44. --- /dev/null
  45. +++ b/services/web/frontend/js/features/source-editor/utils/url.ts
  46. @@ -0,0 +1,11 @@
  47. +const ALLOWED_PROTOCOLS = ['https:', 'http:']
  48. +
  49. +export const openURL = (content: string) => {
  50. + const url = new URL(content, document.location.href)
  51. +
  52. + if (!ALLOWED_PROTOCOLS.includes(url.protocol)) {
  53. + throw new Error(`Not opening URL with protocol ${url.protocol}`)
  54. + }
  55. +
  56. + window.open(url, '_blank')
  57. +}
  58. diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx
  59. index 837f90a64ab..d46b522a116 100644
  60. --- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx
  61. +++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx
  62. @@ -54,8 +54,8 @@ describe('<CodeMirrorEditor/> command tooltip in Visual mode', function () {
  63. // open the link
  64. cy.findByRole('button', { name: 'Go to page' }).click()
  65. cy.get('@window-open').should(
  66. - 'have.been.calledOnceWithExactly',
  67. - 'https://example.com',
  68. + 'have.been.calledWithMatch',
  69. + Cypress.sinon.match.has('href', 'https://example.com/'),
  70. '_blank'
  71. )
  72. @@ -112,8 +112,8 @@ describe('<CodeMirrorEditor/> command tooltip in Visual mode', function () {
  73. // open the link
  74. cy.findByRole('button', { name: 'Go to page' }).click()
  75. cy.get('@window-open').should(
  76. - 'have.been.calledOnceWithExactly',
  77. - 'https://example.com',
  78. + 'have.been.calledWithMatch',
  79. + Cypress.sinon.match.has('href', 'https://example.com/'),
  80. '_blank'
  81. )
  82. })
  83. diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx
  84. index c6e28f9eeeb..106a80ba187 100644
  85. --- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx
  86. +++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx
  87. @@ -42,8 +42,8 @@ describe('<CodeMirrorEditor/> tooltips in Visual mode', function () {
  88. })
  89. cy.findByRole('button', { name: 'Go to page' }).click()
  90. cy.get('@open-window').should(
  91. - 'have.been.calledOnceWithExactly',
  92. - 'https://example.com/foo',
  93. + 'have.been.calledWithMatch',
  94. + Cypress.sinon.match.has('href', 'https://example.com/foo'),
  95. '_blank'
  96. )
  97. cy.findByRole('button', { name: 'Remove link' }).click()
  98. @@ -62,8 +62,8 @@ describe('<CodeMirrorEditor/> tooltips in Visual mode', function () {
  99. })
  100. cy.findByRole('button', { name: 'Go to page' }).click()
  101. cy.get('@open-window').should(
  102. - 'have.been.calledOnceWithExactly',
  103. - 'https://example.com',
  104. + 'have.been.calledWithMatch',
  105. + Cypress.sinon.match.has('href', 'https://example.com/'),
  106. '_blank'
  107. )
  108. })