Merge e62ca2295c into 63fbd3b45c
				
					
				
			This commit is contained in:
		
						commit
						96e3b022a9
					
				
							
								
								
									
										10
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -130,19 +130,24 @@ declare module '@vue/runtime-core' { | |||||||
|     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] |     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] | ||||||
|     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] |     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] | ||||||
|     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] |     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] | ||||||
|     NCheckbox: typeof import('naive-ui')['NCheckbox'] |     NCode: typeof import('naive-ui')['NCode'] | ||||||
|     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] |     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] | ||||||
|     NConfigProvider: typeof import('naive-ui')['NConfigProvider'] |     NConfigProvider: typeof import('naive-ui')['NConfigProvider'] | ||||||
|     NDivider: typeof import('naive-ui')['NDivider'] |     NDivider: typeof import('naive-ui')['NDivider'] | ||||||
|     NEllipsis: typeof import('naive-ui')['NEllipsis'] |     NEllipsis: typeof import('naive-ui')['NEllipsis'] | ||||||
|  |     NForm: typeof import('naive-ui')['NForm'] | ||||||
|  |     NFormItem: typeof import('naive-ui')['NFormItem'] | ||||||
|     NH1: typeof import('naive-ui')['NH1'] |     NH1: typeof import('naive-ui')['NH1'] | ||||||
|     NH3: typeof import('naive-ui')['NH3'] |     NH3: typeof import('naive-ui')['NH3'] | ||||||
|     NIcon: typeof import('naive-ui')['NIcon'] |     NIcon: typeof import('naive-ui')['NIcon'] | ||||||
|     NLayout: typeof import('naive-ui')['NLayout'] |     NLayout: typeof import('naive-ui')['NLayout'] | ||||||
|     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] |     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] | ||||||
|     NMenu: typeof import('naive-ui')['NMenu'] |     NMenu: typeof import('naive-ui')['NMenu'] | ||||||
|  |     NRadio: typeof import('naive-ui')['NRadio'] | ||||||
|  |     NRadioGroup: typeof import('naive-ui')['NRadioGroup'] | ||||||
|  |     NScrollbar: typeof import('naive-ui')['NScrollbar'] | ||||||
|     NSpace: typeof import('naive-ui')['NSpace'] |     NSpace: typeof import('naive-ui')['NSpace'] | ||||||
|     NTable: typeof import('naive-ui')['NTable'] |     NSwitch: typeof import('naive-ui')['NSwitch'] | ||||||
|     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] |     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] | ||||||
|     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] |     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] | ||||||
|     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] |     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] | ||||||
| @ -164,6 +169,7 @@ declare module '@vue/runtime-core' { | |||||||
|     SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default'] |     SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default'] | ||||||
|     SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default'] |     SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default'] | ||||||
|     SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default'] |     SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default'] | ||||||
|  |     SslCertConverter: typeof import('./src/tools/ssl-cert-converter/ssl-cert-converter.vue')['default'] | ||||||
|     StringObfuscator: typeof import('./src/tools/string-obfuscator/string-obfuscator.vue')['default'] |     StringObfuscator: typeof import('./src/tools/string-obfuscator/string-obfuscator.vue')['default'] | ||||||
|     SvgPlaceholderGenerator: typeof import('./src/tools/svg-placeholder-generator/svg-placeholder-generator.vue')['default'] |     SvgPlaceholderGenerator: typeof import('./src/tools/svg-placeholder-generator/svg-placeholder-generator.vue')['default'] | ||||||
|     TemperatureConverter: typeof import('./src/tools/temperature-converter/temperature-converter.vue')['default'] |     TemperatureConverter: typeof import('./src/tools/temperature-converter/temperature-converter.vue')['default'] | ||||||
|  | |||||||
| @ -46,6 +46,7 @@ | |||||||
|     "@tiptap/vue-3": "2.0.3", |     "@tiptap/vue-3": "2.0.3", | ||||||
|     "@types/figlet": "^1.5.8", |     "@types/figlet": "^1.5.8", | ||||||
|     "@types/markdown-it": "^13.0.7", |     "@types/markdown-it": "^13.0.7", | ||||||
|  |     "@types/sshpk": "^1.17.4", | ||||||
|     "@vicons/material": "^0.12.0", |     "@vicons/material": "^0.12.0", | ||||||
|     "@vicons/tabler": "^0.12.0", |     "@vicons/tabler": "^0.12.0", | ||||||
|     "@vueuse/core": "^10.3.0", |     "@vueuse/core": "^10.3.0", | ||||||
| @ -69,6 +70,7 @@ | |||||||
|     "highlight.js": "^11.7.0", |     "highlight.js": "^11.7.0", | ||||||
|     "iarna-toml-esm": "^3.0.5", |     "iarna-toml-esm": "^3.0.5", | ||||||
|     "ibantools": "^4.3.3", |     "ibantools": "^4.3.3", | ||||||
|  |     "jks-js": "^1.1.3", | ||||||
|     "js-base64": "^3.7.6", |     "js-base64": "^3.7.6", | ||||||
|     "json5": "^2.2.3", |     "json5": "^2.2.3", | ||||||
|     "jwt-decode": "^3.1.2", |     "jwt-decode": "^3.1.2", | ||||||
| @ -89,6 +91,7 @@ | |||||||
|     "qrcode": "^1.5.1", |     "qrcode": "^1.5.1", | ||||||
|     "randexp": "^0.5.3", |     "randexp": "^0.5.3", | ||||||
|     "sql-formatter": "^13.0.0", |     "sql-formatter": "^13.0.0", | ||||||
|  |     "sshpk": "^1.18.0", | ||||||
|     "ua-parser-js": "^1.0.35", |     "ua-parser-js": "^1.0.35", | ||||||
|     "ulid": "^2.3.0", |     "ulid": "^2.3.0", | ||||||
|     "unicode-emoji-json": "^0.4.0", |     "unicode-emoji-json": "^0.4.0", | ||||||
| @ -142,6 +145,7 @@ | |||||||
|     "unplugin-icons": "^0.17.0", |     "unplugin-icons": "^0.17.0", | ||||||
|     "unplugin-vue-components": "^0.25.0", |     "unplugin-vue-components": "^0.25.0", | ||||||
|     "vite": "^4.4.9", |     "vite": "^4.4.9", | ||||||
|  |     "vite-plugin-node-polyfills": "^0.22.0", | ||||||
|     "vite-plugin-pwa": "^0.16.0", |     "vite-plugin-pwa": "^0.16.0", | ||||||
|     "vite-plugin-vue-markdown": "^0.23.5", |     "vite-plugin-vue-markdown": "^0.23.5", | ||||||
|     "vite-svg-loader": "^4.0.0", |     "vite-svg-loader": "^4.0.0", | ||||||
|  | |||||||
							
								
								
									
										736
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										736
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -2,6 +2,7 @@ import { tool as base64FileConverter } from './base64-file-converter'; | |||||||
| import { tool as base64StringConverter } from './base64-string-converter'; | import { tool as base64StringConverter } from './base64-string-converter'; | ||||||
| import { tool as basicAuthGenerator } from './basic-auth-generator'; | import { tool as basicAuthGenerator } from './basic-auth-generator'; | ||||||
| import { tool as emailNormalizer } from './email-normalizer'; | import { tool as emailNormalizer } from './email-normalizer'; | ||||||
|  | import { tool as sslCertConverter } from './ssl-cert-converter'; | ||||||
| 
 | 
 | ||||||
