1
0
mirror of https://github.com/lensapp/lens.git synced 2024-09-20 05:47:24 +03:00

Fix crash when using an inline svg Icon (#5450)

This commit is contained in:
Sebastian Malton 2022-05-26 06:46:50 -07:00 committed by GitHub
parent c8cf300e9b
commit 41d4daded7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 12 deletions

View File

@ -12,7 +12,57 @@ import type { LocationDescriptor } from "history";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";
import { withTooltip } from "../tooltip"; import { withTooltip } from "../tooltip";
import isNumber from "lodash/isNumber"; 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
* `<Icon>` 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 { export interface BaseIconProps {
/** /**
@ -21,7 +71,28 @@ export interface BaseIconProps {
material?: string; 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; svg?: string;
@ -78,8 +149,8 @@ export interface BaseIconProps {
export interface IconProps extends React.HTMLAttributes<any>, BaseIconProps {} export interface IconProps extends React.HTMLAttributes<any>, BaseIconProps {}
export function isSvg(content: string): boolean { export function isSvg(content: string): boolean {
// data-url for raw svg-icon // source code of the asset
return String(content).includes("svg+xml"); return String(content).includes("<svg");
} }
const RawIcon = withTooltip((props: IconProps) => { const RawIcon = withTooltip((props: IconProps) => {
@ -131,13 +202,16 @@ const RawIcon = withTooltip((props: IconProps) => {
// render as inline svg-icon // render as inline svg-icon
if (typeof svg === "string") { if (typeof svg === "string") {
const dataUrlPrefix = "data:image/svg+xml;base64,"; const svgIconText = isSvg(svg)
const svgIconDataUrl = svg.startsWith(dataUrlPrefix) ? svg : require(`./${svg}.svg`); ? svg
const svgIconText = typeof svgIconDataUrl == "string" // decode xml from data-url : localSvgIcons.get(svg) ?? "";
? decode(svgIconDataUrl.replace(dataUrlPrefix, ""))
: "";
iconContent = <span className="icon" dangerouslySetInnerHTML={{ __html: svgIconText }} />; iconContent = (
<span
className="icon"
dangerouslySetInnerHTML={{ __html: svgIconText }}
/>
);
} }
// render as material-icon // render as material-icon

6
types/mocks.d.ts vendored
View File

@ -25,7 +25,11 @@ declare module "*.scss" {
// Declare everything what's bundled as webpack's type="asset/resource" // Declare everything what's bundled as webpack's type="asset/resource"
// Should be mocked for tests support in jestConfig.moduleNameMapper (currently in "/package.json") // 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 "*.jpg";
declare module "*.png"; declare module "*.png";
declare module "*.eot"; declare module "*.eot";

View File

@ -132,7 +132,7 @@ export function iconsAndImagesWebpackRules(): webpack.RuleSetRule[] {
return [ return [
{ {
test: /\.svg$/, 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)$/, test: /\.(jpg|png|ico)$/,