From 41d4daded7b569f39c768de893f6383d6b7b8b33 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 26 May 2022 06:46:50 -0700 Subject: [PATCH] Fix crash when using an inline svg Icon (#5450) --- src/renderer/components/icon/icon.tsx | 94 ++++++++++++++++++++++++--- types/mocks.d.ts | 6 +- webpack/renderer.ts | 2 +- 3 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/renderer/components/icon/icon.tsx b/src/renderer/components/icon/icon.tsx index 60cf06f9a6..084b75d804 100644 --- a/src/renderer/components/icon/icon.tsx +++ b/src/renderer/components/icon/icon.tsx @@ -12,7 +12,57 @@ import type { LocationDescriptor } from "history"; import { cssNames } from "../../utils"; import { withTooltip } from "../tooltip"; import isNumber from "lodash/isNumber"; -import { decode } from "../../../common/utils/base64"; +import Configuration from "./configuration.svg"; +import Crane from "./crane.svg"; +import Group from "./group.svg"; +import Helm from "./helm.svg"; +import Install from "./install.svg"; +import Kube from "./kube.svg"; +import LensLogo from "./lens-logo.svg"; +import License from "./license.svg"; +import LogoLens from "./logo-lens.svg"; +import Logout from "./logout.svg"; +import Nodes from "./nodes.svg"; +import PushOff from "./push_off.svg"; +import PushPin from "./push_pin.svg"; +import Spinner from "./spinner.svg"; +import Ssh from "./ssh.svg"; +import Storage from "./storage.svg"; +import Terminal from "./terminal.svg"; +import User from "./user.svg"; +import Users from "./users.svg"; +import Wheel from "./wheel.svg"; +import Workloads from "./workloads.svg"; + +/** + * Mapping between the local file names and the svgs + * + * Because we only really want a fixed list of bundled icons, this is safer so that consumers of + * `` cannot pass in a `../some/path`. + */ +const localSvgIcons = new Map([ + ["configuration", Configuration], + ["crane", Crane], + ["group", Group], + ["helm", Helm], + ["install", Install], + ["kube", Kube], + ["lens-logo", LensLogo], + ["license", License], + ["logo-lens", LogoLens], + ["logout", Logout], + ["nodes", Nodes], + ["push_off", PushOff], + ["push_pin", PushPin], + ["spinner", Spinner], + ["ssh", Ssh], + ["storage", Storage], + ["terminal", Terminal], + ["user", User], + ["users", Users], + ["wheel", Wheel], + ["workloads", Workloads], +]); export interface BaseIconProps { /** @@ -21,7 +71,28 @@ export interface BaseIconProps { material?: string; /** - * Either an SVG data URL or one of the following strings + * Either an SVG XML or one of the following names + * - configuration + * - crane + * - group + * - helm + * - install + * - kube + * - lens-logo + * - license + * - logo-lens + * - logout + * - nodes + * - push_off + * - push_pin + * - spinner + * - ssh + * - storage + * - terminal + * - user + * - users + * - wheel + * - workloads */ svg?: string; @@ -78,8 +149,8 @@ export interface BaseIconProps { export interface IconProps extends React.HTMLAttributes, BaseIconProps {} export function isSvg(content: string): boolean { - // data-url for raw svg-icon - return String(content).includes("svg+xml"); + // source code of the asset + return String(content).includes(" { @@ -131,13 +202,16 @@ const RawIcon = withTooltip((props: IconProps) => { // render as inline svg-icon if (typeof svg === "string") { - const dataUrlPrefix = "data:image/svg+xml;base64,"; - const svgIconDataUrl = svg.startsWith(dataUrlPrefix) ? svg : require(`./${svg}.svg`); - const svgIconText = typeof svgIconDataUrl == "string" // decode xml from data-url - ? decode(svgIconDataUrl.replace(dataUrlPrefix, "")) - : ""; + const svgIconText = isSvg(svg) + ? svg + : localSvgIcons.get(svg) ?? ""; - iconContent = ; + iconContent = ( + + ); } // render as material-icon diff --git a/types/mocks.d.ts b/types/mocks.d.ts index 17dba848b7..4d3e378937 100644 --- a/types/mocks.d.ts +++ b/types/mocks.d.ts @@ -25,7 +25,11 @@ declare module "*.scss" { // Declare everything what's bundled as webpack's type="asset/resource" // Should be mocked for tests support in jestConfig.moduleNameMapper (currently in "/package.json") -declare module "*.svg"; +declare module "*.svg" { + const content: string; + export = content; +} + declare module "*.jpg"; declare module "*.png"; declare module "*.eot"; diff --git a/webpack/renderer.ts b/webpack/renderer.ts index bb38b284d4..c8c87e856f 100755 --- a/webpack/renderer.ts +++ b/webpack/renderer.ts @@ -132,7 +132,7 @@ export function iconsAndImagesWebpackRules(): webpack.RuleSetRule[] { return [ { test: /\.svg$/, - type: "asset/inline", // data:image/svg+xml;base64,... + type: "asset/source", // exports the source code of the asset, so we get XML }, { test: /\.(jpg|png|ico)$/,