From 4679ff791d97f0bd2ff9040e394500965651df15 Mon Sep 17 00:00:00 2001 From: Jakob Guddas Date: Tue, 18 Apr 2023 22:40:18 +0200 Subject: [PATCH] feat: added backdrop to gh-icon (#1097) * feat: added backdrop to gh-icon * feat: added backdrop to gh-icon * feat: changed fill pattern * chore: pattern cleanup * feat: improved backdrop color --- .github/workflows/pull-request.yml | 2 +- site/src/components/SvgPreview/index.tsx | 91 ++++++++++--------- site/src/pages/api/gh-icon/[...data].tsx | 110 +++++++++++++++++++++++ site/src/pages/api/gh-icon/[data].tsx | 19 ---- 4 files changed, 160 insertions(+), 62 deletions(-) create mode 100644 site/src/pages/api/gh-icon/[...data].tsx delete mode 100644 site/src/pages/api/gh-icon/[data].tsx diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 7b3094b80..eb5b73873 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -32,7 +32,7 @@ jobs: tr '\n' ' ' | # remove line breaks sed -e 's/]*>//g' | # remove attributes from svg element base64 -w 0 | # encode svg - sed "s|.*|\"$file\" |" + sed "s|.*|\"$file\" |" done | tr '\n' ' ' >> $GITHUB_OUTPUT echo >> $GITHUB_OUTPUT echo "$delimiter" >> $GITHUB_OUTPUT diff --git a/site/src/components/SvgPreview/index.tsx b/site/src/components/SvgPreview/index.tsx index dcf321a73..13cb0fc06 100644 --- a/site/src/components/SvgPreview/index.tsx +++ b/site/src/components/SvgPreview/index.tsx @@ -173,53 +173,60 @@ const ControlPath = ({ ); }; -const SvgPreview = React.forwardRef( - ({ src, showGrid = false }, ref) => { - const paths = getPaths(src); - const darkModeCss = `@media screen and (prefers-color-scheme: dark) { +const SvgPreview = React.forwardRef< + SVGSVGElement, + { + src: string | ReturnType; + showGrid?: boolean; + } & React.SVGProps +>(({ src, children, showGrid = false, ...props }, ref) => { + const paths = typeof src === 'string' ? getPaths(src) : src; + + const darkModeCss = `@media screen and (prefers-color-scheme: dark) { .svg-preview-grid-group, .svg-preview-shadow-mask-group, .svg-preview-shadow-group { stroke: #fff; } }`; - return ( - - - {showGrid && } - - - - - ); - } -); + return ( + + + {showGrid && } + + + + {children} + + ); +}); export default SvgPreview; diff --git a/site/src/pages/api/gh-icon/[...data].tsx b/site/src/pages/api/gh-icon/[...data].tsx new file mode 100644 index 000000000..b503ec12d --- /dev/null +++ b/site/src/pages/api/gh-icon/[...data].tsx @@ -0,0 +1,110 @@ +import { getData } from 'src/lib/icons'; +import SvgPreview from '../../../components/SvgPreview'; +import { stringify } from 'svgson'; +import { ReactNode } from 'react'; + +export default async function handler(req, res) { + // ReactDOMServer needs to be imported dynamically + // https://github.com/vercel/next.js/issues/43810 + const ReactDOMServer = (await import('react-dom/server')).default; + + const url = req.url.split('/'); + const data = url.at(-1).slice(0, -4); + const src = Buffer.from(data, 'base64') + .toString('utf8') + .replace(/]*>|<\/svg>/g, ''); + + let backdrop: ReactNode; + try { + if (url.at(-2) !== 'gh-icon') { + const backdropString = stringify({ + type: 'element', + name: 'svg', + value: undefined, + attributes: {}, + children: (await getData(url.at(-2))).iconNode.map(([name, attributes]) => ({ + type: 'element', + name, + attributes, + children: undefined, + value: undefined, + })), + }).replace(/]*>|<\/svg>/g, ''); + + backdrop = ( + <> + + + + + + + + + + + + + + + + + + + + + + + ); + } + } catch (e) { + backdrop = undefined; + } + + const svg = Buffer.from( + ReactDOMServer.renderToString( + + {backdrop} + + ) + ); + + res.setHeader('Cache-Control', 'public,max-age=31536000'); + res.setHeader('Content-Type', 'image/svg+xml'); + res.status(200).end(svg); +} diff --git a/site/src/pages/api/gh-icon/[data].tsx b/site/src/pages/api/gh-icon/[data].tsx deleted file mode 100644 index dde8ca233..000000000 --- a/site/src/pages/api/gh-icon/[data].tsx +++ /dev/null @@ -1,19 +0,0 @@ -import SvgPreview from '../../../components/SvgPreview'; - -export default async function handler(req, res) { - // ReactDOMServer needs to be imported dynamically - // https://github.com/vercel/next.js/issues/43810 - const ReactDOMServer = (await import('react-dom/server')).default; - - const url = req.url.split('/').at(-1); - const data = url.slice(0, -4); - const src = Buffer.from(data, 'base64').toString('utf8'); - - const svg = Buffer.from( - ReactDOMServer.renderToString() - ); - - res.setHeader('Cache-Control', 'public,max-age=31536000'); - res.setHeader('Content-Type', 'image/svg+xml'); - res.status(200).end(svg); -}