mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
fix: hyperlinks html entities (#9063)
This commit is contained in:
parent
52eaf64591
commit
a3e1619635
5 changed files with 15 additions and 30 deletions
|
@ -25,7 +25,7 @@ describe("normalizeLink", () => {
|
||||||
expect(normalizeLink("file://")).toBe("file://");
|
expect(normalizeLink("file://")).toBe("file://");
|
||||||
expect(normalizeLink("[test](https://test)")).toBe("[test](https://test)");
|
expect(normalizeLink("[test](https://test)")).toBe("[test](https://test)");
|
||||||
expect(normalizeLink("[[test]]")).toBe("[[test]]");
|
expect(normalizeLink("[[test]]")).toBe("[[test]]");
|
||||||
expect(normalizeLink("<test>")).toBe("<test>");
|
expect(normalizeLink("<test>")).toBe("<test>");
|
||||||
expect(normalizeLink("test&")).toBe("test&");
|
expect(normalizeLink("test&")).toBe("test&");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { sanitizeUrl } from "@braintree/sanitize-url";
|
import { sanitizeUrl } from "@braintree/sanitize-url";
|
||||||
import { sanitizeHTMLAttribute } from "../utils";
|
import { escapeDoubleQuotes } from "../utils";
|
||||||
|
|
||||||
export const normalizeLink = (link: string) => {
|
export const normalizeLink = (link: string) => {
|
||||||
link = link.trim();
|
link = link.trim();
|
||||||
if (!link) {
|
if (!link) {
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
return sanitizeUrl(sanitizeHTMLAttribute(link));
|
return sanitizeUrl(escapeDoubleQuotes(link));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isLocalLink = (link: string | null) => {
|
export const isLocalLink = (link: string | null) => {
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import { register } from "../actions/register";
|
import { register } from "../actions/register";
|
||||||
import { FONT_FAMILY, VERTICAL_ALIGN } from "../constants";
|
import { FONT_FAMILY, VERTICAL_ALIGN } from "../constants";
|
||||||
import type { ExcalidrawProps } from "../types";
|
import type { ExcalidrawProps } from "../types";
|
||||||
import {
|
import { escapeDoubleQuotes, getFontString, updateActiveTool } from "../utils";
|
||||||
getFontString,
|
|
||||||
sanitizeHTMLAttribute,
|
|
||||||
updateActiveTool,
|
|
||||||
} from "../utils";
|
|
||||||
import { setCursorForShape } from "../cursor";
|
import { setCursorForShape } from "../cursor";
|
||||||
import { newTextElement } from "./newElement";
|
import { newTextElement } from "./newElement";
|
||||||
import { wrapText } from "./textWrapping";
|
import { wrapText } from "./textWrapping";
|
||||||
|
@ -212,7 +208,7 @@ export const getEmbedLink = (
|
||||||
// Note that we don't attempt to parse the username as it can consist of
|
// Note that we don't attempt to parse the username as it can consist of
|
||||||
// non-latin1 characters, and the username in the url can be set to anything
|
// non-latin1 characters, and the username in the url can be set to anything
|
||||||
// without affecting the embed.
|
// without affecting the embed.
|
||||||
const safeURL = sanitizeHTMLAttribute(
|
const safeURL = escapeDoubleQuotes(
|
||||||
`https://twitter.com/x/status/${postId}`,
|
`https://twitter.com/x/status/${postId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -231,7 +227,7 @@ export const getEmbedLink = (
|
||||||
|
|
||||||
if (RE_REDDIT.test(link)) {
|
if (RE_REDDIT.test(link)) {
|
||||||
const [, page, postId, title] = link.match(RE_REDDIT)!;
|
const [, page, postId, title] = link.match(RE_REDDIT)!;
|
||||||
const safeURL = sanitizeHTMLAttribute(
|
const safeURL = escapeDoubleQuotes(
|
||||||
`https://reddit.com/r/${page}/comments/${postId}/${title}`,
|
`https://reddit.com/r/${page}/comments/${postId}/${title}`,
|
||||||
);
|
);
|
||||||
const ret: IframeDataWithSandbox = {
|
const ret: IframeDataWithSandbox = {
|
||||||
|
@ -249,7 +245,7 @@ export const getEmbedLink = (
|
||||||
|
|
||||||
if (RE_GH_GIST.test(link)) {
|
if (RE_GH_GIST.test(link)) {
|
||||||
const [, user, gistId] = link.match(RE_GH_GIST)!;
|
const [, user, gistId] = link.match(RE_GH_GIST)!;
|
||||||
const safeURL = sanitizeHTMLAttribute(
|
const safeURL = escapeDoubleQuotes(
|
||||||
`https://gist.github.com/${user}/${gistId}`,
|
`https://gist.github.com/${user}/${gistId}`,
|
||||||
);
|
);
|
||||||
const ret: IframeDataWithSandbox = {
|
const ret: IframeDataWithSandbox = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isTransparent, sanitizeHTMLAttribute } from "../utils";
|
import { isTransparent } from "../utils";
|
||||||
|
|
||||||
describe("Test isTransparent", () => {
|
describe("Test isTransparent", () => {
|
||||||
it("should return true when color is rgb transparent", () => {
|
it("should return true when color is rgb transparent", () => {
|
||||||
|
@ -11,9 +11,3 @@ describe("Test isTransparent", () => {
|
||||||
expect(isTransparent("#ced4da")).toEqual(false);
|
expect(isTransparent("#ced4da")).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("sanitizeHTMLAttribute()", () => {
|
|
||||||
it("should escape HTML attribute special characters & not double escape", () => {
|
|
||||||
expect(sanitizeHTMLAttribute(`&"'><`)).toBe("&"'><");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -1226,15 +1226,10 @@ export class PromisePool<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sanitizeHTMLAttribute = (html: string) => {
|
/**
|
||||||
return (
|
* use when you need to render unsafe string as HTML attribute, but MAKE SURE
|
||||||
html
|
* the attribute is double-quoted when constructing the HTML string
|
||||||
// note, if we're not doing stupid things, escaping " is enough,
|
*/
|
||||||
// but we might end up doing stupid things
|
export const escapeDoubleQuotes = (str: string) => {
|
||||||
.replace(/&/g, "&")
|
return str.replace(/"/g, """);
|
||||||
.replace(/"/g, """)
|
|
||||||
.replace(/'/g, "'")
|
|
||||||
.replace(/>/g, ">")
|
|
||||||
.replace(/</g, "<")
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue