2
0
mirror of https://github.com/iconify/iconify.git synced 2024-11-08 14:20:57 +00:00

feat: support require-trusted-types-for policy

This commit is contained in:
Vjacheslav Trushkin 2023-06-22 11:50:27 +03:00
parent 7bec9456c8
commit 39868cf79c
16 changed files with 85 additions and 25 deletions

View File

@ -4,7 +4,11 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title> <meta
http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script';"
/>
<title>React Demo</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@ -2,7 +2,7 @@
"name": "@iconify/react", "name": "@iconify/react",
"description": "Iconify icon component for React.", "description": "Iconify icon component for React.",
"author": "Vjacheslav Trushkin", "author": "Vjacheslav Trushkin",
"version": "4.1.0", "version": "4.1.1",
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/iconify/iconify/issues", "bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/", "homepage": "https://iconify.design/",

View File

@ -8,6 +8,7 @@ import { iconToSVG } from '@iconify/utils/lib/svg/build';
import { replaceIDs } from '@iconify/utils/lib/svg/id'; import { replaceIDs } from '@iconify/utils/lib/svg/id';
import { iconToHTML } from '@iconify/utils/lib/svg/html'; import { iconToHTML } from '@iconify/utils/lib/svg/html';
import { svgToURL } from '@iconify/utils/lib/svg/url'; import { svgToURL } from '@iconify/utils/lib/svg/url';
import { cleanUpInnerHTML } from '@iconify/utils/lib/svg/inner-html';
import type { import type {
IconifyIconCustomisations, IconifyIconCustomisations,
IconifyRenderMode, IconifyRenderMode,
@ -48,7 +49,7 @@ const propsToAdd: Record<string, string> = {
Size: '100% 100%', Size: '100% 100%',
}; };
const propsToAddTo: Record<string, Record<string, string>> = { const propsToAddTo: Record<string, Record<string, string>> = {
webkitMask: monotoneProps, WebkitMask: monotoneProps,
mask: monotoneProps, mask: monotoneProps,
background: coloredProps, background: coloredProps,
}; };
@ -202,9 +203,11 @@ export const render = (
// Add icon stuff // Add icon stuff
componentProps.dangerouslySetInnerHTML = { componentProps.dangerouslySetInnerHTML = {
__html: replaceIDs( __html: cleanUpInnerHTML(
replaceIDs(
item.body, item.body,
id ? () => id + 'ID' + localCounter++ : 'iconifyReact' id ? () => id + 'ID' + localCounter++ : 'iconifyReact'
)
), ),
}; };
return React.createElement('svg', componentProps); return React.createElement('svg', componentProps);

View File

@ -21,13 +21,13 @@ Iconify SVG framework is designed to be as easy to use as possible.
Add this line to your page to load Iconify SVG framework (you can add it to `<head>` section of the page or before `</body>`): Add this line to your page to load Iconify SVG framework (you can add it to `<head>` section of the page or before `</body>`):
```html ```html
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script> <script src="https://code.iconify.design/3/3.1.1/iconify.min.js"></script>
``` ```
or or
```html ```html
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@3.1.0/dist/iconify.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@3.1.1/dist/iconify.min.js"></script>
``` ```
or, if you are building a project with something like WebPack or Rollup, you can include the script by installing `@iconify/iconify` as a dependency and importing it in your project: or, if you are building a project with something like WebPack or Rollup, you can include the script by installing `@iconify/iconify` as a dependency and importing it in your project:

View File

@ -3,6 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script';"
/>
<title>Iconify Demo: Usage</title> <title>Iconify Demo: Usage</title>
<style> <style>
html, html,

View File

@ -2,7 +2,7 @@
"name": "@iconify/iconify", "name": "@iconify/iconify",
"description": "Unified SVG framework with over 100,000 icons to choose from", "description": "Unified SVG framework with over 100,000 icons to choose from",
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)", "author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
"version": "3.1.0", "version": "3.1.1",
"license": "MIT", "license": "MIT",
"main": "./dist/iconify.min.js", "main": "./dist/iconify.min.js",
"types": "./dist/iconify.d.ts", "types": "./dist/iconify.d.ts",

View File

@ -2,6 +2,7 @@ import type { IconifyIcon } from '@iconify/utils/lib/icon/defaults';
import { iconToSVG } from '@iconify/utils/lib/svg/build'; import { iconToSVG } from '@iconify/utils/lib/svg/build';
import { replaceIDs } from '@iconify/utils/lib/svg/id'; import { replaceIDs } from '@iconify/utils/lib/svg/id';
import { iconToHTML } from '@iconify/utils/lib/svg/html'; import { iconToHTML } from '@iconify/utils/lib/svg/html';
import { cleanUpInnerHTML } from '@iconify/utils/lib/svg/inner-html';
import { import {
elementDataProperty, elementDataProperty,
IconifyElement, IconifyElement,
@ -40,7 +41,7 @@ export function renderInlineSVG(
'role': 'img', 'role': 'img',
...renderData.attributes, ...renderData.attributes,
}); });
span.innerHTML = html; span.innerHTML = cleanUpInnerHTML(html);
// Get SVG element // Get SVG element
const svg = span.childNodes[0] as IconifyElement; const svg = span.childNodes[0] as IconifyElement;