| import { tool as asciiTextDrawer } from './ascii-text-drawer'; | import { tool as asciiTextDrawer } from './ascii-text-drawer'; | ||||||
| 
 | 
 | ||||||
| @ -164,7 +165,15 @@ export const toolsByCategory: ToolCategory[] = [ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: 'Network', |     name: 'Network', | ||||||
|     components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator], |     components: [ | ||||||
|  |       ipv4SubnetCalculator, | ||||||
|  |       ipv4AddressConverter, | ||||||
|  |       ipv4RangeExpander, | ||||||
|  |       macAddressLookup, | ||||||
|  |       macAddressGenerator, | ||||||
|  |       ipv6UlaGenerator, | ||||||
|  |       sslCertConverter, | ||||||
|  |     ], | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: 'Math', |     name: 'Math', | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/tools/ssl-cert-converter/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/ssl-cert-converter/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | import { ShieldChevron } from '@vicons/tabler'; | ||||||
|  | import { defineTool } from '../tool'; | ||||||
|  | 
 | ||||||
|  | export const tool = defineTool({ | ||||||
|  |   name: 'SSL Certificate converter', | ||||||
|  |   path: '/ssl-cert-converter', | ||||||
|  |   description: 'Convert SSL Certificate from different formats', | ||||||
|  |   keywords: ['ssl', 'certificate', 'crt', 'pkcs', 'p12', 'pem', 'der', 'jks', 'converter'], | ||||||
|  |   component: () => import('./ssl-cert-converter.vue'), | ||||||
|  |   icon: ShieldChevron, | ||||||
|  |   createdAt: new Date('2024-08-15'), | ||||||
|  | }); | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										119
									
								
								src/tools/ssl-cert-converter/ssl-cert-converter.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								src/tools/ssl-cert-converter/ssl-cert-converter.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | |||||||
