diff --git a/components.d.ts b/components.d.ts index d14dd515..a190f7a3 100644 --- a/components.d.ts +++ b/components.d.ts @@ -124,6 +124,7 @@ declare module '@vue/runtime-core' { IconMdiVideo: typeof import('~icons/mdi/video')['default'] ImageExifReader: typeof import('./src/tools/image-exif-reader/image-exif-reader.vue')['default'] ImageResizer: typeof import('./src/tools/image-resizer/image-resizer.vue')['default'] + ImageToCss: typeof import('./src/tools/image-to-css/image-to-css.vue')['default'] InputCopyable: typeof import('./src/components/InputCopyable.vue')['default'] IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default'] IpGeoLocation: typeof import('./src/tools/ip-geo-location/ip-geo-location.vue')['default'] @@ -193,9 +194,9 @@ declare module '@vue/runtime-core' { NP: typeof import('naive-ui')['NP'] NProgress: typeof import('naive-ui')['NProgress'] NScrollbar: typeof import('naive-ui')['NScrollbar'] - NSelect: typeof import('naive-ui')['NSelect'] NSlider: typeof import('naive-ui')['NSlider'] NSpace: typeof import('naive-ui')['NSpace'] + NSpin: typeof import('naive-ui')['NSpin'] NStatistic: typeof import('naive-ui')['NStatistic'] NSwitch: typeof import('naive-ui')['NSwitch'] NTable: typeof import('naive-ui')['NTable'] diff --git a/package.json b/package.json index 8fde3b2c..abc7caac 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ ], "scripts": { "dev": "vite", - "build": "vue-tsc --noEmit && NODE_OPTIONS=--max_old_space_size=4096 vite build", + "build": "vue-tsc --noEmit && NODE_OPTIONS=--max_old_space_size=8192 vite build", "preview": "vite preview --port 5050", "test": "npm run test:unit", "test:unit": "vitest --environment jsdom", @@ -76,8 +76,8 @@ "figlet": "^1.7.0", "figue": "^1.2.0", "fuse.js": "^6.6.2", - "hash-wasm": "^4.9.0", "generate-schema": "^2.6.0", + "hash-wasm": "^4.9.0", "highlight.js": "^11.7.0", "iarna-toml-esm": "^3.0.5", "ibantools": "^4.3.3", @@ -113,6 +113,7 @@ "qrcode": "^1.5.1", "randexp": "^0.5.3", "sql-formatter": "^13.0.0", + "svg-to-url": "^4.0.0", "tesseract.js": "^5.0.4", "ua-parser-js": "^1.0.35", "ulid": "^2.3.0", @@ -120,7 +121,7 @@ "unplugin-auto-import": "^0.16.4", "uuid": "^9.0.0", "vanilla-jsoneditor": "^0.23.8", - "vite-plugin-node-polyfills": "^0.21.0", + "vite-plugin-node-polyfills": "^0.22.0", "vue": "^3.3.4", "vue-i18n": "^9.9.1", "vue-router": "^4.1.6", @@ -178,6 +179,5 @@ "vitest": "^0.34.0", "workbox-window": "^7.0.0", "zx": "^7.2.1" - }, - "packageManager": "pnpm@8.15.3" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f83835ad..8f7d8694 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -239,6 +239,9 @@ importers: sql-formatter: specifier: ^13.0.0 version: 13.0.0 + svg-to-url: + specifier: ^4.0.0 + version: 4.0.0 tesseract.js: specifier: ^5.0.4 version: 5.1.1 @@ -261,8 +264,8 @@ importers: specifier: ^0.23.8 version: 0.23.8(@lezer/common@1.2.3) vite-plugin-node-polyfills: - specifier: ^0.21.0 - version: 0.21.0(rollup@2.79.1)(vite@4.4.9(@types/node@18.15.11)(less@4.1.3)(sass@1.80.4)(terser@5.24.0)) + specifier: ^0.22.0 + version: 0.22.0(rollup@2.79.1)(vite@4.4.9(@types/node@18.15.11)(less@4.1.3)(sass@1.80.4)(terser@5.24.0)) vue: specifier: ^3.3.4 version: 3.3.4 @@ -2824,6 +2827,10 @@ packages: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + change-case@3.1.0: resolution: {integrity: sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==} @@ -2884,6 +2891,10 @@ packages: resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} engines: {node: '>=6'} + clipboardy@4.0.0: + resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} + engines: {node: '>=18'} + cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} @@ -3588,6 +3599,10 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + exif-be-gone@1.5.1: resolution: {integrity: sha512-+fV9PoomNVR5Hmp0n1c0ZVl78/GaFrpnC0t7q4F9Aey8NcL+7Lutcez8KY2Ni30NWpvgLXawqiRFFwtdo4QgFg==} hasBin: true @@ -3772,6 +3787,10 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -3940,6 +3959,10 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + husky@9.1.6: resolution: {integrity: sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==} engines: {node: '>=18'} @@ -4095,6 +4118,11 @@ packages: engines: {node: '>=8'} hasBin: true + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-electron@2.2.2: resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} @@ -4125,6 +4153,11 @@ packages: is-hexadecimal@1.0.4: resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -4192,6 +4225,10 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -4224,6 +4261,14 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + is64bit@2.0.0: + resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} + engines: {node: '>=18'} + isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -4589,6 +4634,10 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + mimic-response@2.1.0: resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} engines: {node: '>=8'} @@ -4769,6 +4818,10 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npmlog@5.0.1: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} deprecated: This package is no longer supported. @@ -4816,6 +4869,10 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -4923,6 +4980,10 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -5445,6 +5506,10 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} @@ -5582,6 +5647,10 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -5623,11 +5692,21 @@ packages: svg-tags@1.0.0: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + svg-to-url@4.0.0: + resolution: {integrity: sha512-F7TJJGyfHHbVj1DD9Go6T8aHOcr84H/imr1bjaJII97Ni+uqKfABKaiR3BPrA/PFlNRTuB5Psjii7vmiuM970w==} + engines: {node: '>=18'} + hasBin: true + svgo@3.0.2: resolution: {integrity: sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==} engines: {node: '>=14.0.0'} hasBin: true + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} + engines: {node: '>=14.0.0'} + hasBin: true + swap-case@1.1.2: resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} @@ -5638,6 +5717,10 @@ packages: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} + system-architecture@0.1.0: + resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} + engines: {node: '>=18'} + tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} @@ -6041,8 +6124,8 @@ packages: engines: {node: '>=v14.18.0'} hasBin: true - vite-plugin-node-polyfills@0.21.0: - resolution: {integrity: sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA==} + vite-plugin-node-polyfills@0.22.0: + resolution: {integrity: sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA==} peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 @@ -9434,6 +9517,8 @@ snapshots: chalk@5.2.0: {} + chalk@5.3.0: {} + change-case@3.1.0: dependencies: camel-case: 3.0.0 @@ -9524,6 +9609,12 @@ snapshots: cli-spinners@2.9.1: {} + clipboardy@4.0.0: + dependencies: + execa: 8.0.1 + is-wsl: 3.1.0 + is64bit: 2.0.0 + cliui@6.0.0: dependencies: string-width: 4.2.3 @@ -10348,6 +10439,18 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + exif-be-gone@1.5.1: {} exifreader@4.25.0: @@ -10539,6 +10642,8 @@ snapshots: get-stream@6.0.1: {} + get-stream@8.0.1: {} + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.7 @@ -10724,6 +10829,8 @@ snapshots: human-signals@2.1.0: {} + human-signals@5.0.0: {} + husky@9.1.6: {} hygen@6.2.11: @@ -10878,6 +10985,8 @@ snapshots: is-docker@2.2.1: {} + is-docker@3.0.0: {} + is-electron@2.2.2: {} is-extendable@0.1.1: {} @@ -10900,6 +11009,10 @@ snapshots: is-hexadecimal@1.0.4: {} + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-interactive@1.0.0: {} is-ip@5.0.1: @@ -10955,6 +11068,8 @@ snapshots: is-stream@2.0.1: {} + is-stream@3.0.0: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 @@ -10985,6 +11100,14 @@ snapshots: dependencies: is-docker: 2.2.1 + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + is64bit@2.0.0: + dependencies: + system-architecture: 0.1.0 + isarray@1.0.0: {} isarray@2.0.5: {} @@ -11367,6 +11490,8 @@ snapshots: mimic-fn@2.1.0: {} + mimic-fn@4.0.0: {} + mimic-response@2.1.0: optional: true @@ -11575,6 +11700,10 @@ snapshots: dependencies: path-key: 3.1.1 + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + npmlog@5.0.1: dependencies: are-we-there-yet: 2.0.0 @@ -11630,6 +11759,10 @@ snapshots: dependencies: mimic-fn: 2.1.0 + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -11760,6 +11893,8 @@ snapshots: path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-type@4.0.0: {} @@ -12346,6 +12481,8 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + simple-concat@1.0.1: {} simple-get@3.1.1: @@ -12511,6 +12648,8 @@ snapshots: strip-final-newline@2.0.0: {} + strip-final-newline@3.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -12560,6 +12699,13 @@ snapshots: svg-tags@1.0.0: {} + svg-to-url@4.0.0: + dependencies: + chalk: 5.3.0 + clipboardy: 4.0.0 + commander: 12.1.0 + svgo: 3.3.2 + svgo@3.0.2: dependencies: '@trysound/sax': 0.2.0 @@ -12569,6 +12715,16 @@ snapshots: csso: 5.0.5 picocolors: 1.0.0 + svgo@3.3.2: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.1.0 + css-tree: 2.3.1 + css-what: 6.1.0 + csso: 5.0.5 + picocolors: 1.0.0 + swap-case@1.1.2: dependencies: lower-case: 1.1.4 @@ -12581,6 +12737,8 @@ snapshots: '@pkgr/utils': 2.3.1 tslib: 2.5.0 + system-architecture@0.1.0: {} + tar-fs@2.1.1: dependencies: chownr: 1.1.4 @@ -13099,7 +13257,7 @@ snapshots: - supports-color - terser - vite-plugin-node-polyfills@0.21.0(rollup@2.79.1)(vite@4.4.9(@types/node@18.15.11)(less@4.1.3)(sass@1.80.4)(terser@5.24.0)): + vite-plugin-node-polyfills@0.22.0(rollup@2.79.1)(vite@4.4.9(@types/node@18.15.11)(less@4.1.3)(sass@1.80.4)(terser@5.24.0)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@2.79.1) node-stdlib-browser: 1.2.1 diff --git a/src/tools/image-to-css/image-to-css.service.ts b/src/tools/image-to-css/image-to-css.service.ts new file mode 100644 index 00000000..75339483 --- /dev/null +++ b/src/tools/image-to-css/image-to-css.service.ts @@ -0,0 +1,47 @@ +import { stringToUrl } from 'svg-to-url'; + +export type CSSType = 'Background' | 'Border' | 'ListItemBullet' | 'Url'; + +async function fileToDataUrl(file: File) { + if (file.type === 'image/svg+xml') { + const svgContent = (await (new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsText(file); + reader.onload = () => resolve(reader.result?.toString() ?? ''); + reader.onerror = error => reject(error); + }))); + return svgToDataUrl(svgContent); + } + + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result?.toString() ?? ''); + reader.onerror = error => reject(error); + }); +} + +function svgToDataUrl(image: string) { + const getUrlFromSvgString = stringToUrl({}); + return getUrlFromSvgString(image); +} + +export async function imageToCSS( + image: File | string, + type: CSSType, +) { + if (image === '' || !image) { + return ''; + } + const dataURI = image instanceof File ? await fileToDataUrl(image) : svgToDataUrl(image); + switch (type) { + case 'Background': + return `background-image: url(${dataURI});`; + case 'Border': + return `border-image-source: url(${dataURI});`; + case 'ListItemBullet': + return `li{\n list-style-image: ${dataURI};\n}\nli::marker{\n font-size: 1.5em;\n}'}`; + default: + return `url(${dataURI})`; + } +} diff --git a/src/tools/image-to-css/image-to-css.vue b/src/tools/image-to-css/image-to-css.vue new file mode 100644 index 00000000..a7ffe6e7 --- /dev/null +++ b/src/tools/image-to-css/image-to-css.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/tools/image-to-css/index.ts b/src/tools/image-to-css/index.ts new file mode 100644 index 00000000..08d20ad1 --- /dev/null +++ b/src/tools/image-to-css/index.ts @@ -0,0 +1,12 @@ +import { BrandCss3 } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Image to CSS', + path: '/image-to-css', + description: 'Convert image to CSS (url, background, ...)', + keywords: ['image', 'css'], + component: () => import('./image-to-css.vue'), + icon: BrandCss3, + createdAt: new Date('2024-05-11'), +}); diff --git a/src/tools/index.ts b/src/tools/index.ts index 723f5821..6bdf047a 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -29,6 +29,7 @@ import { tool as regexMemo } from './regex-memo'; import { tool as markdownToHtml } from './markdown-to-html'; import { tool as propertiesToYaml } from './properties-to-yaml'; import { tool as apiTester } from './api-tester'; +import { tool as imageToCss } from './image-to-css'; import { tool as jsonToSchema } from './json-to-schema'; import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as uuidConverter } from './uuid-converter'; @@ -180,6 +181,7 @@ export const toolsByCategory: ToolCategory[] = [ safelinkDecoder, apiTester, jsUnobfuscator, + imageToCss, ], }, { diff --git a/vite.config.ts b/vite.config.ts index 0c083ceb..aba6aa3f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -15,7 +15,7 @@ import { VitePWA } from 'vite-plugin-pwa'; import markdown from 'vite-plugin-vue-markdown'; import svgLoader from 'vite-svg-loader'; import { configDefaults } from 'vitest/config'; -import { nodePolyfills } from 'vite-plugin-node-polyfills' +import { nodePolyfills } from 'vite-plugin-node-polyfills'; const baseUrl = process.env.BASE_URL ?? '/'; @@ -121,7 +121,7 @@ export default defineConfig({ build: { target: 'esnext', rollupOptions: { - external: ['./out/isolated_vm'], + external: ['./out/isolated_vm', 'node:fs/promises', 'fs'], }, }, optimizeDeps: {