diff --git a/.eslintrc.json b/.eslintrc.json index 8263b08a9..89f822736 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -32,6 +32,12 @@ "name": "jotai", "message": "Do not import from \"jotai\" directly. Use our app-specific modules (\"editor-jotai\" or \"app-jotai\")." } + ], + "react/jsx-no-target-blank": [ + "error", + { + "allowReferrer": true + } ] } } diff --git a/excalidraw-app/components/AI.tsx b/excalidraw-app/components/AI.tsx index 4469d74f6..9a222a968 100644 --- a/excalidraw-app/components/AI.tsx +++ b/excalidraw-app/components/AI.tsx @@ -73,7 +73,7 @@ export const AIComponents = ({
You can also try Excalidraw+ to get more requests.
+ }/plus?utm_source=excalidraw&utm_medium=app&utm_content=d2c" target="_blank" rel="noopener">Excalidraw+ to get more requests. `, diff --git a/excalidraw-app/components/EncryptedIcon.tsx b/excalidraw-app/components/EncryptedIcon.tsx index 552e7ca82..f7d8ca601 100644 --- a/excalidraw-app/components/EncryptedIcon.tsx +++ b/excalidraw-app/components/EncryptedIcon.tsx @@ -10,7 +10,7 @@ export const EncryptedIcon = () => { className="encrypted-icon tooltip" href="https://plus.excalidraw.com/blog/end-to-end-encryption" target="_blank" - rel="noopener noreferrer" + rel="noopener" aria-label={t("encrypted.link")} > diff --git a/excalidraw-app/components/ExcalidrawPlusAppLink.tsx b/excalidraw-app/components/ExcalidrawPlusAppLink.tsx index 76be9a8f0..04cd96302 100644 --- a/excalidraw-app/components/ExcalidrawPlusAppLink.tsx +++ b/excalidraw-app/components/ExcalidrawPlusAppLink.tsx @@ -10,7 +10,7 @@ export const ExcalidrawPlusAppLink = () => { import.meta.env.VITE_APP_PLUS_APP }?utm_source=excalidraw&utm_medium=app&utm_content=signedInUserRedirectButton#excalidraw-redirect`} target="_blank" - rel="noreferrer" + rel="noopener" className="plus-button" > Go to Excalidraw+ diff --git a/excalidraw-app/tests/__snapshots__/MobileMenu.test.tsx.snap b/excalidraw-app/tests/__snapshots__/MobileMenu.test.tsx.snap index 77fc14757..53b16c40f 100644 --- a/excalidraw-app/tests/__snapshots__/MobileMenu.test.tsx.snap +++ b/excalidraw-app/tests/__snapshots__/MobileMenu.test.tsx.snap @@ -198,7 +198,7 @@ exports[`Test MobileMenu > should initialize with welcome screen and hide once u
( className="HelpDialog__btn" href="https://docs.excalidraw.com" target="_blank" - rel="noopener noreferrer" + rel="noopener" >
{ExternalLinkIcon}
{t("helpDialog.documentation")} @@ -30,7 +30,7 @@ const Header = () => ( className="HelpDialog__btn" href="https://plus.excalidraw.com/blog" target="_blank" - rel="noopener noreferrer" + rel="noopener" >
{ExternalLinkIcon}
{t("helpDialog.blog")} diff --git a/packages/excalidraw/components/PublishLibrary.tsx b/packages/excalidraw/components/PublishLibrary.tsx index c1db91296..580b909d4 100644 --- a/packages/excalidraw/components/PublishLibrary.tsx +++ b/packages/excalidraw/components/PublishLibrary.tsx @@ -389,7 +389,7 @@ const PublishLibrary = ({
{el} diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx index 1457f5ae7..d4f549c84 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx @@ -16,7 +16,7 @@ const DropdownMenuItemLink = ({ onSelect, className = "", selected, - rel = "noreferrer", + rel = "noopener", ...rest }: { href: string; @@ -31,11 +31,12 @@ const DropdownMenuItemLink = ({ const handleClick = useHandleDropdownMenuItemClick(rest.onClick, onSelect); return ( + // eslint-disable-next-line react/jsx-no-target-blank {children} diff --git a/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap index bbcc8d7e0..bb87746c0 100644 --- a/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap @@ -21,7 +21,7 @@ exports[` > > should render main menu with host menu it
> Test UIOptions prop > Test canvasActions > should rende aria-label="GitHub" class="dropdown-menu-item dropdown-menu-item-base" href="https://github.com/excalidraw/excalidraw" - rel="noreferrer" + rel="noopener" target="_blank" title="GitHub" > @@ -426,7 +426,7 @@ exports[` > Test UIOptions prop > Test canvasActions > should rende aria-label="X" class="dropdown-menu-item dropdown-menu-item-base" href="https://x.com/excalidraw" - rel="noreferrer" + rel="noopener" target="_blank" title="X" > @@ -472,7 +472,7 @@ exports[` > Test UIOptions prop > Test canvasActions > should rende aria-label="Discord" class="dropdown-menu-item dropdown-menu-item-base" href="https://discord.gg/UexuTaE" - rel="noreferrer" + rel="noopener" target="_blank" title="Discord" > diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 44dba2e34..680cd82d5 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -171,7 +171,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 19, + "version": 9, "width": 100, "x": 100, "y": -50, @@ -198,7 +198,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "102.35417", + "height": "102.45605", "id": "id172", "index": "a2", "isDeleted": false, @@ -212,8 +212,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - "101.77517", - "102.35417", + "102.80179", + "102.45605", ], ], "roughness": 1, @@ -227,9 +227,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 40, - "width": "101.77517", - "x": "0.70711", + "version": 37, + "width": "102.80179", + "x": "-0.42182", "y": 0, } `; @@ -264,7 +264,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 14, "width": 50, "x": 100, "y": 100, @@ -291,22 +291,39 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { + "id171" => Delta { + "deleted": { + "boundElements": [], + }, + "inserted": { + "boundElements": [ + { + "id": "id172", + "type": "arrow", + }, + ], + }, + }, "id172" => Delta { "deleted": { "endBinding": { - "elementId": "id171", - "focus": "0.00990", + "elementId": "id175", + "fixedPoint": [ + "0.50000", + 1, + ], + "focus": 0, "gap": 1, }, - "height": "0.98586", + "height": "70.45017", "points": [ [ 0, 0, ], [ - "98.58579", - "-0.98586", + "100.70774", + "70.45017", ], ], "startBinding": { @@ -321,7 +338,7 @@ History { "focus": "-0.02000", "gap": 1, }, - "height": "0.00000", + "height": "0.09250", "points": [ [ 0, @@ -329,7 +346,7 @@ History { ], [ "98.58579", - "0.00000", + "0.09250", ], ], "startBinding": { @@ -339,6 +356,19 @@ History { }, }, }, + "id175" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id172", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, }, }, }, @@ -366,59 +396,32 @@ History { ], }, }, - "id171" => Delta { - "deleted": { - "boundElements": [], - }, - "inserted": { - "boundElements": [ - { - "id": "id172", - "type": "arrow", - }, - ], - }, - }, "id172" => Delta { "deleted": { - "endBinding": { - "elementId": "id175", - "fixedPoint": [ - "0.50000", - 1, - ], - "focus": 0, - "gap": 1, - }, - "height": "102.35417", + "height": "102.45584", "points": [ [ 0, 0, ], [ - "101.77517", - "102.35417", + "102.79971", + "102.45584", ], ], "startBinding": null, "y": 0, }, "inserted": { - "endBinding": { - "elementId": "id171", - "focus": "0.00990", - "gap": 1, - }, - "height": "0.98586", + "height": "70.33521", "points": [ [ 0, 0, ], [ - "98.58579", - "-0.98586", + "100.78887", + "70.33521", ], ], "startBinding": { @@ -426,20 +429,7 @@ History { "focus": "0.02970", "gap": 1, }, - "y": "0.99364", - }, - }, - "id175" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id172", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], + "y": "35.20327", }, }, }, @@ -739,7 +729,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 9, + "version": 19, "width": 100, "x": 150, "y": -50, @@ -819,8 +809,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 30, - "width": 0, + "version": 33, + "width": 100, "x": "149.29289", "y": 0, } @@ -846,20 +836,22 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id167" => Delta { + "id166" => Delta { "deleted": { - "points": [ - [ - 0, - 0, - ], - [ - 0, - 0, - ], - ], + "boundElements": [], }, "inserted": { + "boundElements": [ + { + "id": "id167", + "type": "arrow", + }, + ], + }, + }, + "id167" => Delta { + "deleted": { + "endBinding": null, "points": [ [ 0, @@ -871,6 +863,23 @@ History { ], ], }, + "inserted": { + "endBinding": { + "elementId": "id166", + "focus": -0, + "gap": 1, + }, + "points": [ + [ + 0, + 0, + ], + [ + 0, + 0, + ], + ], + }, }, }, }, @@ -899,22 +908,8 @@ History { ], }, }, - "id166" => Delta { - "deleted": { - "boundElements": [], - }, - "inserted": { - "boundElements": [ - { - "id": "id167", - "type": "arrow", - }, - ], - }, - }, "id167" => Delta { "deleted": { - "endBinding": null, "points": [ [ 0, @@ -928,18 +923,13 @@ History { "startBinding": null, }, "inserted": { - "endBinding": { - "elementId": "id166", - "focus": -0, - "gap": 1, - }, "points": [ [ 0, 0, ], [ - 0, + 100, 0, ], ],