View File

@ -20,13 +20,13 @@ Iconify Icon web component renders icons.
Add this line to your page to load IconifyIcon (you can add it to `<head>` section of the page or before `</body>`): Add this line to your page to load IconifyIcon (you can add it to `<head>` section of the page or before `</body>`):
```html ```html
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script> <script src="https://code.iconify.design/iconify-icon/1.0.8/iconify-icon.min.js"></script>
``` ```
or or
```html ```html
<script src="https://cdn.jsdelivr.net/npm/iconify-icon@1.0.7/dist/iconify-icon.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/iconify-icon@1.0.8/dist/iconify-icon.min.js"></script>
``` ```
or, if you are building a project with a bundler, you can include the script by installing `iconify-icon` as a dependency and importing it in your project: or, if you are building a project with a bundler, you can include the script by installing `iconify-icon` as a dependency and importing it in your project:

View File

@ -3,6 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script';"
/>
<title>Iconify Icon Demo: Usage</title> <title>Iconify Icon Demo: Usage</title>
<style> <style>
html, html,

View File

@ -2,7 +2,7 @@
"name": "iconify-icon", "name": "iconify-icon",
"description": "Icon web component that loads icon data on demand. Over 150,000 icons to choose from", "description": "Icon web component that loads icon data on demand. Over 150,000 icons to choose from",
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)", "author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
"version": "1.0.7", "version": "1.0.8",
"license": "MIT", "license": "MIT",
"main": "./dist/iconify-icon.cjs", "main": "./dist/iconify-icon.cjs",
"types": "./dist/iconify-icon.d.ts", "types": "./dist/iconify-icon.d.ts",

View File

@ -1,5 +1,6 @@
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build'; import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { iconToHTML } from '@iconify/utils/lib/svg/html'; import { iconToHTML } from '@iconify/utils/lib/svg/html';
import { cleanUpInnerHTML } from '@iconify/utils/lib/svg/inner-html';
/** /**
* Render node as <svg> * Render node as <svg>
@ -21,6 +22,7 @@ export function renderSVG(data: IconifyIconBuildResult): Element {
} }
// Generate SVG // Generate SVG
node.innerHTML = iconToHTML(data.body, attr); const html = iconToHTML(data.body, attr);
node.innerHTML = cleanUpInnerHTML(html);
return node.firstChild as HTMLElement; return node.firstChild as HTMLElement;
} }

View File

@ -2,7 +2,7 @@
"name": "@iconify-icon/react", "name": "@iconify-icon/react",
"description": "React wrapper for Iconify Icon web component", "description": "React wrapper for Iconify Icon web component",
"author": "Vjacheslav Trushkin", "author": "Vjacheslav Trushkin",
"version": "1.0.7", "version": "1.0.8",
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/iconify/iconify/issues", "bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/", "homepage": "https://iconify.design/",

View File

@ -3,7 +3,7 @@
"type": "module", "type": "module",
"description": "SolidJS wrapper for Iconify Icon web component", "description": "SolidJS wrapper for Iconify Icon web component",
"author": "Vjacheslav Trushkin", "author": "Vjacheslav Trushkin",
"version": "1.0.7", "version": "1.0.8",
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/iconify/iconify/issues", "bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/", "homepage": "https://iconify.design/",

View File

@ -352,6 +352,11 @@
"import": "./lib/svg/id.mjs", "import": "./lib/svg/id.mjs",
"types": "./lib/svg/id.d.ts" "types": "./lib/svg/id.d.ts"
}, },
"./lib/svg/inner-html": {
"require": "./lib/svg/inner-html.cjs",
"import": "./lib/svg/inner-html.mjs",
"types": "./lib/svg/inner-html.d.ts"
},
"./lib/svg/size": { "./lib/svg/size": {
"require": "./lib/svg/size.cjs", "require": "./lib/svg/size.cjs",
"import": "./lib/svg/size.mjs", "import": "./lib/svg/size.mjs",

View File

@ -59,6 +59,7 @@ export { encodeSvgForCss } from './svg/encode-svg-for-css';
export { trimSVG } from './svg/trim'; export { trimSVG } from './svg/trim';
export { iconToHTML } from './svg/html'; export { iconToHTML } from './svg/html';
export { svgToURL, svgToData } from './svg/url'; export { svgToURL, svgToData } from './svg/url';
export { cleanUpInnerHTML } from './svg/inner-html';
// Colors // Colors
export { colorKeywords } from './colors/keywords'; export { colorKeywords } from './colors/keywords';

View File

@ -0,0 +1,36 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
interface Policy {
createHTML: (s: string) => string;
}
let policy: undefined | null | Policy;
/**
* Attempt to create policy
*/
function createPolicy() {
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
policy = window.trustedTypes.createPolicy('iconify', {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
createHTML: (s) => s,
}) as Policy;
} catch (err) {
policy = null;
}
}
/**
* Clean up value for innerHTML assignment
*
* This code doesn't actually clean up anything.
* It is intended be used with Iconify icon data, which has already been validated
*/
export function cleanUpInnerHTML(html: string): string {
if (policy === undefined) {
createPolicy();
}
return policy ? (policy.createHTML(html) as unknown as string) : html;
}