add svgo
Main daploy / deploy (push) Successful in 43s

This commit is contained in:
2024-11-18 21:45:34 +02:00
parent 691d7137db
commit 9686f9bbc2
4 changed files with 237 additions and 31 deletions
+179 -2
View File
@@ -16,6 +16,7 @@
"primeicons": "^7.0.0",
"primevue": "^4.2.1",
"qr-code-styling": "^1.8.4",
"svgo": "^3.3.2",
"tailwindcss-primeui": "^0.3.4",
"vue": "^3.5.12",
"vue-router": "^4.4.5"
@@ -1753,6 +1754,15 @@
"win32"
]
},
"node_modules/@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"license": "ISC",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/@tsconfig/node20": {
"version": "20.1.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz",
@@ -2796,7 +2806,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true,
"license": "ISC"
},
"node_modules/brace-expansion": {
@@ -3102,6 +3111,47 @@
"node": ">= 8"
}
},
"node_modules/css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-tree": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"license": "MIT",
"dependencies": {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -3114,6 +3164,39 @@
"node": ">=4"
}
},
"node_modules/csso": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
"integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
"license": "MIT",
"dependencies": {
"css-tree": "~2.2.0"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/csso/node_modules/css-tree": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
"integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
"license": "MIT",
"dependencies": {
"mdn-data": "2.0.28",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/csso/node_modules/mdn-data": {
"version": "2.0.28",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
"license": "CC0-1.0"
},
"node_modules/cssstyle": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz",
@@ -3261,6 +3344,61 @@
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"license": "MIT"
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -4692,6 +4830,12 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"license": "CC0-1.0"
},
"node_modules/memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
@@ -5021,7 +5165,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0"
@@ -6164,6 +6307,40 @@
"integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
"dev": true
},
"node_modules/svgo": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz",
"integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==",
"license": "MIT",
"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"
},
"bin": {
"svgo": "bin/svgo"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/svgo"
}
},
"node_modules/svgo/node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"license": "MIT",
"engines": {
"node": ">= 10"
}
},
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+1
View File
@@ -27,6 +27,7 @@
"primeicons": "^7.0.0",
"primevue": "^4.2.1",
"qr-code-styling": "^1.8.4",
"svgo": "^3.3.2",
"tailwindcss-primeui": "^0.3.4",
"vue": "^3.5.12",
"vue-router": "^4.4.5"
+56 -29
View File
@@ -10,15 +10,24 @@
<!-- Кнопки для скачивания -->
<div class="flex flex-col md:flex-row gap-4 justify-center">
<a
<!-- Основная кнопка для скачивания SVG -->
<Button
v-if="svgUrl"
label="Скачать SVG"
icon="pi pi-download"
class="p-button-sm"
:href="svgUrl"
:download="`${sanitizedFileName}.svg`"
class="p-button p-button-sm p-button-outlined text-center"
>
Скачать SVG
</a>
<Button label="Скачать PNG" icon="pi pi-download" class="p-button-sm" @click="downloadPng" />
as="a"
/>
<!-- Кнопка для скачивания PNG с outlined стилем -->
<Button
label="Скачать PNG"
icon="pi pi-download"
class="p-button-sm p-button-outlined"
@click="downloadPng"
/>
</div>
<p v-if="error" class="text-red-500 mt-4">Ошибка: {{ error }}</p>
@@ -28,14 +37,14 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import QRCodeStyling from 'qr-code-styling'
import { optimize } from 'svgo'
// Пропсы
const { uri, name } = defineProps<{ uri: string; name: string }>()
const qrCodeUrl = `https://hereconnect.condev.ru/read/${uri}`
const sanitizedFileName = computed(() => {
const sanitized = name.replace(/[^a-zA-Z0-9-_]/g, '').trim()
return sanitized || 'qr-code'
return sanitized ? `${sanitized}_QR-Code_HereConnect` : 'QR-Code_HereConnect'
})
const error = ref<string | null>(null)
@@ -47,45 +56,63 @@ const qrCode = new QRCodeStyling({
height: 256 * 4,
data: qrCodeUrl,
type: 'svg',
// dotsOptions: {
// color: '#000',
// type: 'rounded',
// },
backgroundOptions: {
color: '#ffffff',
},
})
// Генерация SVG и отображение QR-кода
onMounted(async () => {
// Генерация и оптимизация SVG
async function generateOptimizedSvg() {
try {
const blob = await qrCode.getRawData('svg')
if (blob && blob instanceof Blob) {
svgUrl.value = URL.createObjectURL(blob)
const text = await blob.text()
const optimizedSvg = optimize(text, {
plugins: [
{ name: 'removeDoctype' },
{ name: 'removeComments' },
{ name: 'removeDimensions' },
{ name: 'convertShapeToPath' },
{ name: 'convertPathData' },
{ name: 'mergePaths' },
],
})
if (optimizedSvg.data) {
svgUrl.value = URL.createObjectURL(new Blob([optimizedSvg.data], { type: 'image/svg+xml' }))
} else {
error.value = 'Ошибка оптимизации SVG'
}
} else {
error.value = 'Ошибка генерации QR-кода'
}
} catch (err) {
error.value = (err as Error).message
error.value = (err as Error).message || 'Неизвестная ошибка'
}
}
// Скачивание PNG
async function downloadPng() {
try {
await qrCode.download({
name: sanitizedFileName.value,
extension: 'png',
})
} catch (err) {
error.value = (err as Error).message || 'Ошибка при скачивании QR-кода'
}
}
// Монтирование
onMounted(() => {
generateOptimizedSvg()
})
// Очистка ресурсов при размонтировании
onUnmounted(() => {
if (svgUrl.value) {
URL.revokeObjectURL(svgUrl.value)
}
})
// Скачивание PNG
async function downloadPng() {
try {
const blob = await qrCode.getRawData('png') // Получение PNG в формате Blob
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `${sanitizedFileName.value}.png`
link.click()
} catch (err) {
error.value = (err as Error).message || 'Ошибка при скачивании QR-кода'
}
}
</script>
+1
View File
@@ -16,6 +16,7 @@ watch(
() => props.isActive,
(isActive) => {
if (isActive) {
sectionRef.value?.querySelector('input')?.focus()
sectionRef.value?.scrollIntoView({ behavior: 'smooth' })
}
},