|  | import type { Buffer } from 'node:buffer'; | ||||||
|  | import { | ||||||
|  |   parseCertificate, | ||||||
|  | } from 'sshpk'; | ||||||
|  | 
 | ||||||
|  | import type { | ||||||
|  |   Certificate, | ||||||
|  |   CertificateFormat, | ||||||
|  | } from 'sshpk'; | ||||||
|  | 
 | ||||||
|  | import * as forge from 'node-forge'; | ||||||
|  | import jks from 'jks-js'; | ||||||
|  | 
 | ||||||
|  | function convertPKCS12ToPem(p12base64: forge.Bytes | forge.util.ByteBuffer, password: string) { | ||||||
|  |   const p12Asn1 = forge.asn1.fromDer(p12base64, false); | ||||||
|  |   const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, password); | ||||||
|  | 
 | ||||||
|  |   const pemKey = getKeyFromP12(p12); | ||||||
|  |   const { pemCertificate, commonName } = getCertificateFromP12(p12); | ||||||
|  | 
 | ||||||
|  |   return { pemKey, pemCertificate, commonName }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getKeyFromP12(p12: forge.pkcs12.Pkcs12Pfx) { | ||||||
|  |   const keyData = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag }); | ||||||
|  |   let pkcs8Key = keyData[forge.pki.oids.pkcs8ShroudedKeyBag]![0]; | ||||||
|  | 
 | ||||||
