feat: added dpi preview (#1510)

* feat: added dpi preview

* fix: switched to resvg

* build: updated versions and nitro build config

* fix: switched to resvg-wasm

* fix: trying out fetch with import meta url

* fix: trying out copy wasm file manually

* fix: wrong file path

* fix: trying out esmImport

* fix: oups

* fix: giving up

* fix: await initialization

* fix: still nothing

* Revert "fix: still nothing"

This reverts commit dcb9fe3837a32ec4149f41c9b8925ae0e2fbdb79.

* fix: implement suggestions

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

* Update .github/workflows/pull-request.yml

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
This commit is contained in:
Jakob Guddas
2023-08-24 11:37:07 +02:00
committed by GitHub
co-authored by Eric Fennis
parent e78d910a83
commit 5f442122ab
7 changed files with 4280 additions and 4660 deletions
+18
View File
@@ -22,6 +22,20 @@ jobs:
uses: tj-actions/changed-files@v35
with:
files: icons/*.svg
- name: Generate 24px dpi preview
id: generate-24px-dpi-preview
run: |
delimiter="$(openssl rand -hex 8)"
echo "body<<$delimiter" >> $GITHUB_OUTPUT
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
cat "$file" | # get file content
tr '\n' ' ' | # remove line breaks
sed -e 's/<svg[^>]*>/<svg>/g' | # remove attributes from svg element
base64 -w 0 | # encode svg
sed "s|.*|<img title=\"$file\" alt=\"$file\" src=\"https://lucide.dev/api/gh-icon/dpi/24/&.svg\"/> |"
done | tr '\n' ' ' >> $GITHUB_OUTPUT
echo >> $GITHUB_OUTPUT
echo "$delimiter" >> $GITHUB_OUTPUT
- name: Generate cohesion check random
id: generate-cohesion-check-random
run: |
@@ -134,6 +148,10 @@ jobs:
${{ steps.generate-3px-stroke-width.outputs.body }}<br/>
</details>
<details>
<summary>DPI Preview (24px)</summary>
${{ steps.generate-24px-dpi-preview.outputs.body }}<br/>
</details>
<details>
<summary>Icon X-rays</summary>
${{ steps.generate-x-rays.outputs.body }}
</details>
@@ -0,0 +1,73 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { Resvg, initWasm } from '@resvg/resvg-wasm';
import wasm from './loadWasm';
var initializedResvg = initWasm(wasm);
export default eventHandler(async (event) => {
const { params = {} } = event.context;
await initializedResvg;
const imageSize = 96;
const [iconSizeString, svgData] = params.data.split('/');
const iconSize = parseInt(iconSizeString, 10);
const data = svgData.slice(0, -4);
const src = Buffer.from(data, 'base64').toString('utf8');
const svg = (src.includes('<svg') ? src : `<svg>${src}</svg>`)
.replace(/(\r\n|\n|\r)/gm, '')
.replace(
/<svg[^>]*/,
`<svg
xmlns="http://www.w3.org/2000/svg"
width="${iconSize}"
height="${iconSize}"
viewBox="0 0 24 24"
fill="none"
stroke="#fff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
`
);
const resvg = new Resvg(svg, { background: '#000' });
const pngData = resvg.render();
const pngBuffer = Buffer.from(pngData.asPng());
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return `
<svg xmlns="http://www.w3.org/2000/svg" width="${imageSize}" height="${imageSize}" viewBox="0 0 ${imageSize} ${imageSize}">
<style>
@media screen and (prefers-color-scheme: light) {
#fallback-background { fill: transparent; }
}
@media screen and (prefers-color-scheme: dark) {
#fallback-background { fill: transparent; }
rect { fill: #fff; }
}
</style>
<mask id="mask">
<image
width="${imageSize}"
height="${imageSize}"
href="data:image/png;base64,${pngBuffer.toString('base64')}"
image-rendering="pixelated"
/>
</mask>
<rect
id="fallback-background"
width="${imageSize}"
height="${imageSize}" ry="${imageSize / 24}"
fill="#fff"
/>
<rect
width="${imageSize}"
height="${imageSize}"
fill="#000"
mask="url(#mask)"
/>
</svg>`;
});
@@ -0,0 +1,15 @@
import fs from 'fs';
import module from 'node:module';
/* WASM_IMPORT */
let wasm;
if (process.env.NODE_ENV === 'development') {
const require = module.createRequire(import.meta.url);
wasm = fs.readFileSync(require.resolve('@resvg/resvg-wasm/index_bg.wasm'));
} else {
wasm = resvg_wasm;
}
export default wasm;
+11 -3
View File
@@ -1,10 +1,18 @@
declare module "*.vue" {
import Vue from "vue";
declare module '*.vue' {
import Vue from 'vue';
export default Vue;
}
declare module "*.data.ts" {
declare module '*.data.ts' {
const data: any;
export { data };
}
declare module '*.wasm' {}
declare const resvg_wasm: RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
declare module 'node:module' {
function createRequire(filename: string): NodeRequire;
}
+24 -9
View File
@@ -1,4 +1,5 @@
import { defineNitroConfig } from "nitropack";
import copy from 'rollup-plugin-copy';
import replace from '@rollup/plugin-replace';
export default defineNitroConfig({
preset: 'vercel-edge',
@@ -6,15 +7,29 @@ export default defineNitroConfig({
routeRules: {
'/api/**': { cors: false },
},
rollupConfig: {
external: ['@resvg/resvg-wasm/index_bg.wasm', './index_bg.wasm?module'],
plugins: [
copy({
targets: [
{
src: './node_modules/@resvg/resvg-wasm/index_bg.wasm',
dest: './.vercel/output/functions/__nitro.func',
},
],
}),
replace({
include: ['./**/*.ts'],
'/* WASM_IMPORT */': 'import resvg_wasm from "./index_bg.wasm?module";',
delimiters: ['', ''],
preventAssignment: false,
}),
],
},
esbuild: {
options: {
include: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.json'],
loaders: {
'.js': 'js',
'.jsx': 'jsx',
'.ts': 'ts',
'.tsx': 'tsx',
}
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
},
},
})
});
+5 -2
View File
@@ -24,14 +24,17 @@
"author": "Eric Fennis",
"license": "ISC",
"devDependencies": {
"h3": "^1.7.1",
"nitropack": "2.4.1",
"@rollup/plugin-replace": "^5.0.2",
"h3": "^1.8.0",
"nitropack": "npm:nitropack-edge@latest",
"node-fetch": "2",
"rollup-plugin-copy": "^3.4.0",
"vitepress": "1.0.0-rc.4"
},
"dependencies": {
"@floating-ui/vue": "^1.0.1",
"@headlessui/vue": "^1.7.13",
"@resvg/resvg-wasm": "^2.4.1",
"@vueuse/components": "^10.1.0",
"@vueuse/core": "^10.1.0",
"element-to-path": "^1.2.1",
+4134 -4646
View File
File diff suppressed because it is too large Load Diff