+4
-2
@@ -2,6 +2,7 @@ import pluginVue from 'eslint-plugin-vue'
|
|||||||
import vueTsEslintConfig from '@vue/eslint-config-typescript'
|
import vueTsEslintConfig from '@vue/eslint-config-typescript'
|
||||||
import pluginVitest from '@vitest/eslint-plugin'
|
import pluginVitest from '@vitest/eslint-plugin'
|
||||||
import pluginPlaywright from 'eslint-plugin-playwright'
|
import pluginPlaywright from 'eslint-plugin-playwright'
|
||||||
|
import oxlint from 'eslint-plugin-oxlint'
|
||||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
@@ -17,15 +18,16 @@ export default [
|
|||||||
|
|
||||||
...pluginVue.configs['flat/essential'],
|
...pluginVue.configs['flat/essential'],
|
||||||
...vueTsEslintConfig(),
|
...vueTsEslintConfig(),
|
||||||
|
|
||||||
{
|
{
|
||||||
...pluginVitest.configs.recommended,
|
...pluginVitest.configs.recommended,
|
||||||
files: ['src/**/__tests__/*'],
|
files: ['src/**/__tests__/*'],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
...pluginPlaywright.configs['flat/recommended'],
|
...pluginPlaywright.configs['flat/recommended'],
|
||||||
files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
|
files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
|
||||||
},
|
},
|
||||||
|
oxlint.configs['flat/recommended'],
|
||||||
skipFormatting,
|
skipFormatting,
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import md5 from 'md5'
|
import md5 from 'md5'
|
||||||
import type { ContactInfo } from '@/types/DBDocumentTypes'
|
import type { ContactInfo } from '@/types/DBDocumentTypes'
|
||||||
|
import { sanitizeFileName } from '@/utils/sanitizeFileName'
|
||||||
|
|
||||||
const { contactInfo } = defineProps<{ contactInfo: ContactInfo }>()
|
const { contactInfo } = defineProps<{ contactInfo: ContactInfo }>()
|
||||||
|
|
||||||
@@ -90,10 +91,7 @@ function addToAddressBook() {
|
|||||||
const blob = new Blob([vCard], { type: 'text/vcard;charset=utf-8' })
|
const blob = new Blob([vCard], { type: 'text/vcard;charset=utf-8' })
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
|
|
||||||
const sanitized = contactInfo.name
|
const sanitized = contactInfo.name && sanitizeFileName(contactInfo.name)
|
||||||
?.replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // Убираем запрещённые символы
|
|
||||||
.replace(/\s+/g, '_') // Заменяем пробелы на подчёркивания
|
|
||||||
.trim()
|
|
||||||
|
|
||||||
link.href = URL.createObjectURL(blob)
|
link.href = URL.createObjectURL(blob)
|
||||||
link.download = `${sanitized || 'contact'}.vcf`
|
link.download = `${sanitized || 'contact'}.vcf`
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export const sanitizeFileName = (fileName: string) => {
|
||||||
|
return fileName
|
||||||
|
.replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // Убираем запрещённые символы
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
@@ -74,6 +74,7 @@ import { getQrCodeDocument } from '@/api/qrCode'
|
|||||||
import { type QRCodeDocument } from '@/types/DBDocumentTypes'
|
import { type QRCodeDocument } from '@/types/DBDocumentTypes'
|
||||||
import { addLabelToSvg } from '@/utils/images/svg/addLabelToSvg'
|
import { addLabelToSvg } from '@/utils/images/svg/addLabelToSvg'
|
||||||
import logo from '@/assets/logo.svg?raw'
|
import logo from '@/assets/logo.svg?raw'
|
||||||
|
import { sanitizeFileName } from '@/utils/sanitizeFileName'
|
||||||
|
|
||||||
const { qr_code_uri } = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>()
|
const { qr_code_uri } = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>()
|
||||||
const color = ref('#000') // Цвет для текста QR-кода
|
const color = ref('#000') // Цвет для текста QR-кода
|
||||||
@@ -92,12 +93,9 @@ const {
|
|||||||
queryFn: () => getQrCodeDocument(qr_code_uri),
|
queryFn: () => getQrCodeDocument(qr_code_uri),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Получение имени файла
|
|
||||||
const sanitizedFileName = computed(() => {
|
const sanitizedFileName = computed(() => {
|
||||||
const sanitized = qrCodeDoc.value?.name
|
const sanitized = qrCodeDoc.value?.name && sanitizeFileName(qrCodeDoc.value?.name)
|
||||||
?.replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // Убираем запрещённые символы
|
|
||||||
.replace(/\s+/g, ' ') // Заменяем пробелы на подчёркивания
|
|
||||||
.trim()
|
|
||||||
return sanitized ? `${sanitized} QR-Code - НаСвязи` : 'QR-Code - НаСвязи'
|
return sanitized ? `${sanitized} QR-Code - НаСвязи` : 'QR-Code - НаСвязи'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import tailwindScrollbar from 'tailwind-scrollbar'
|
||||||
|
import tailwindcssPrimeUI from 'tailwindcss-primeui'
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
plugins: [require('tailwindcss-primeui'), require('tailwind-scrollbar')],
|
plugins: [tailwindScrollbar, tailwindcssPrimeUI],
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user