Adjust react in api

This commit is contained in:
Eric Fennis
2026-02-26 16:57:10 +01:00
parent 0020c21fd6
commit 68a7c22cbd
10 changed files with 97 additions and 121 deletions
@@ -1,6 +1,6 @@
// import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { createElement } from 'react';
import React from 'react';
import SvgPreview from '../../lib/SvgPreview/index.tsx';
import iconNodes from '../../data/iconNodes';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
@@ -34,36 +34,30 @@ export default eventHandler((event) => {
const iconNode = iconNodes[backdropName];
const LucideIcon = createLucideIcon(backdropName, iconNode);
const svg = renderToStaticMarkup(createElement(LucideIcon));
const svg = renderToStaticMarkup(<LucideIcon/>);
const backdropString = svg.replaceAll('\n', '').replace(/<svg[^>]*>|<\/svg>/g, '');
children.push(
createElement(Backdrop, {
backdropString,
src: src.replace(/<svg[^>]*>|<\/svg>/g, ''),
color: '#777',
}),
<Backdrop
backdropString={backdropString}
src={src.replace(/<svg[^>]*>|<\/svg>/g, '')}
color="#777"
/>
);
}
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(
createElement(
SvgPreview,
{
src: src.replace(/<svg[^>]*>|<\/svg>/g, ''),
height,
width,
showGrid: true,
},
children,
),
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<SvgPreview
src={src.replace(/<svg[^>]*>|<\/svg>/g, '')}
showGrid
height={height}
width={width}
>
{children}
</SvgPreview>
)
});
@@ -1,6 +1,6 @@
// import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { createElement } from 'react';
import React from 'react';
import Diff from '../../../lib/SvgPreview/Diff.tsx';
import iconNodes from '../../../data/iconNodes';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
@@ -26,21 +26,26 @@ export default eventHandler((event) => {
const children = [];
const Icon = createLucideIcon(name, iconNodes[name])
const oldSrc = iconNodes[name]
? renderToStaticMarkup(createElement(createLucideIcon(name, iconNodes[name])))
? renderToStaticMarkup(<Icon/>)
.replaceAll('\n', '')
.replace(/<svg[^>]*>|<\/svg>/g, '')
: '';
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(
createElement(Diff, { oldSrc, newSrc, showGrid: true, height, width }, children),
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<Diff
oldSrc={oldSrc}
newSrc={newSrc}
showGrid
height={height}
width={width}
>
{children}
</Diff>
)
});
@@ -1,8 +1,7 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString } from 'react-dom/server';
import { createElement } from 'react';
import SvgPreview from '../../../lib/SvgPreview/index.tsx';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
import React from 'react';
import Icon from 'lucide-react/src/Icon';
import type { IconNode } from 'lucide-react/src/types';
import { parseSync } from 'svgson';
@@ -13,33 +12,26 @@ export default eventHandler((event) => {
const data = svgData.slice(0, -4);
const src = Buffer.from(data, 'base64').toString('utf8');
const Icon = createLucideIcon(
'icon',
parseSync(src.includes('<svg') ? src : `<svg>${src}</svg>`).children.map(
({ name, attributes }) => [name, attributes],
) as IconNode,
);
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(createElement(Icon, { strokeWidth }))
.replace(/fill\="none"/, 'fill="#fff"')
.replace(
/>/,
`><style>
@media screen and (prefers-color-scheme: light) {
svg { fill: transparent !important; }
}
@media screen and (prefers-color-scheme: dark) {
svg { stroke: #fff; fill: transparent !important; }
}
</style>`,
),
).toString('utf8');
const iconNode = parseSync(src.includes('<svg') ? src : `<svg>${src}</svg>`).children.map(
({ name, attributes }) => [name, attributes],
) as IconNode
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<Icon
iconNode={iconNode}
strokeWidth={strokeWidth}
>
<style>
{ `@media screen and (prefers-color-scheme: light) {
svg { fill: transparent !important; }
}
@media screen and (prefers-color-scheme: dark) {
svg { stroke: #fff; fill: transparent !important; }
}`}
</style>
</Icon>
)
});
@@ -1,6 +1,6 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString } from 'react-dom/server';
import { createElement } from 'react';
import React from 'react';
import Diff from '../../../lib/SvgPreview/Diff.tsx';
export default eventHandler((event) => {
@@ -41,15 +41,18 @@ export default eventHandler((event) => {
return '';
}
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(
createElement(Diff, { oldSrc, newSrc, showGrid: true, height, width }, children),
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<Diff
oldSrc={oldSrc}
newSrc={newSrc}
showGrid
height={height}
width={width}
>
{children}
</Diff>
)
});
+1 -1
View File
@@ -1,4 +1,4 @@
// import { eventHandler, getQuery, setResponseHeader } from 'h3';
import { eventHandler, getQuery, setResponseHeader } from 'h3';
import iconNodes from '../../data/iconNodes';
import { IconNodeWithKeys } from '../../theme/types';
+1 -1
View File
@@ -1,4 +1,4 @@
// import { eventHandler, getQuery, setResponseHeader, createError } from 'h3';
import { eventHandler, getQuery, setResponseHeader, createError } from 'h3';
import iconNodes from '../../data/iconNodes';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
import { renderToString } from 'react-dom/server';
+10 -10
View File
@@ -389,15 +389,15 @@ const Handles = ({
</g>
);
const SvgPreview = React.forwardRef<
SVGSVGElement,
{
height?: number;
width?: number;
src: string | ReturnType<typeof getPaths>;
showGrid?: boolean;
} & React.SVGProps<SVGSVGElement>
>(({ src, children, height = 24, width = 24, showGrid = false, ...props }, ref) => {
interface SvgPreviewProps extends React.SVGProps<SVGSVGElement> {
height?: number;
width?: number;
src: string | ReturnType<typeof getPaths>;
showGrid?: boolean;
children?: React.ReactNode;
}
const SvgPreview = ({ src, children, height = 24, width = 24, showGrid = false, ...props }: SvgPreviewProps, ref) => {
const subGridSize =
Math.max(height, width) % 3 === 0
? Math.max(height, width) > 24
@@ -494,7 +494,7 @@ const SvgPreview = React.forwardRef<
{children}
</svg>
);
});
};
SvgPreview.displayName = 'SvgPreview';
+2 -2
View File
@@ -49,8 +49,8 @@
"lodash-es": "^4.17.23",
"lucide-react": "workspace:*",
"lucide-vue-next": "workspace:*",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"sandpack-vue3": "3.1.11",
"semver": "^7.7.3",
"sharp": "^0.34.5",
+4 -1
View File
@@ -2,11 +2,14 @@
"extends": "./.nitro/types/tsconfig.json",
"compilerOptions": {
"jsx": "react",
"jsxFactory": "React.createElement",
"allowImportingTsExtensions": true,
"allowSyntheticDefaultImports": true,
"noEmit": true,
"paths": {
"~/.vitepress/*": ["./.vitepress/*"],
"~/.vitepress/*": [
"./.vitepress/*"
],
},
},
}
+12 -33
View File
@@ -149,11 +149,11 @@ importers:
specifier: workspace:*
version: link:../packages/lucide-vue-next
react:
specifier: ^19.2.4
version: 19.2.4
specifier: 18.2.0
version: 18.2.0
react-dom:
specifier: ^19.2.4
version: 19.2.4(react@19.2.4)
specifier: 18.2.0
version: 18.2.0(react@18.2.0)
sandpack-vue3:
specifier: 3.1.11
version: 3.1.11(vue@3.5.24(typescript@5.9.3))
@@ -211,7 +211,7 @@ importers:
version: 2.1.11
vitepress:
specifier: ^1.6.4
version: 1.6.4(@algolia/client-search@5.44.0)(@types/node@24.10.1)(@types/react@18.3.27)(axios@1.13.2)(fuse.js@7.1.0)(less@4.2.0)(postcss@8.5.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.8)(search-insights@2.8.2)(stylus@0.56.0)(terser@5.44.1)(typescript@5.9.3)
version: 1.6.4(@algolia/client-search@5.44.0)(@types/node@24.10.1)(@types/react@18.3.27)(axios@1.13.2)(fuse.js@7.1.0)(less@4.2.0)(postcss@8.5.6)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.77.8)(search-insights@2.8.2)(stylus@0.56.0)(terser@5.44.1)(typescript@5.9.3)
packages/astro:
devDependencies:
@@ -11305,11 +11305,6 @@ packages:
peerDependencies:
react: ^18.3.1
react-dom@19.2.4:
resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
peerDependencies:
react: ^19.2.4
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
@@ -11349,10 +11344,6 @@ packages:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
react@19.2.4:
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
engines: {node: '>=0.10.0'}
read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
@@ -11793,9 +11784,6 @@ packages:
scheduler@0.24.0-canary-efb381bbf-20230505:
resolution: {integrity: sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==}
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
schema-utils@2.7.1:
resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==}
engines: {node: '>= 8.9.0'}
@@ -16294,9 +16282,9 @@ snapshots:
'@docsearch/css@3.8.2': {}
'@docsearch/js@3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.8.2)':
'@docsearch/js@3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(search-insights@2.8.2)':
dependencies:
'@docsearch/react': 3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.8.2)
'@docsearch/react': 3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(search-insights@2.8.2)
preact: 10.28.2
transitivePeerDependencies:
- '@algolia/client-search'
@@ -16305,7 +16293,7 @@ snapshots:
- react-dom
- search-insights
'@docsearch/react@3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.8.2)':
'@docsearch/react@3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(search-insights@2.8.2)':
dependencies:
'@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.44.0)(algoliasearch@5.44.0)(search-insights@2.8.2)
'@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.44.0)(algoliasearch@5.44.0)
@@ -16313,8 +16301,8 @@ snapshots:
algoliasearch: 5.44.0
optionalDependencies:
'@types/react': 18.3.27
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
search-insights: 2.8.2
transitivePeerDependencies:
- '@algolia/client-search'
@@ -26370,11 +26358,6 @@ snapshots:
react: 18.3.1
scheduler: 0.23.2
react-dom@19.2.4(react@19.2.4):
dependencies:
react: 19.2.4
scheduler: 0.27.0
react-is@17.0.2: {}
react-is@18.2.0: {}
@@ -26451,8 +26434,6 @@ snapshots:
dependencies:
loose-envify: 1.4.0
react@19.2.4: {}
read-cache@1.0.0:
dependencies:
pify: 2.3.0
@@ -27068,8 +27049,6 @@ snapshots:
dependencies:
loose-envify: 1.4.0
scheduler@0.27.0: {}
schema-utils@2.7.1:
dependencies:
'@types/json-schema': 7.0.15
@@ -28724,10 +28703,10 @@ snapshots:
optionalDependencies:
vite: 6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)
vitepress@1.6.4(@algolia/client-search@5.44.0)(@types/node@24.10.1)(@types/react@18.3.27)(axios@1.13.2)(fuse.js@7.1.0)(less@4.2.0)(postcss@8.5.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.8)(search-insights@2.8.2)(stylus@0.56.0)(terser@5.44.1)(typescript@5.9.3):
vitepress@1.6.4(@algolia/client-search@5.44.0)(@types/node@24.10.1)(@types/react@18.3.27)(axios@1.13.2)(fuse.js@7.1.0)(less@4.2.0)(postcss@8.5.6)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.77.8)(search-insights@2.8.2)(stylus@0.56.0)(terser@5.44.1)(typescript@5.9.3):
dependencies:
'@docsearch/css': 3.8.2
'@docsearch/js': 3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.8.2)
'@docsearch/js': 3.8.2(@algolia/client-search@5.44.0)(@types/react@18.3.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(search-insights@2.8.2)
'@iconify-json/simple-icons': 1.2.59
'@shikijs/core': 2.5.0
'@shikijs/transformers': 2.5.0