Custom component fixes (#9711)

* add code

* Add code

* add changeset

* compatible lockfile

* add code

* add changeset

* trigger-ci

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: pngwn <hello@pngwn.io>
This commit is contained in:
Freddy Boulton 2024-10-16 15:11:39 -07:00 committed by GitHub
parent f118587c25
commit 7134fc272e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 122 additions and 66 deletions

View File

@ -0,0 +1,9 @@
---
"@gradio/atoms": patch
"@gradio/markdown": patch
"@gradio/sanitize": patch
"@self/build": patch
"gradio": patch
---
fix:Custom component fixes

View File

@ -8,7 +8,8 @@
"license": "ISC",
"dependencies": {
"@gradio/icons": "workspace:^",
"@gradio/utils": "workspace:^"
"@gradio/utils": "workspace:^",
"@gradio/markdown": "workspace:^"
},
"peerDependencies": {
"svelte": "^4.0.0"

View File

@ -149,7 +149,8 @@ var ignore_list = [
"tooltip",
"upload",
"utils",
"wasm"
"wasm",
"sanitize"
];
function generate_component_imports() {
const exports = readdirSync(join(__dirname, "..", "..")).map((dir) => {

View File

@ -211,7 +211,8 @@ const ignore_list = [
"tooltip",
"upload",
"utils",
"wasm"
"wasm",
"sanitize"
];
function generate_component_imports(): string {
const exports = readdirSync(join(__dirname, "..", ".."))

View File

@ -26,10 +26,10 @@
"@gradio/icons": "workspace:^",
"@gradio/statustracker": "workspace:^",
"@gradio/utils": "workspace:^",
"@gradio/sanitize": "workspace:^",
"@types/dompurify": "^3.0.2",
"@types/katex": "^0.16.0",
"@types/prismjs": "1.26.4",
"amuchina": "^1.0.12",
"dom-parser": "^1.1.5",
"github-slugger": "^2.0.0",
"isomorphic-dompurify": "^2.14.0",
@ -37,12 +37,10 @@
"marked": "^12.0.0",
"marked-gfm-heading-id": "^3.1.2",
"marked-highlight": "^2.0.1",
"prismjs": "1.29.0",
"sanitize-html": "^2.13.0"
"prismjs": "1.29.0"
},
"devDependencies": {
"@gradio/preview": "workspace:^",
"@types/sanitize-html": "^2.13.0"
"@gradio/preview": "workspace:^"
},
"peerDependencies": {
"svelte": "^4.0.0"

View File

@ -3,8 +3,7 @@
import render_math_in_element from "katex/contrib/auto-render";
import "katex/dist/katex.min.css";
import { create_marked } from "./utils";
import sanitize_server from "sanitize-html";
import Amuchina from "amuchina";
import { sanitize } from "@gradio/sanitize";
import "./prism.css";
export let chatbot = true;
@ -29,52 +28,6 @@
latex_delimiters
});
const amuchina = new Amuchina();
const is_browser = typeof window !== "undefined";
let sanitize = is_browser ? sanitize_browser : sanitize_server;
function sanitize_browser(source: string): string {
const node = new DOMParser().parseFromString(source, "text/html");
walk_nodes(node.body, "A", (node) => {
if (node instanceof HTMLElement && "target" in node) {
if (is_external_url(node.getAttribute("href"))) {
node.setAttribute("target", "_blank");
node.setAttribute("rel", "noopener noreferrer");
}
}
});
return amuchina.sanitize(node).body.innerHTML;
}
function walk_nodes(
node: Node | null | HTMLElement,
test: string | ((node: Node | HTMLElement) => boolean),
callback: (node: Node | HTMLElement) => void
): void {
if (
node &&
((typeof test === "string" && node.nodeName === test) ||
(typeof test === "function" && test(node)))
) {
callback(node);
}
const children = node?.childNodes || [];
for (let i = 0; i < children.length; i++) {
// @ts-ignore
walk_nodes(children[i], test, callback);
}
}
const is_external_url = (link: string | null): boolean => {
try {
return !!link && new URL(link).origin !== new URL(root).origin;
} catch (e) {
return false;
}
};
function escapeRegExp(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
@ -106,7 +59,7 @@
}
if (sanitize_html && sanitize) {
parsedValue = sanitize(parsedValue);
parsedValue = sanitize(parsedValue, root);
}
return parsedValue;

43
js/sanitize/browser.ts Normal file
View File

@ -0,0 +1,43 @@
import Amuchina from "amuchina";
const is_external_url = (link: string | null, root: string): boolean => {
try {
return !!link && new URL(link).origin !== new URL(root).origin;
} catch (e) {
return false;
}
};
export function sanitize(source: string, root: string): string {
const amuchina = new Amuchina();
const node = new DOMParser().parseFromString(source, "text/html");
walk_nodes(node.body, "A", (node) => {
if (node instanceof HTMLElement && "target" in node) {
if (is_external_url(node.getAttribute("href"), root)) {
node.setAttribute("target", "_blank");
node.setAttribute("rel", "noopener noreferrer");
}
}
});
return amuchina.sanitize(node).body.innerHTML;
}
function walk_nodes(
node: Node | null | HTMLElement,
test: string | ((node: Node | HTMLElement) => boolean),
callback: (node: Node | HTMLElement) => void
): void {
if (
node &&
((typeof test === "string" && node.nodeName === test) ||
(typeof test === "function" && test(node)))
) {
callback(node);
}
const children = node?.childNodes || [];
for (let i = 0; i < children.length; i++) {
// @ts-ignore
walk_nodes(children[i], test, callback);
}
}

1
js/sanitize/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export declare function sanitize(source: string, root: string): string;

34
js/sanitize/package.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "@gradio/sanitize",
"version": "0.1.0",
"description": "Gradio UI packages",
"type": "module",
"author": "",
"main": "./dist/server.js",
"license": "ISC",
"dependencies": {
"sanitize-html": "^2.13.0",
"amuchina": "^1.0.12"
},
"devDependencies": {
"@types/sanitize-html": "^2.13.0"
},
"main_changeset": true,
"repository": {
"type": "git",
"url": "git+https://github.com/gradio-app/gradio.git",
"directory": "js/utils"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"browser": "./dist/browser.js",
"import": "./dist/server.js",
"default": "./dist/server.js"
},
"./package.json": "./package.json"
},
"scripts": {
"package": "svelte-package --input=. --cwd=../../.config/"
}
}

5
js/sanitize/server.ts Normal file
View File

@ -0,0 +1,5 @@
import { default as sanitize_html_ } from "sanitize-html";
export function sanitize(source: string, root: string): string {
return sanitize_html_(source);
}

View File

@ -625,6 +625,9 @@ importers:
'@gradio/icons':
specifier: workspace:^
version: link:../icons
'@gradio/markdown':
specifier: workspace:^
version: link:../markdown
'@gradio/utils':
specifier: workspace:^
version: link:../utils
@ -1669,6 +1672,9 @@ importers:
'@gradio/icons':
specifier: workspace:^
version: link:../icons
'@gradio/sanitize':
specifier: workspace:^
version: link:../sanitize
'@gradio/statustracker':
specifier: workspace:^
version: link:../statustracker
@ -1684,9 +1690,6 @@ importers:
'@types/prismjs':
specifier: 1.26.4
version: 1.26.4
amuchina:
specifier: ^1.0.12
version: 1.0.12
dom-parser:
specifier: ^1.1.5
version: 1.1.5
@ -1711,9 +1714,6 @@ importers:
prismjs:
specifier: 1.29.0
version: 1.29.0
sanitize-html:
specifier: ^2.13.0
version: 2.13.0
svelte:
specifier: ^4.0.0
version: 4.2.15
@ -1721,9 +1721,6 @@ importers:
'@gradio/preview':
specifier: workspace:^
version: link:../preview
'@types/sanitize-html':
specifier: ^2.13.0
version: 2.13.0
js/model3D:
dependencies:
@ -2034,6 +2031,19 @@ importers:
specifier: workspace:^
version: link:../utils
js/sanitize:
dependencies:
amuchina:
specifier: ^1.0.12
version: 1.0.12
sanitize-html:
specifier: ^2.13.0
version: 2.13.0
devDependencies:
'@types/sanitize-html':
specifier: ^2.13.0
version: 2.13.0
js/simpledropdown:
dependencies:
'@gradio/atoms':