|  |   if (!pkcs8Key) { | ||||||
|  |     pkcs8Key = keyData[forge.pki.oids.keyBag]![0]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!pkcs8Key?.key) { | ||||||
|  |     throw new TypeError('Unable to get private key.'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return forge.pki.privateKeyToPem(pkcs8Key.key); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getCertificateFromP12(p12: any) { | ||||||
|  |   const certData = p12.getBags({ bagType: forge.pki.oids.certBag }); | ||||||
|  |   const certificate = certData[forge.pki.oids.certBag][0]; | ||||||
|  | 
 | ||||||
|  |   const pemCertificate = forge.pki.certificateToPem(certificate.cert); | ||||||
|  |   const commonName = certificate.cert.subject.attributes[0].value; | ||||||
|  |   return { pemCertificate, commonName }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function convertCertificate( | ||||||
|  |   inputKeyOrCertificateValue: string | Buffer, | ||||||
|  |   password: string) { | ||||||
|  |   const canParse = (value: any, parseFunction: (value: any) => any) => { | ||||||
|  |     try { | ||||||
|  |       return parseFunction(value); | ||||||
|  |     } | ||||||
|  |     catch (e: any) { | ||||||
|  |       // console.log(e);
 | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const cert = canParse(inputKeyOrCertificateValue, (value) => { | ||||||
|  |     for (const format of ['openssh', 'pem', 'x509']) { | ||||||
|  |       try { | ||||||
|  |         return parseCertificate(value, format as CertificateFormat); | ||||||
|  |       } | ||||||
|  |       catch { | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return null; | ||||||
|  |   }) as Certificate; | ||||||
|  |   if (cert) { | ||||||
|  |     return [{ | ||||||
|  |       alias: '#default', | ||||||
|  |       key: null, | ||||||
|  |       der: canParse(cert, c => c.toBuffer('x509')), | ||||||
|  |       pem: cert.toString('pem'), | ||||||
|  |     }]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const pkcs12 = canParse(inputKeyOrCertificateValue, (value) => { | ||||||
|  |     return convertPKCS12ToPem(forge.util.createBuffer(value, 'raw'), password); | ||||||
|  |   }); | ||||||
|  |   if (pkcs12) { | ||||||
|  |     return [{ | ||||||
|  |       alias: pkcs12.commonName, | ||||||
|  |       key: pkcs12.pemKey, | ||||||
|  |       der: canParse(pkcs12.pemCertificate, pemCert => parseCertificate(pemCert, 'pem').toBuffer('x509')), | ||||||
|  |       pem: pkcs12.pemCertificate, | ||||||
|  |     }]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const parsedJKS = canParse(inputKeyOrCertificateValue, (value) => { | ||||||
|  |     return jks.toPem( | ||||||
|  |       value, | ||||||
|  |       password, | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |   if (parsedJKS) { | ||||||
|  |     return Object.entries(parsedJKS).map(([k, v]) => { | ||||||
|  |       if (typeof v === 'string') { | ||||||
|  |         return { | ||||||
|  |           alias: k, | ||||||
|  |           key: null, | ||||||
|  |           der: canParse(v, pemCert => parseCertificate(pemCert, 'pem').toBuffer('x509')), | ||||||
|  |           pem: v, | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |       const { cert, key } = v as { cert: string; key: string }; | ||||||
|  |       return { | ||||||
|  |         alias: k, | ||||||
|  |         key, | ||||||
|  |         der: canParse(cert, pemCert => parseCertificate(pemCert, 'pem').toBuffer('x509')), | ||||||
|  |         pem: cert, | ||||||
|  |       }; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return null; | ||||||
|  | } | ||||||
							
								
								
									
										112
									
								
								src/tools/ssl-cert-converter/ssl-cert-converter.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/tools/ssl-cert-converter/ssl-cert-converter.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,112 @@ | |||||||
|  | <script setup lang="ts"> | ||||||
|  | import { Buffer } from 'node:buffer'; | ||||||
|  | import { convertCertificate } from './ssl-cert-converter.service'; | ||||||
|  | 
 | ||||||
|  | const inputKeyOrCertificate = ref(''); | ||||||
|  | const fileInput = ref() as Ref<Buffer>; | ||||||
|  | const passphrase = ref(''); | ||||||
|  | const inputType = ref<'file' | 'content'>('file'); | ||||||
|  | 
 | ||||||
|  | async function onUpload(file: File) { | ||||||
|  |   if (file) { | ||||||
|  |     fileInput.value = Buffer.from(await file.arrayBuffer()); | ||||||
|  |     inputKeyOrCertificate.value = ''; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function downloadFile(data: ArrayBuffer | string, fileName: string, fileType?: string) { | ||||||
|  |   const blob = new Blob( | ||||||
|  |     [typeof data === 'string' ? new TextEncoder().encode(data) : data], | ||||||
|  |     { type: fileType || 'application/octet-stream' }); | ||||||
|  |   const downloadUrl = URL.createObjectURL(blob); | ||||||
|  |   const a = document.createElement('a'); | ||||||
|  |   a.href = downloadUrl; | ||||||
|  |   a.download = fileName; | ||||||
|  |   document.body.appendChild(a); | ||||||
|  |   a.click(); | ||||||
|  |   URL.revokeObjectURL(downloadUrl); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const convertedCertificates = computed(() => { | ||||||
|  |   const inputContent = inputKeyOrCertificate.value; | ||||||
|  |   const file = fileInput.value; | ||||||
|  |   let inputKeyOrCertificateValue: string | Buffer = ''; | ||||||
|  |   if (inputType.value === 'file' && file) { | ||||||
|  |     inputKeyOrCertificateValue = file; | ||||||
|  |   } | ||||||
|  |   else if (inputType.value === 'content' && inputContent) { | ||||||
|  |     inputKeyOrCertificateValue = inputContent; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return convertCertificate(inputKeyOrCertificateValue, passphrase.value); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <c-card> | ||||||
|  |       <n-radio-group v-model:value="inputType" name="radiogroup" mb-2 flex justify-center> | ||||||
|  |         <n-space> | ||||||
|  |           <n-radio | ||||||
|  |             value="file" | ||||||
|  |             label="File" | ||||||
|  |           /> | ||||||
|  |           <n-radio | ||||||
|  |             value="content" | ||||||
|  |             label="Content" | ||||||
|  |           /> | ||||||
|  |         </n-space> | ||||||
|  |       </n-radio-group> | ||||||
|  | 
 | ||||||
|  |       <c-file-upload | ||||||
|  |         v-if="inputType === 'file'" | ||||||
|  |         title="Drag and drop a PEM, DER, JKS or PKCS#12 file here, or click to select a file" | ||||||
|  |         @file-upload="onUpload" | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       <c-input-text | ||||||
|  |         v-if="inputType === 'content'" | ||||||
|  |         v-model:value="inputKeyOrCertificate" | ||||||
|  |         label="Paste your Certificate/Store:" | ||||||
|  |         placeholder="Your Certificate/Store..." | ||||||
|  |         multiline | ||||||
|  |         rows="8" | ||||||
|  |         data-test-id="input" | ||||||
|  |       /> | ||||||
|  |     </c-card> | ||||||
|  | 
 | ||||||
|  |     <c-input-text | ||||||
|  |       v-model:value="passphrase" | ||||||
|  |       label="Passphrase (for encrypted certificate/store):" | ||||||
|  |       placeholder="Passphrase (for encrypted certificate/store)..." | ||||||
|  |       type="password" | ||||||
|  |       data-test-id="pass" | ||||||
|  |     /> | ||||||
|  | 
 | ||||||
|  |     <n-divider /> | ||||||
|  | 
 | ||||||
|  |     <c-alert v-if="!convertedCertificates"> | ||||||
|  |       Please provide an input or enter the good password! | ||||||
|  |     </c-alert> | ||||||
|  | 
 | ||||||
|  |     <c-card v-for="(cert, ix) in convertedCertificates" :key="ix" :title="cert.alias"> | ||||||
|  |       <n-form-item v-if="cert.key" label="Key (PEM)"> | ||||||
|  |         <textarea-copyable :value="cert.key" /> | ||||||
|  |       </n-form-item> | ||||||
|  |       <n-form-item v-if="cert.pem" label="Certificate (PEM)"> | ||||||
|  |         <textarea-copyable :value="cert.pem" /> | ||||||
|  |       </n-form-item> | ||||||
|  |       <div flex justify-center gap-1> | ||||||
|  |         <c-button v-if="cert.der" @click="downloadFile(cert.der, `${cert.alias}.der`)"> | ||||||
|  |           Download DER | ||||||
|  |         </c-button> | ||||||
|  |         <c-button v-if="cert.pem" @click="downloadFile(cert.pem, `${cert.alias}.pem`)"> | ||||||
|  |           Download PEM | ||||||
|  |         </c-button> | ||||||
|  |         <c-button v-if="cert.key" @click="downloadFile(cert.key, `${cert.alias}.key.pem`)"> | ||||||
|  |           Download Key (PEM) | ||||||
|  |         </c-button> | ||||||
|  |       </div> | ||||||
|  |     </c-card> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
| @ -15,6 +15,7 @@ import { VitePWA } from 'vite-plugin-pwa'; | |||||||
| import markdown from 'vite-plugin-vue-markdown'; | import markdown from 'vite-plugin-vue-markdown'; | ||||||
| import svgLoader from 'vite-svg-loader'; | import svgLoader from 'vite-svg-loader'; | ||||||
| import { configDefaults } from 'vitest/config'; | import { configDefaults } from 'vitest/config'; | ||||||
|  | import { nodePolyfills } from 'vite-plugin-node-polyfills' | ||||||
| 
 | 
 | ||||||
| const baseUrl = process.env.BASE_URL ?? '/'; | const baseUrl = process.env.BASE_URL ?? '/'; | ||||||
| 
 | 
 | ||||||
| @ -97,6 +98,7 @@ export default defineConfig({ | |||||||
|       resolvers: [NaiveUiResolver(), IconsResolver({ prefix: 'icon' })], |       resolvers: [NaiveUiResolver(), IconsResolver({ prefix: 'icon' })], | ||||||
|     }), |     }), | ||||||
|     Unocss(), |     Unocss(), | ||||||
|  |     nodePolyfills(), | ||||||
|   ], |   ], | ||||||
|   base: baseUrl, |   base: baseUrl, | ||||||
|   resolve: { |   resolve: { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user